Click events, children
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
element::{AnyElement, Element, Layout, ParentElement},
|
||||
element::{AnyElement, Element, IntoElement, Layout, ParentElement},
|
||||
interactive::{InteractionHandlers, Interactive},
|
||||
layout_context::LayoutContext,
|
||||
paint_context::PaintContext,
|
||||
@@ -47,6 +47,8 @@ impl<V: 'static> Element<V> for Div<V> {
|
||||
{
|
||||
self.computed_style()
|
||||
.paint_background(layout.bounds(cx), cx);
|
||||
self.interaction_handlers()
|
||||
.paint(layout.order(cx), layout.bounds(cx), cx);
|
||||
for child in &mut self.children {
|
||||
child.paint(view, cx);
|
||||
}
|
||||
@@ -79,35 +81,10 @@ impl<V: 'static> ParentElement<V> for Div<V> {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
// let elt = div().w_auto();
|
||||
impl<V: 'static> IntoElement<V> for Div<V> {
|
||||
type Element = Self;
|
||||
|
||||
fn into_element(self) -> Self::Element {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
// trait Element<V: 'static> {
|
||||
// type Style;
|
||||
|
||||
// fn layout()
|
||||
// }
|
||||
|
||||
// trait Stylable<V: 'static>: Element<V> {
|
||||
// type Style;
|
||||
|
||||
// fn with_style(self, style: Self::Style) -> Self;
|
||||
// }
|
||||
|
||||
// pub struct HoverStyle<S> {
|
||||
// default: S,
|
||||
// hovered: S,
|
||||
// }
|
||||
|
||||
// struct Hover<V: 'static, C: Stylable<V>> {
|
||||
// child: C,
|
||||
// style: HoverStyle<C::Style>,
|
||||
// }
|
||||
|
||||
// impl<V: 'static, C: Stylable<V>> Hover<V, C> {
|
||||
// fn new(child: C, style: HoverStyle<C::Style>) -> Self {
|
||||
// Self { child, style }
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::{
|
||||
element::{Element, Layout},
|
||||
element::{AnyElement, Element, IntoElement, Layout, ParentElement},
|
||||
interactive::{InteractionHandlers, Interactive},
|
||||
layout_context::LayoutContext,
|
||||
paint_context::PaintContext,
|
||||
style::{Style, StyleHelpers, Styleable},
|
||||
@@ -7,6 +8,7 @@ use crate::{
|
||||
use anyhow::Result;
|
||||
use gpui::platform::MouseMovedEvent;
|
||||
use refineable::{CascadeSlot, Refineable, RefinementCascade};
|
||||
use smallvec::SmallVec;
|
||||
use std::{cell::Cell, rc::Rc};
|
||||
|
||||
pub struct Hoverable<E: Styleable> {
|
||||
@@ -76,3 +78,23 @@ impl<V: 'static, E: Element<V> + Styleable> Element<V> for Hoverable<E> {
|
||||
}
|
||||
|
||||
impl<E: Styleable<Style = Style>> StyleHelpers for Hoverable<E> {}
|
||||
|
||||
impl<V: 'static, E: Interactive<V> + Styleable> Interactive<V> for Hoverable<E> {
|
||||
fn interaction_handlers(&mut self) -> &mut InteractionHandlers<V> {
|
||||
self.child.interaction_handlers()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static, E: ParentElement<V> + Styleable> ParentElement<V> for Hoverable<E> {
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
|
||||
self.child.children_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static, E: Element<V> + Styleable> IntoElement<V> for Hoverable<E> {
|
||||
type Element = Self;
|
||||
|
||||
fn into_element(self) -> Self::Element {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,147 @@
|
||||
use gpui::{platform::MouseMovedEvent, EventContext};
|
||||
use gpui::{
|
||||
geometry::rect::RectF,
|
||||
platform::{MouseButton, MouseButtonEvent},
|
||||
EventContext,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use std::rc::Rc;
|
||||
use std::{cell::Cell, rc::Rc};
|
||||
|
||||
use crate::element::PaintContext;
|
||||
|
||||
pub trait Interactive<V: 'static> {
|
||||
fn interaction_handlers(&mut self) -> &mut InteractionHandlers<V>;
|
||||
|
||||
fn on_mouse_move<H>(mut self, handler: H) -> Self
|
||||
fn on_mouse_down(
|
||||
mut self,
|
||||
button: MouseButton,
|
||||
handler: impl Fn(&mut V, &MouseButtonEvent, &mut EventContext<V>) + 'static,
|
||||
) -> Self
|
||||
where
|
||||
H: 'static + Fn(&mut V, &MouseMovedEvent, bool, &mut EventContext<V>),
|
||||
Self: Sized,
|
||||
{
|
||||
self.interaction_handlers()
|
||||
.mouse_moved
|
||||
.push(Rc::new(move |view, event, hit_test, cx| {
|
||||
handler(view, event, hit_test, cx);
|
||||
cx.bubble
|
||||
}));
|
||||
.mouse_down
|
||||
.push(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
|
||||
fn on_mouse_up(
|
||||
mut self,
|
||||
button: MouseButton,
|
||||
handler: impl Fn(&mut V, &MouseButtonEvent, &mut EventContext<V>) + 'static,
|
||||
) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.interaction_handlers().mouse_up.push(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
|
||||
fn on_mouse_down_out(
|
||||
mut self,
|
||||
button: MouseButton,
|
||||
handler: impl Fn(&mut V, &MouseButtonEvent, &mut EventContext<V>) + 'static,
|
||||
) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.interaction_handlers()
|
||||
.mouse_down_out
|
||||
.push(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
|
||||
fn on_mouse_up_out(
|
||||
mut self,
|
||||
button: MouseButton,
|
||||
handler: impl Fn(&mut V, &MouseButtonEvent, &mut EventContext<V>) + 'static,
|
||||
) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.interaction_handlers()
|
||||
.mouse_up_out
|
||||
.push(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
|
||||
fn on_click(
|
||||
self,
|
||||
button: MouseButton,
|
||||
handler: impl Fn(&mut V, &MouseButtonEvent, &mut EventContext<V>) + 'static,
|
||||
) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let pressed = Rc::new(Cell::new(false));
|
||||
self.on_mouse_down(button, {
|
||||
let pressed = pressed.clone();
|
||||
move |_, _, _| {
|
||||
pressed.set(true);
|
||||
}
|
||||
})
|
||||
.on_mouse_up_out(button, {
|
||||
let pressed = pressed.clone();
|
||||
move |_, _, _| {
|
||||
pressed.set(false);
|
||||
}
|
||||
})
|
||||
.on_mouse_up(button, move |view, event, cx| {
|
||||
if pressed.get() {
|
||||
pressed.set(false);
|
||||
handler(view, event, cx);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct InteractionHandlers<V: 'static> {
|
||||
mouse_moved:
|
||||
SmallVec<[Rc<dyn Fn(&mut V, &MouseMovedEvent, bool, &mut EventContext<V>) -> bool>; 2]>,
|
||||
mouse_down: SmallVec<[Rc<dyn Fn(&mut V, &MouseButtonEvent, &mut EventContext<V>)>; 2]>,
|
||||
mouse_down_out: SmallVec<[Rc<dyn Fn(&mut V, &MouseButtonEvent, &mut EventContext<V>)>; 2]>,
|
||||
mouse_up: SmallVec<[Rc<dyn Fn(&mut V, &MouseButtonEvent, &mut EventContext<V>)>; 2]>,
|
||||
mouse_up_out: SmallVec<[Rc<dyn Fn(&mut V, &MouseButtonEvent, &mut EventContext<V>)>; 2]>,
|
||||
}
|
||||
|
||||
impl<V: 'static> InteractionHandlers<V> {
|
||||
pub fn paint(&self, order: u32, bounds: RectF, cx: &mut PaintContext<V>) {
|
||||
for handler in self.mouse_down.iter().cloned() {
|
||||
cx.on_event(order, move |view, event: &MouseButtonEvent, cx| {
|
||||
if event.is_down && bounds.contains_point(event.position) {
|
||||
handler(view, event, cx);
|
||||
}
|
||||
})
|
||||
}
|
||||
for handler in self.mouse_up.iter().cloned() {
|
||||
cx.on_event(order, move |view, event: &MouseButtonEvent, cx| {
|
||||
if !event.is_down && bounds.contains_point(event.position) {
|
||||
handler(view, event, cx);
|
||||
}
|
||||
})
|
||||
}
|
||||
for handler in self.mouse_down_out.iter().cloned() {
|
||||
cx.on_event(order, move |view, event: &MouseButtonEvent, cx| {
|
||||
if event.is_down && !bounds.contains_point(event.position) {
|
||||
handler(view, event, cx);
|
||||
}
|
||||
})
|
||||
}
|
||||
for handler in self.mouse_up_out.iter().cloned() {
|
||||
cx.on_event(order, move |view, event: &MouseButtonEvent, cx| {
|
||||
if !event.is_down && !bounds.contains_point(event.position) {
|
||||
handler(view, event, cx);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Default for InteractionHandlers<V> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
mouse_moved: Default::default(),
|
||||
mouse_down: Default::default(),
|
||||
mouse_up: Default::default(),
|
||||
mouse_down_out: Default::default(),
|
||||
mouse_up_out: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ impl<'a, 'b, 'c, 'd, V: 'static> PaintContext<'a, 'b, 'c, 'd, V> {
|
||||
pub fn on_event<E: 'static>(
|
||||
&mut self,
|
||||
order: u32,
|
||||
handler: impl Fn(&mut V, &E, &mut ViewContext<V>) + 'static,
|
||||
handler: impl Fn(&mut V, &E, &mut EventContext<V>) + 'static,
|
||||
) {
|
||||
let view = self.weak_handle();
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#![allow(dead_code, unused_variables)]
|
||||
use crate::{
|
||||
color::black,
|
||||
element::ParentElement,
|
||||
style::{StyleHelpers, Styleable},
|
||||
};
|
||||
use element::Element;
|
||||
@@ -59,7 +60,14 @@ fn playground<V: 'static>(theme: &ThemeColors) -> impl Element<V> {
|
||||
.fill(theme.error(0.5))
|
||||
.pressed()
|
||||
.fill(theme.warning(0.5))
|
||||
// .child(button().label("Hello").click(|_, _, _| println!("click!")))
|
||||
.child(
|
||||
div()
|
||||
.h_6()
|
||||
.w_6()
|
||||
.absolute()
|
||||
.bottom_0()
|
||||
.fill(theme.success(0.)),
|
||||
)
|
||||
}
|
||||
|
||||
// todo!()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::{
|
||||
element::{Element, Layout},
|
||||
element::{AnyElement, Element, IntoElement, Layout, ParentElement},
|
||||
interactive::{InteractionHandlers, Interactive},
|
||||
layout_context::LayoutContext,
|
||||
paint_context::PaintContext,
|
||||
style::{Style, StyleHelpers, Styleable},
|
||||
@@ -7,6 +8,7 @@ use crate::{
|
||||
use anyhow::Result;
|
||||
use gpui::platform::MouseButtonEvent;
|
||||
use refineable::{CascadeSlot, Refineable, RefinementCascade};
|
||||
use smallvec::SmallVec;
|
||||
use std::{cell::Cell, rc::Rc};
|
||||
|
||||
pub struct Pressable<E: Styleable> {
|
||||
@@ -79,3 +81,23 @@ impl<V: 'static, E: Element<V> + Styleable> Element<V> for Pressable<E> {
|
||||
}
|
||||
|
||||
impl<E: Styleable<Style = Style>> StyleHelpers for Pressable<E> {}
|
||||
|
||||
impl<V: 'static, E: Interactive<V> + Styleable> Interactive<V> for Pressable<E> {
|
||||
fn interaction_handlers(&mut self) -> &mut InteractionHandlers<V> {
|
||||
self.child.interaction_handlers()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static, E: ParentElement<V> + Styleable> ParentElement<V> for Pressable<E> {
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
|
||||
self.child.children_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static, E: Element<V> + Styleable> IntoElement<V> for Pressable<E> {
|
||||
type Element = Self;
|
||||
|
||||
fn into_element(self) -> Self::Element {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,6 +274,22 @@ pub trait Styleable {
|
||||
pub trait StyleHelpers: Styleable<Style = Style> {
|
||||
styleable_helpers!();
|
||||
|
||||
fn relative(mut self) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.declared_style().position = Some(Position::Relative);
|
||||
self
|
||||
}
|
||||
|
||||
fn absolute(mut self) -> Self
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
self.declared_style().position = Some(Position::Absolute);
|
||||
self
|
||||
}
|
||||
|
||||
fn fill<F>(mut self, fill: F) -> Self
|
||||
where
|
||||
F: Into<Fill>,
|
||||
|
||||
Reference in New Issue
Block a user