Detailed changes
@@ -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();
-}
-
-// trait Element<V: 'static> {
-// type Style;
-
-// fn layout()
-// }
-
-// trait Stylable<V: 'static>: Element<V> {
-// type Style;
-
-// fn with_style(self, style: Self::Style) -> Self;
-// }
+impl<V: 'static> IntoElement<V> for Div<V> {
+ type Element = 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 }
-// }
-// }
+ fn into_element(self) -> Self::Element {
+ self
+ }
+}
@@ -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>,