Click events, children

This commit is contained in:
Nathan Sobo
2023-08-23 16:02:56 -06:00
parent 8e3b23e510
commit 4c000379d2
7 changed files with 206 additions and 48 deletions
+9 -32
View File
@@ -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 }
// }
// }
+23 -1
View File
@@ -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
}
}
+125 -12
View File
@@ -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(),
}
}
}
+1 -1
View File
@@ -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();
+9 -1
View File
@@ -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!()
+23 -1
View File
@@ -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
}
}
+16
View File
@@ -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>,