From aec7955ccf26ee456f5a140c6a678785e864dc10 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 13 Nov 2023 16:40:29 -0700 Subject: [PATCH 01/23] Checkpoint --- crates/gpui2/docs/contexts.md | 0 crates/gpui2/docs/key_dispatch.md | 101 ++++ crates/gpui2/src/app.rs | 2 +- crates/gpui2/src/elements.rs | 1 + crates/gpui2/src/elements/div.rs | 4 +- crates/gpui2/src/elements/node.rs | 767 ++++++++++++++++++++++++++++++ crates/gpui2/src/style.rs | 2 +- crates/gpui2/src/window.rs | 21 + 8 files changed, 894 insertions(+), 4 deletions(-) create mode 100644 crates/gpui2/docs/contexts.md create mode 100644 crates/gpui2/docs/key_dispatch.md create mode 100644 crates/gpui2/src/elements/node.rs diff --git a/crates/gpui2/docs/contexts.md b/crates/gpui2/docs/contexts.md new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/crates/gpui2/docs/key_dispatch.md b/crates/gpui2/docs/key_dispatch.md new file mode 100644 index 0000000000000000000000000000000000000000..339eb430281b5863b68bda2bd3f71117963adf8e --- /dev/null +++ b/crates/gpui2/docs/key_dispatch.md @@ -0,0 +1,101 @@ +# Key Dispatch + +GPUI is designed for keyboard-first interactivity. + +To expose functionality to the mouse, you render a button with a click handler. + +To expose functionality to the keyboard, you bind an *action* in a *key context*. + +Actions are similar to framework-level events like `MouseDown`, `KeyDown`, etc, but you can define them yourself: + +```rust +mod menu { + #[gpui::action] + struct MoveUp; + + #[gpui::action] + struct MoveDown; +} +``` + +Actions are frequently unit structs, for which we have a macro. The above could also be written: + +```rust +mod menu { + actions!(MoveUp, MoveDown); +} +``` + +Actions can also be more complex types: + +```rust +mod menu { + #[gpui::action] + struct Move { + direction: Direction, + select: bool, + } +} +``` + +To bind actions, chain `on_action` on to your element: + +```rust +impl Render for Menu { + fn render(&mut self, cx: &mut ViewContext) -> impl Component { + div() + .on_action(|this: &mut Menu, move: &MoveUp, cx: &mut ViewContext| { + // ... + }) + .on_action(|this, move: &MoveDown, cx| { + // ... + }) + .children(todo!()) + } +} +``` + +In order to bind keys to actions, you need to declare a *key context* for part of the element tree by calling `key_context`. + +```rust +impl Render for Menu { + fn render(&mut self, cx: &mut ViewContext) -> impl Component { + div() + .key_context("menu") + .on_action(|this: &mut Menu, move: &MoveUp, cx: &mut ViewContext| { + // ... + }) + .on_action(|this, move: &MoveDown, cx| { + // ... + }) + .children(todo!()) + } +} +``` + +Now you can target your context in the keymap. Note how actions are identified in the keymap by their fully-qualified type name. + +```json +{ + "context": "menu", + "bindings": { + "up": "menu::MoveUp", + "down": "menu::MoveDown" + } +} +``` + +If you had opted for the more complex type definition, you'd provide the serialized representation of the action alongside the name: + +```json +{ + "context": "menu", + "bindings": { + "up": ["menu::Move", {direction: "up", select: false}] + "down": ["menu::Move", {direction: "down", select: false}] + "shift-up": ["menu::Move", {direction: "up", select: true}] + "shift-down": ["menu::Move", {direction: "down", select: true}] + } +} + +``` diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index 61c6195d903095105b741caed25e408a49519cf1..1a3d95e761f154966256a1d8b9df92c8450be578 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -1068,7 +1068,7 @@ impl DerefMut for GlobalLease { /// Contains state associated with an active drag operation, started by dragging an element /// within the window or by dragging into the app from the underlying platform. -pub(crate) struct AnyDrag { +pub struct AnyDrag { pub view: AnyView, pub cursor_offset: Point, } diff --git a/crates/gpui2/src/elements.rs b/crates/gpui2/src/elements.rs index eb061f7d34c8e77c1a366123818b253d33620c7a..e0e155fb0390c15faf34c28af0d41d6130c55512 100644 --- a/crates/gpui2/src/elements.rs +++ b/crates/gpui2/src/elements.rs @@ -1,5 +1,6 @@ mod div; mod img; +mod node; mod svg; mod text; mod uniform_list; diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 95c44038ed115ead27a00d2dcd7a10e1fae429dc..080cdc2c4de47ad8f75886670b457fb8d46209b2 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -252,7 +252,7 @@ where cx: &mut ViewContext, ) -> LayoutId { let style = self.compute_style(Bounds::default(), element_state, cx); - style.apply_text_style(cx, |cx| { + style.with_text_style(cx, |cx| { self.with_element_id(cx, |this, _global_id, cx| { let layout_ids = this .children @@ -318,7 +318,7 @@ where ); }); cx.with_z_index(1, |cx| { - style.apply_text_style(cx, |cx| { + style.with_text_style(cx, |cx| { style.apply_overflow(bounds, cx, |cx| { let scroll_offset = element_state.interactive.scroll_offset(); cx.with_element_offset(scroll_offset, |cx| { diff --git a/crates/gpui2/src/elements/node.rs b/crates/gpui2/src/elements/node.rs new file mode 100644 index 0000000000000000000000000000000000000000..ec73af872112983a3766d0eea7efba26c1cd50e5 --- /dev/null +++ b/crates/gpui2/src/elements/node.rs @@ -0,0 +1,767 @@ +use crate::{ + point, Action, AnyDrag, AnyElement, AnyView, AppContext, BorrowWindow, Bounds, ClickEvent, + DispatchPhase, Element, FocusHandle, KeyContext, KeyDownEvent, KeyUpEvent, LayoutId, + MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, Point, Render, + ScrollWheelEvent, SharedString, Style, StyleRefinement, Styled, View, ViewContext, Visibility, +}; +use collections::HashMap; +use refineable::Refineable; +use smallvec::SmallVec; +use std::{ + any::{Any, TypeId}, + marker::PhantomData, + sync::Arc, +}; + +pub struct GroupStyle { + pub group: SharedString, + pub style: StyleRefinement, +} + +pub trait InteractiveComponent { + fn interactivity(&mut self) -> &mut Interactivity; + + fn hover(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self + where + Self: Sized, + { + self.interactivity().hover_style = f(StyleRefinement::default()); + self + } + + fn group_hover( + mut self, + group_name: impl Into, + f: impl FnOnce(StyleRefinement) -> StyleRefinement, + ) -> Self + where + Self: Sized, + { + self.interactivity().group_hover_style = Some(GroupStyle { + group: group_name.into(), + style: f(StyleRefinement::default()), + }); + self + } + + fn on_mouse_down( + mut self, + button: MouseButton, + handler: impl Fn(&mut V, &MouseDownEvent, &mut ViewContext) + 'static, + ) -> Self + where + Self: Sized, + { + self.interactivity().mouse_down_listeners.push(Box::new( + move |view, event, bounds, phase, cx| { + if phase == DispatchPhase::Bubble + && event.button == button + && bounds.contains_point(&event.position) + { + handler(view, event, cx) + } + }, + )); + self + } + + fn on_mouse_up( + mut self, + button: MouseButton, + handler: impl Fn(&mut V, &MouseUpEvent, &mut ViewContext) + 'static, + ) -> Self + where + Self: Sized, + { + self.interactivity().mouse_up_listeners.push(Box::new( + move |view, event, bounds, phase, cx| { + if phase == DispatchPhase::Bubble + && event.button == button + && bounds.contains_point(&event.position) + { + handler(view, event, cx) + } + }, + )); + self + } + + fn on_mouse_down_out( + mut self, + handler: impl Fn(&mut V, &MouseDownEvent, &mut ViewContext) + 'static, + ) -> Self + where + Self: Sized, + { + self.interactivity().mouse_down_listeners.push(Box::new( + move |view, event, bounds, phase, cx| { + if phase == DispatchPhase::Capture && !bounds.contains_point(&event.position) { + handler(view, event, cx) + } + }, + )); + self + } + + fn on_mouse_up_out( + mut self, + button: MouseButton, + handler: impl Fn(&mut V, &MouseUpEvent, &mut ViewContext) + 'static, + ) -> Self + where + Self: Sized, + { + self.interactivity().mouse_up_listeners.push(Box::new( + move |view, event, bounds, phase, cx| { + if phase == DispatchPhase::Capture + && event.button == button + && !bounds.contains_point(&event.position) + { + handler(view, event, cx); + } + }, + )); + self + } + + fn on_mouse_move( + mut self, + handler: impl Fn(&mut V, &MouseMoveEvent, &mut ViewContext) + 'static, + ) -> Self + where + Self: Sized, + { + self.interactivity().mouse_move_listeners.push(Box::new( + move |view, event, bounds, phase, cx| { + if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { + handler(view, event, cx); + } + }, + )); + self + } + + fn on_scroll_wheel( + mut self, + handler: impl Fn(&mut V, &ScrollWheelEvent, &mut ViewContext) + 'static, + ) -> Self + where + Self: Sized, + { + self.interactivity().scroll_wheel_listeners.push(Box::new( + move |view, event, bounds, phase, cx| { + if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { + handler(view, event, cx); + } + }, + )); + self + } + + /// Capture the given action, fires during the capture phase + fn capture_action( + mut self, + listener: impl Fn(&mut V, &A, &mut ViewContext) + 'static, + ) -> Self + where + Self: Sized, + { + self.interactivity().action_listeners.push(( + TypeId::of::(), + Box::new(move |view, action, phase, cx| { + let action = action.downcast_ref().unwrap(); + if phase == DispatchPhase::Capture { + listener(view, action, cx) + } + }), + )); + self + } + + /// Add a listener for the given action, fires during the bubble event phase + fn on_action( + mut self, + listener: impl Fn(&mut V, &A, &mut ViewContext) + 'static, + ) -> Self + where + Self: Sized, + { + self.interactivity().action_listeners.push(( + TypeId::of::(), + Box::new(move |view, action, phase, cx| { + let action = action.downcast_ref().unwrap(); + if phase == DispatchPhase::Bubble { + listener(view, action, cx) + } + }), + )); + self + } + + fn on_key_down( + mut self, + listener: impl Fn(&mut V, &KeyDownEvent, DispatchPhase, &mut ViewContext) + 'static, + ) -> Self + where + Self: Sized, + { + self.interactivity() + .key_down_listeners + .push(Box::new(move |view, event, phase, cx| { + listener(view, event, phase, cx) + })); + self + } + + fn on_key_up( + mut self, + listener: impl Fn(&mut V, &KeyUpEvent, DispatchPhase, &mut ViewContext) + 'static, + ) -> Self + where + Self: Sized, + { + self.interactivity() + .key_up_listeners + .push(Box::new(move |view, event, phase, cx| { + listener(view, event, phase, cx) + })); + self + } + + fn drag_over(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self + where + Self: Sized, + { + self.interactivity() + .drag_over_styles + .push((TypeId::of::(), f(StyleRefinement::default()))); + self + } + + fn group_drag_over( + mut self, + group_name: impl Into, + f: impl FnOnce(StyleRefinement) -> StyleRefinement, + ) -> Self + where + Self: Sized, + { + self.interactivity().group_drag_over_styles.push(( + TypeId::of::(), + GroupStyle { + group: group_name.into(), + style: f(StyleRefinement::default()), + }, + )); + self + } + + fn on_drop( + mut self, + listener: impl Fn(&mut V, View, &mut ViewContext) + 'static, + ) -> Self + where + Self: Sized, + { + self.interactivity().drop_listeners.push(( + TypeId::of::(), + Box::new(move |view, dragged_view, cx| { + listener(view, dragged_view.downcast().unwrap(), cx); + }), + )); + self + } +} + +pub trait StatefulInteractiveComponent { + fn interactivity(&mut self) -> &mut StatefulInteractivity; + + fn active(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self + where + Self: Sized, + { + self.interactivity().active_style = f(StyleRefinement::default()); + self + } + + fn group_active( + mut self, + group_name: impl Into, + f: impl FnOnce(StyleRefinement) -> StyleRefinement, + ) -> Self + where + Self: Sized, + { + self.interactivity().group_active_style = Some(GroupStyle { + group: group_name.into(), + style: f(StyleRefinement::default()), + }); + self + } + + fn on_click( + mut self, + listener: impl Fn(&mut V, &ClickEvent, &mut ViewContext) + 'static, + ) -> Self + where + Self: Sized, + { + self.interactivity() + .click_listeners + .push(Box::new(move |view, event, cx| listener(view, event, cx))); + self + } + + fn on_drag( + mut self, + listener: impl Fn(&mut V, &mut ViewContext) -> View + 'static, + ) -> Self + where + Self: Sized, + W: 'static + Render, + { + debug_assert!( + self.interactivity().drag_listener.is_none(), + "calling on_drag more than once on the same element is not supported" + ); + self.interactivity().drag_listener = + Some(Box::new(move |view_state, cursor_offset, cx| AnyDrag { + view: listener(view_state, cx).into(), + cursor_offset, + })); + self + } + + fn on_hover(mut self, listener: impl 'static + Fn(&mut V, bool, &mut ViewContext)) -> Self + where + Self: Sized, + { + debug_assert!( + self.interactivity().hover_listener.is_none(), + "calling on_hover more than once on the same element is not supported" + ); + self.interactivity().hover_listener = Some(Box::new(listener)); + self + } + + fn tooltip( + mut self, + build_tooltip: impl Fn(&mut V, &mut ViewContext) -> View + 'static, + ) -> Self + where + Self: Sized, + W: 'static + Render, + { + debug_assert!( + self.interactivity().tooltip_builder.is_none(), + "calling tooltip more than once on the same element is not supported" + ); + self.interactivity().tooltip_builder = Some(Arc::new(move |view_state, cx| { + build_tooltip(view_state, cx).into() + })); + + self + } +} + +pub trait FocusableComponent { + fn focusability(&mut self) -> &mut Focusability; + + fn focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self + where + Self: Sized, + { + self.focusability().focus_style = f(StyleRefinement::default()); + self + } + + fn focus_in(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self + where + Self: Sized, + { + self.focusability().focus_in_style = f(StyleRefinement::default()); + self + } + + fn in_focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self + where + Self: Sized, + { + // self.focusability(). (f(StyleRefinement::default())); + self + } + + fn on_focus( + mut self, + listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext) + 'static, + ) -> Self + where + Self: Sized, + { + self.focusability() + .focus_listeners + .push(Box::new(move |view, focus_handle, event, cx| { + if event.focused.as_ref() == Some(focus_handle) { + listener(view, event, cx) + } + })); + self + } + + fn on_blur( + mut self, + listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext) + 'static, + ) -> Self + where + Self: Sized, + { + self.focusability() + .focus_listeners + .push(Box::new(move |view, focus_handle, event, cx| { + if event.blurred.as_ref() == Some(focus_handle) { + listener(view, event, cx) + } + })); + self + } + + fn on_focus_in( + mut self, + listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext) + 'static, + ) -> Self + where + Self: Sized, + { + self.focusability() + .focus_listeners + .push(Box::new(move |view, focus_handle, event, cx| { + let descendant_blurred = event + .blurred + .as_ref() + .map_or(false, |blurred| focus_handle.contains(blurred, cx)); + let descendant_focused = event + .focused + .as_ref() + .map_or(false, |focused| focus_handle.contains(focused, cx)); + + if !descendant_blurred && descendant_focused { + listener(view, event, cx) + } + })); + self + } + + fn on_focus_out( + mut self, + listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext) + 'static, + ) -> Self + where + Self: Sized, + { + self.focusability() + .focus_listeners + .push(Box::new(move |view, focus_handle, event, cx| { + let descendant_blurred = event + .blurred + .as_ref() + .map_or(false, |blurred| focus_handle.contains(blurred, cx)); + let descendant_focused = event + .focused + .as_ref() + .map_or(false, |focused| focus_handle.contains(focused, cx)); + if descendant_blurred && !descendant_focused { + listener(view, event, cx) + } + })); + self + } +} + +pub type FocusListeners = SmallVec<[FocusListener; 2]>; + +pub type FocusListener = + Box) + 'static>; + +pub type MouseDownListener = Box< + dyn Fn(&mut V, &MouseDownEvent, &Bounds, DispatchPhase, &mut ViewContext) + 'static, +>; +pub type MouseUpListener = Box< + dyn Fn(&mut V, &MouseUpEvent, &Bounds, DispatchPhase, &mut ViewContext) + 'static, +>; + +pub type MouseMoveListener = Box< + dyn Fn(&mut V, &MouseMoveEvent, &Bounds, DispatchPhase, &mut ViewContext) + 'static, +>; + +pub type ScrollWheelListener = Box< + dyn Fn(&mut V, &ScrollWheelEvent, &Bounds, DispatchPhase, &mut ViewContext) + + 'static, +>; + +pub type ClickListener = Box) + 'static>; + +pub type DragListener = + Box, &mut ViewContext) -> AnyDrag + 'static>; + +type DropListener = dyn Fn(&mut V, AnyView, &mut ViewContext) + 'static; + +pub type HoverListener = Box) + 'static>; + +pub type TooltipBuilder = Arc) -> AnyView + 'static>; + +pub type KeyDownListener = + Box) + 'static>; + +pub type KeyUpListener = + Box) + 'static>; + +pub type ActionListener = + Box) + 'static>; + +pub struct FocusEvent { + pub blurred: Option, + pub focused: Option, +} + +pub struct Node { + style: StyleRefinement, + key_context: KeyContext, + interactivity: Interactivity, + children: Vec>, +} + +pub struct Interactivity { + group: Option, + pub dispatch_context: KeyContext, + pub mouse_down_listeners: SmallVec<[MouseDownListener; 2]>, + pub mouse_up_listeners: SmallVec<[MouseUpListener; 2]>, + pub mouse_move_listeners: SmallVec<[MouseMoveListener; 2]>, + pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener; 2]>, + pub key_down_listeners: SmallVec<[KeyDownListener; 2]>, + pub key_up_listeners: SmallVec<[KeyUpListener; 2]>, + pub action_listeners: SmallVec<[(TypeId, ActionListener); 8]>, + pub hover_style: StyleRefinement, + pub group_hover_style: Option, + drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>, + group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>, + drop_listeners: SmallVec<[(TypeId, Box>); 2]>, + scroll_offset: Point, +} + +impl Node { + fn compute_style(&self) -> Style { + let mut style = Style::default(); + style.refine(&self.style); + style + } +} + +impl Styled for Node { + fn style(&mut self) -> &mut StyleRefinement { + &mut self.style + } +} + +impl InteractiveComponent for Node { + fn interactivity(&mut self) -> &mut Interactivity { + &mut self.interactivity + } +} + +pub struct NodeState { + child_layout_ids: SmallVec<[LayoutId; 4]>, +} + +impl Element for Node { + type ElementState = NodeState; + + fn id(&self) -> Option { + None + } + + fn initialize( + &mut self, + view_state: &mut V, + _: Option, + cx: &mut ViewContext, + ) -> Self::ElementState { + for child in &mut self.children { + child.initialize(view_state, cx); + } + NodeState { + child_layout_ids: SmallVec::new(), + } + } + + fn layout( + &mut self, + view_state: &mut V, + element_state: &mut Self::ElementState, + cx: &mut ViewContext, + ) -> crate::LayoutId { + let style = self.compute_style(); + style.with_text_style(cx, |cx| { + element_state.child_layout_ids = self + .children + .iter_mut() + .map(|child| child.layout(view_state, cx)) + .collect::>(); + cx.request_layout(&style, element_state.child_layout_ids.iter().copied()) + }) + } + + fn paint( + &mut self, + bounds: Bounds, + view_state: &mut V, + element_state: &mut Self::ElementState, + cx: &mut ViewContext, + ) { + let style = self.compute_style(); + if style.visibility == Visibility::Hidden { + return; + } + + if let Some(mouse_cursor) = style.mouse_cursor { + let hovered = bounds.contains_point(&cx.mouse_position()); + if hovered { + cx.set_cursor_style(mouse_cursor); + } + } + + if let Some(group) = self.interactivity.group.clone() { + GroupBounds::push(group, bounds, cx); + } + + let z_index = style.z_index.unwrap_or(0); + + let mut child_min = point(Pixels::MAX, Pixels::MAX); + let mut child_max = Point::default(); + + let content_size = if element_state.child_layout_ids.is_empty() { + bounds.size + } else { + for child_layout_id in &element_state.child_layout_ids { + let child_bounds = cx.layout_bounds(*child_layout_id); + child_min = child_min.min(&child_bounds.origin); + child_max = child_max.max(&child_bounds.lower_right()); + } + (child_max - child_min).into() + }; + + cx.with_z_index(z_index, |cx| { + cx.with_z_index(0, |cx| { + style.paint(bounds, cx); + }); + cx.with_z_index(1, |cx| { + style.with_text_style(cx, |cx| { + style.apply_overflow(bounds, cx, |cx| { + let scroll_offset = self.interactivity.scroll_offset; + cx.with_element_offset2(scroll_offset, |cx| { + for child in &mut self.children { + child.paint(view_state, cx); + } + }); + }) + }) + }); + }); + + if let Some(group) = self.interactivity.group.as_ref() { + GroupBounds::pop(group, cx); + } + } +} + +#[derive(Default)] +pub struct GroupBounds(HashMap; 1]>>); + +impl GroupBounds { + pub fn get(name: &SharedString, cx: &mut AppContext) -> Option> { + cx.default_global::() + .0 + .get(name) + .and_then(|bounds_stack| bounds_stack.last()) + .cloned() + } + + pub fn push(name: SharedString, bounds: Bounds, cx: &mut AppContext) { + cx.default_global::() + .0 + .entry(name) + .or_default() + .push(bounds); + } + + pub fn pop(name: &SharedString, cx: &mut AppContext) { + cx.default_global::().0.get_mut(name).unwrap().pop(); + } +} + +pub struct Focusable { + focusability: Focusability, + view_type: PhantomData, + element: E, +} + +pub struct Focusability { + focus_handle: Option, + focus_listeners: FocusListeners, + focus_style: StyleRefinement, + focus_in_style: StyleRefinement, + in_focus_style: StyleRefinement, +} + +impl FocusableComponent for Focusable { + fn focusability(&mut self) -> &mut Focusability { + &mut self.focusability + } +} + +impl> InteractiveComponent for Focusable { + fn interactivity(&mut self) -> &mut Interactivity { + self.element.interactivity() + } +} + +impl> StatefulInteractiveComponent + for Focusable +{ + fn interactivity(&mut self) -> &mut StatefulInteractivity { + self.element.interactivity() + } +} + +pub struct Stateful { + id: SharedString, + interactivity: StatefulInteractivity, + view_type: PhantomData, + element: E, +} + +pub struct StatefulInteractivity { + click_listeners: SmallVec<[ClickListener; 2]>, + active_style: StyleRefinement, + group_active_style: Option, + drag_listener: Option>, + hover_listener: Option>, + tooltip_builder: Option>, +} + +impl StatefulInteractiveComponent for Stateful { + fn interactivity(&mut self) -> &mut StatefulInteractivity { + &mut self.interactivity + } +} + +impl> InteractiveComponent for Stateful { + fn interactivity(&mut self) -> &mut Interactivity { + self.element.interactivity() + } +} + +impl> FocusableComponent for Stateful { + fn focusability(&mut self) -> &mut Focusability { + self.element.focusability() + } +} diff --git a/crates/gpui2/src/style.rs b/crates/gpui2/src/style.rs index 664cc61f8a1bf100678bc13d2cf796019380f9e5..18b92c0b8b7ae8f0bfe83a7f45d56e5b92fe5e51 100644 --- a/crates/gpui2/src/style.rs +++ b/crates/gpui2/src/style.rs @@ -228,7 +228,7 @@ impl Style { } } - pub fn apply_text_style(&self, cx: &mut C, f: F) -> R + pub fn with_text_style(&self, cx: &mut C, f: F) -> R where C: BorrowAppContext, F: FnOnce(&mut C) -> R, diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 4a7241a5c52f0238f50679b5d25005d35cda35c0..52c5464e4fe77b5a76a0de922208744e06c5be00 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -1587,6 +1587,27 @@ pub trait BorrowWindow: BorrowMut + BorrowMut { result } + /// Update the global element offset based on the given offset. This is used to implement + /// scrolling and position drag handles. + fn with_element_offset2( + &mut self, + offset: Point, + f: impl FnOnce(&mut Self) -> R, + ) -> R { + if offset.is_zero() { + return f(self); + }; + + let offset = self.element_offset() + offset; + self.window_mut() + .current_frame + .element_offset_stack + .push(offset); + let result = f(self); + self.window_mut().current_frame.element_offset_stack.pop(); + result + } + /// Obtain the current element offset. fn element_offset(&self) -> Point { self.window() From 76754c559ccfad91c8c1bb785462c637a780cc56 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 13 Nov 2023 18:18:25 -0700 Subject: [PATCH 02/23] WIP --- crates/editor2/src/element.rs | 9 ++ crates/gpui2/src/element.rs | 53 +++++++ crates/gpui2/src/elements/div.rs | 12 +- crates/gpui2/src/elements/img.rs | 9 ++ crates/gpui2/src/elements/node.rs | 172 +++++++++++++++++++--- crates/gpui2/src/elements/svg.rs | 9 ++ crates/gpui2/src/elements/text.rs | 9 ++ crates/gpui2/src/elements/uniform_list.rs | 12 +- crates/gpui2/src/interactive.rs | 2 +- crates/gpui2/src/view.rs | 29 ++++ crates/ui2/src/components/modal.rs | 2 +- 11 files changed, 296 insertions(+), 22 deletions(-) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index f8386ee271e658148d7edb9b32fec5c67a044443..38ec0f3d11e3a1f3258d66c066ff8a7c906cee48 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -2640,6 +2640,15 @@ impl Element for EditorElement { cx.request_layout(&style, None) } + fn prepaint( + &mut self, + bounds: Bounds, + view_state: &mut Editor, + element_state: &mut Self::ElementState, + cx: &mut ViewContext, + ) { + } + fn paint( &mut self, bounds: Bounds, diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index 9ee9eaa7c335960f3e3c6974b0a8798c3d13f9c4..1dc9c155eb7501daeb949b106641eca8abe1a733 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -26,6 +26,14 @@ pub trait Element { cx: &mut ViewContext, ) -> LayoutId; + fn prepaint( + &mut self, + bounds: Bounds, + view_state: &mut V, + element_state: &mut Self::ElementState, + cx: &mut ViewContext, + ); + fn paint( &mut self, bounds: Bounds, @@ -62,6 +70,7 @@ pub trait ParentElement { trait ElementObject { fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext); fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext) -> LayoutId; + fn prepaint(&mut self, view_state: &mut V, cx: &mut ViewContext); fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext); fn measure( &mut self, @@ -199,6 +208,36 @@ where }; } + fn prepaint(&mut self, view_state: &mut V, cx: &mut ViewContext) { + self.phase = match mem::take(&mut self.phase) { + ElementRenderPhase::LayoutRequested { + layout_id, + mut frame_state, + } + | ElementRenderPhase::LayoutComputed { + layout_id, + mut frame_state, + .. + } => { + let bounds = cx.layout_bounds(layout_id); + if let Some(id) = self.element.id() { + cx.with_element_state(id, |element_state, cx| { + let mut element_state = element_state.unwrap(); + self.element + .prepaint(bounds, view_state, &mut element_state, cx); + ((), element_state) + }); + } else { + self.element + .prepaint(bounds, view_state, frame_state.as_mut().unwrap(), cx); + } + ElementRenderPhase::Painted + } + + _ => panic!("must call layout before paint"), + }; + } + fn measure( &mut self, available_space: Size, @@ -283,6 +322,10 @@ impl AnyElement { self.0.paint(view_state, cx) } + pub fn prepaint(&mut self, view_state: &mut V, cx: &mut ViewContext) { + self.0.prepaint(view_state, cx) + } + /// Initializes this element and performs layout within the given available space to determine its size. pub fn measure( &mut self, @@ -376,6 +419,16 @@ where rendered_element.layout(view_state, cx) } + fn prepaint( + &mut self, + _bounds: Bounds, + view_state: &mut V, + rendered_element: &mut Self::ElementState, + cx: &mut ViewContext, + ) { + rendered_element.prepaint(view_state, cx) + } + fn paint( &mut self, _bounds: Bounds, diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 080cdc2c4de47ad8f75886670b457fb8d46209b2..1211a6bc12a0faac992d4b4d2936ba339ccf8462 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -265,6 +265,16 @@ where }) } + fn prepaint( + &mut self, + bounds: Bounds, + view_state: &mut V, + element_state: &mut Self::ElementState, + cx: &mut ViewContext, + ) { + todo!() + } + fn paint( &mut self, bounds: Bounds, @@ -309,7 +319,7 @@ where cx.with_z_index(0, |cx| { style.paint(bounds, cx); this.key_dispatch.paint(bounds, cx); - this.interactivity.paint( + this.interactivity.handle_events( bounds, content_size, style.overflow, diff --git a/crates/gpui2/src/elements/img.rs b/crates/gpui2/src/elements/img.rs index 1ff088c1afc4a2098dc2ba41e37d0ae2ff6eef55..137dde7dfed2a17398edaf0c848b1437f42270d5 100644 --- a/crates/gpui2/src/elements/img.rs +++ b/crates/gpui2/src/elements/img.rs @@ -94,6 +94,15 @@ where self.base.layout(view_state, element_state, cx) } + fn prepaint( + &mut self, + bounds: Bounds, + view_state: &mut V, + element_state: &mut Self::ElementState, + cx: &mut ViewContext, + ) { + } + fn paint( &mut self, bounds: Bounds, diff --git a/crates/gpui2/src/elements/node.rs b/crates/gpui2/src/elements/node.rs index ec73af872112983a3766d0eea7efba26c1cd50e5..bcf3772aed018107929adb767208bd314894acd8 100644 --- a/crates/gpui2/src/elements/node.rs +++ b/crates/gpui2/src/elements/node.rs @@ -10,6 +10,7 @@ use smallvec::SmallVec; use std::{ any::{Any, TypeId}, marker::PhantomData, + mem, sync::Arc, }; @@ -530,24 +531,6 @@ pub struct Node { children: Vec>, } -pub struct Interactivity { - group: Option, - pub dispatch_context: KeyContext, - pub mouse_down_listeners: SmallVec<[MouseDownListener; 2]>, - pub mouse_up_listeners: SmallVec<[MouseUpListener; 2]>, - pub mouse_move_listeners: SmallVec<[MouseMoveListener; 2]>, - pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener; 2]>, - pub key_down_listeners: SmallVec<[KeyDownListener; 2]>, - pub key_up_listeners: SmallVec<[KeyUpListener; 2]>, - pub action_listeners: SmallVec<[(TypeId, ActionListener); 8]>, - pub hover_style: StyleRefinement, - pub group_hover_style: Option, - drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>, - group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>, - drop_listeners: SmallVec<[(TypeId, Box>); 2]>, - scroll_offset: Point, -} - impl Node { fn compute_style(&self) -> Style { let mut style = Style::default(); @@ -610,6 +593,20 @@ impl Element for Node { }) } + fn prepaint( + &mut self, + bounds: Bounds, + view_state: &mut V, + _: &mut Self::ElementState, + cx: &mut ViewContext, + ) { + for child in &mut self.children { + child.prepaint(view_state, cx); + } + self.interactivity + .refine_style(&mut self.style, bounds, view_state, cx); + } + fn paint( &mut self, bounds: Bounds, @@ -652,6 +649,7 @@ impl Element for Node { cx.with_z_index(z_index, |cx| { cx.with_z_index(0, |cx| { style.paint(bounds, cx); + self.interactivity.paint(bounds, cx); }); cx.with_z_index(1, |cx| { style.with_text_style(cx, |cx| { @@ -673,6 +671,144 @@ impl Element for Node { } } +pub struct Interactivity { + pub hover_style: StyleRefinement, + pub group_hover_style: Option, + pub drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>, + pub group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>, + group: Option, + pub dispatch_context: KeyContext, + pub mouse_down_listeners: SmallVec<[MouseDownListener; 2]>, + pub mouse_up_listeners: SmallVec<[MouseUpListener; 2]>, + pub mouse_move_listeners: SmallVec<[MouseMoveListener; 2]>, + pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener; 2]>, + pub key_down_listeners: SmallVec<[KeyDownListener; 2]>, + pub key_up_listeners: SmallVec<[KeyUpListener; 2]>, + pub action_listeners: SmallVec<[(TypeId, ActionListener); 8]>, + drop_listeners: SmallVec<[(TypeId, Box>); 2]>, + scroll_offset: Point, +} + +impl Interactivity { + fn refine_style( + &self, + style: &mut StyleRefinement, + bounds: Bounds, + cx: &mut ViewContext, + ) { + let mouse_position = cx.mouse_position(); + if let Some(group_hover) = self.group_hover_style.as_ref() { + if let Some(group_bounds) = GroupBounds::get(&group_hover.group, cx) { + if group_bounds.contains_point(&mouse_position) { + style.refine(&group_hover.style); + } + } + } + if bounds.contains_point(&mouse_position) { + style.refine(&self.hover_style); + } + + if let Some(drag) = cx.active_drag.take() { + for (state_type, group_drag_style) in &self.group_drag_over_styles { + if let Some(group_bounds) = GroupBounds::get(&group_drag_style.group, cx) { + if *state_type == drag.view.entity_type() + && group_bounds.contains_point(&mouse_position) + { + style.refine(&group_drag_style.style); + } + } + } + + for (state_type, drag_over_style) in &self.drag_over_styles { + if *state_type == drag.view.entity_type() && bounds.contains_point(&mouse_position) + { + style.refine(drag_over_style); + } + } + + cx.active_drag = Some(drag); + } + } + + fn paint(&mut self, bounds: Bounds, cx: &mut ViewContext) { + for listener in self.mouse_down_listeners.drain(..) { + cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| { + listener(state, event, &bounds, phase, cx); + }) + } + + for listener in self.mouse_up_listeners.drain(..) { + cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| { + listener(state, event, &bounds, phase, cx); + }) + } + + for listener in self.mouse_move_listeners.drain(..) { + cx.on_mouse_event(move |state, event: &MouseMoveEvent, phase, cx| { + listener(state, event, &bounds, phase, cx); + }) + } + + for listener in self.scroll_wheel_listeners.drain(..) { + cx.on_mouse_event(move |state, event: &ScrollWheelEvent, phase, cx| { + listener(state, event, &bounds, phase, cx); + }) + } + + let hover_group_bounds = self + .group_hover_style + .as_ref() + .and_then(|group_hover| GroupBounds::get(&group_hover.group, cx)); + + if let Some(group_bounds) = hover_group_bounds { + let hovered = group_bounds.contains_point(&cx.mouse_position()); + cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| { + if phase == DispatchPhase::Capture { + if group_bounds.contains_point(&event.position) != hovered { + cx.notify(); + } + } + }); + } + + if self.hover_style.is_some() + || (cx.active_drag.is_some() && !self.drag_over_styles.is_empty()) + { + let hovered = bounds.contains_point(&cx.mouse_position()); + cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| { + if phase == DispatchPhase::Capture { + if bounds.contains_point(&event.position) != hovered { + cx.notify(); + } + } + }); + } + + if cx.active_drag.is_some() { + let drop_listeners = mem::take(&mut self.drop_listeners); + cx.on_mouse_event(move |view, event: &MouseUpEvent, phase, cx| { + if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { + if let Some(drag_state_type) = + cx.active_drag.as_ref().map(|drag| drag.view.entity_type()) + { + for (drop_state_type, listener) in &drop_listeners { + if *drop_state_type == drag_state_type { + let drag = cx + .active_drag + .take() + .expect("checked for type drag state type above"); + listener(view, drag.view.clone(), cx); + cx.notify(); + cx.stop_propagation(); + } + } + } + } + }); + } + } +} + #[derive(Default)] pub struct GroupBounds(HashMap; 1]>>); diff --git a/crates/gpui2/src/elements/svg.rs b/crates/gpui2/src/elements/svg.rs index bafedb7f2d8469f4c143b59d6f8c743710ebef8e..124c578b28761964bb6e64b7c09c5d7ce15b6d85 100644 --- a/crates/gpui2/src/elements/svg.rs +++ b/crates/gpui2/src/elements/svg.rs @@ -84,6 +84,15 @@ where self.base.layout(view_state, element_state, cx) } + fn prepaint( + &mut self, + bounds: Bounds, + view_state: &mut V, + element_state: &mut Self::ElementState, + cx: &mut ViewContext, + ) { + } + fn paint( &mut self, bounds: Bounds, diff --git a/crates/gpui2/src/elements/text.rs b/crates/gpui2/src/elements/text.rs index 5c5709d32e5a12e247726789a35dfd21806c6c7c..0794ef431adbfbfdc0d77afcf49dca359f72eaaf 100644 --- a/crates/gpui2/src/elements/text.rs +++ b/crates/gpui2/src/elements/text.rs @@ -121,6 +121,15 @@ impl Element for Text { layout_id } + fn prepaint( + &mut self, + bounds: Bounds, + view_state: &mut V, + element_state: &mut Self::ElementState, + cx: &mut ViewContext, + ) { + } + fn paint( &mut self, bounds: Bounds, diff --git a/crates/gpui2/src/elements/uniform_list.rs b/crates/gpui2/src/elements/uniform_list.rs index 6687559d1c811349a3f18a5585f2d2d4110eb16e..16abbcf883a45f5c222de8a53054ede499caa2fa 100644 --- a/crates/gpui2/src/elements/uniform_list.rs +++ b/crates/gpui2/src/elements/uniform_list.rs @@ -152,6 +152,16 @@ impl Element for UniformList { ) } + fn prepaint( + &mut self, + bounds: Bounds, + view_state: &mut V, + element_state: &mut Self::ElementState, + cx: &mut ViewContext, + ) { + todo!() + } + fn paint( &mut self, bounds: crate::Bounds, @@ -229,7 +239,7 @@ impl Element for UniformList { let overflow = point(style.overflow.x, Overflow::Scroll); cx.with_z_index(0, |cx| { - self.interactivity.paint( + self.interactivity.handle_events( bounds, content_size, overflow, diff --git a/crates/gpui2/src/interactive.rs b/crates/gpui2/src/interactive.rs index aacaeac01ff0dd60dfc096d04a82fb2029704874..f896bfc439c1c09c58a281d9e900a60e3589004f 100644 --- a/crates/gpui2/src/interactive.rs +++ b/crates/gpui2/src/interactive.rs @@ -450,7 +450,7 @@ pub trait ElementInteractivity: 'static { } } - fn paint( + fn handle_events( &mut self, bounds: Bounds, content_size: Size, diff --git a/crates/gpui2/src/view.rs b/crates/gpui2/src/view.rs index d12d84f43b424f83c5785d7dd0b33c776054bbb3..9b2a06191f66e257387a9f0a1a5710d94c438e2d 100644 --- a/crates/gpui2/src/view.rs +++ b/crates/gpui2/src/view.rs @@ -147,6 +147,7 @@ pub struct AnyView { model: AnyModel, initialize: fn(&AnyView, &mut WindowContext) -> AnyBox, layout: fn(&AnyView, &mut AnyBox, &mut WindowContext) -> LayoutId, + prepaint: fn(&AnyView, &mut AnyBox, &mut WindowContext), paint: fn(&AnyView, &mut AnyBox, &mut WindowContext), } @@ -156,6 +157,7 @@ impl AnyView { model: self.model.downgrade(), initialize: self.initialize, layout: self.layout, + prepaint: self.prepaint, paint: self.paint, } } @@ -167,6 +169,7 @@ impl AnyView { model, initialize: self.initialize, layout: self.layout, + prepaint: self.prepaint, paint: self.paint, }), } @@ -198,6 +201,7 @@ impl From> for AnyView { model: value.model.into_any(), initialize: any_view::initialize::, layout: any_view::layout::, + prepaint: any_view::prepaint::, paint: any_view::paint::, } } @@ -228,6 +232,16 @@ impl Element for AnyView { (self.layout)(self, rendered_element, cx) } + fn prepaint( + &mut self, + bounds: Bounds, + view_state: &mut ParentViewState, + rendered_element: &mut Self::ElementState, + cx: &mut ViewContext, + ) { + (self.prepaint)(self, rendered_element, cx) + } + fn paint( &mut self, _bounds: Bounds, @@ -243,6 +257,7 @@ pub struct AnyWeakView { model: AnyWeakModel, initialize: fn(&AnyView, &mut WindowContext) -> AnyBox, layout: fn(&AnyView, &mut AnyBox, &mut WindowContext) -> LayoutId, + prepaint: fn(&AnyView, &mut AnyBox, &mut WindowContext), paint: fn(&AnyView, &mut AnyBox, &mut WindowContext), } @@ -253,6 +268,7 @@ impl AnyWeakView { model, initialize: self.initialize, layout: self.layout, + prepaint: self.prepaint, paint: self.paint, }) } @@ -264,6 +280,7 @@ impl From> for AnyWeakView { model: view.model.into(), initialize: any_view::initialize::, layout: any_view::layout::, + prepaint: any_view::prepaint::, paint: any_view::paint::, } } @@ -309,6 +326,18 @@ mod any_view { }) } + pub(crate) fn prepaint( + view: &AnyView, + element: &mut Box, + cx: &mut WindowContext, + ) { + cx.with_element_id(view.model.entity_id, |_, cx| { + let view = view.clone().downcast::().unwrap(); + let element = element.downcast_mut::>().unwrap(); + view.update(cx, |view, cx| element.prepaint(view, cx)) + }) + } + pub(crate) fn paint( view: &AnyView, element: &mut Box, diff --git a/crates/ui2/src/components/modal.rs b/crates/ui2/src/components/modal.rs index 75528b5c3460defeb139f7a16d8d311d87a5093b..805bbe95b2b4d4798a380efad6e2bc68f623f3fa 100644 --- a/crates/ui2/src/components/modal.rs +++ b/crates/ui2/src/components/modal.rs @@ -1,4 +1,4 @@ -use gpui::AnyElement; +use gpui::{AnyElement, Pixels}; use smallvec::SmallVec; use crate::{h_stack, prelude::*, v_stack, Button, Icon, IconButton, Label}; From 922bb3195b2f7f3fa83fc6e7fbefb8e95c24d9d9 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 13 Nov 2023 18:58:42 -0700 Subject: [PATCH 03/23] WIP --- crates/editor2/src/element.rs | 9 -- crates/gpui2/src/element.rs | 53 -------- crates/gpui2/src/elements/div.rs | 10 -- crates/gpui2/src/elements/img.rs | 9 -- crates/gpui2/src/elements/node.rs | 154 +++++++++++----------- crates/gpui2/src/elements/svg.rs | 9 -- crates/gpui2/src/elements/text.rs | 9 -- crates/gpui2/src/elements/uniform_list.rs | 10 -- crates/gpui2/src/view.rs | 29 ---- 9 files changed, 78 insertions(+), 214 deletions(-) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 38ec0f3d11e3a1f3258d66c066ff8a7c906cee48..f8386ee271e658148d7edb9b32fec5c67a044443 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -2640,15 +2640,6 @@ impl Element for EditorElement { cx.request_layout(&style, None) } - fn prepaint( - &mut self, - bounds: Bounds, - view_state: &mut Editor, - element_state: &mut Self::ElementState, - cx: &mut ViewContext, - ) { - } - fn paint( &mut self, bounds: Bounds, diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index 1dc9c155eb7501daeb949b106641eca8abe1a733..9ee9eaa7c335960f3e3c6974b0a8798c3d13f9c4 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -26,14 +26,6 @@ pub trait Element { cx: &mut ViewContext, ) -> LayoutId; - fn prepaint( - &mut self, - bounds: Bounds, - view_state: &mut V, - element_state: &mut Self::ElementState, - cx: &mut ViewContext, - ); - fn paint( &mut self, bounds: Bounds, @@ -70,7 +62,6 @@ pub trait ParentElement { trait ElementObject { fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext); fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext) -> LayoutId; - fn prepaint(&mut self, view_state: &mut V, cx: &mut ViewContext); fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext); fn measure( &mut self, @@ -208,36 +199,6 @@ where }; } - fn prepaint(&mut self, view_state: &mut V, cx: &mut ViewContext) { - self.phase = match mem::take(&mut self.phase) { - ElementRenderPhase::LayoutRequested { - layout_id, - mut frame_state, - } - | ElementRenderPhase::LayoutComputed { - layout_id, - mut frame_state, - .. - } => { - let bounds = cx.layout_bounds(layout_id); - if let Some(id) = self.element.id() { - cx.with_element_state(id, |element_state, cx| { - let mut element_state = element_state.unwrap(); - self.element - .prepaint(bounds, view_state, &mut element_state, cx); - ((), element_state) - }); - } else { - self.element - .prepaint(bounds, view_state, frame_state.as_mut().unwrap(), cx); - } - ElementRenderPhase::Painted - } - - _ => panic!("must call layout before paint"), - }; - } - fn measure( &mut self, available_space: Size, @@ -322,10 +283,6 @@ impl AnyElement { self.0.paint(view_state, cx) } - pub fn prepaint(&mut self, view_state: &mut V, cx: &mut ViewContext) { - self.0.prepaint(view_state, cx) - } - /// Initializes this element and performs layout within the given available space to determine its size. pub fn measure( &mut self, @@ -419,16 +376,6 @@ where rendered_element.layout(view_state, cx) } - fn prepaint( - &mut self, - _bounds: Bounds, - view_state: &mut V, - rendered_element: &mut Self::ElementState, - cx: &mut ViewContext, - ) { - rendered_element.prepaint(view_state, cx) - } - fn paint( &mut self, _bounds: Bounds, diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 1211a6bc12a0faac992d4b4d2936ba339ccf8462..25c13d6980f3c8b3e3cdfd80570e603c574e795d 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -265,16 +265,6 @@ where }) } - fn prepaint( - &mut self, - bounds: Bounds, - view_state: &mut V, - element_state: &mut Self::ElementState, - cx: &mut ViewContext, - ) { - todo!() - } - fn paint( &mut self, bounds: Bounds, diff --git a/crates/gpui2/src/elements/img.rs b/crates/gpui2/src/elements/img.rs index 137dde7dfed2a17398edaf0c848b1437f42270d5..1ff088c1afc4a2098dc2ba41e37d0ae2ff6eef55 100644 --- a/crates/gpui2/src/elements/img.rs +++ b/crates/gpui2/src/elements/img.rs @@ -94,15 +94,6 @@ where self.base.layout(view_state, element_state, cx) } - fn prepaint( - &mut self, - bounds: Bounds, - view_state: &mut V, - element_state: &mut Self::ElementState, - cx: &mut ViewContext, - ) { - } - fn paint( &mut self, bounds: Bounds, diff --git a/crates/gpui2/src/elements/node.rs b/crates/gpui2/src/elements/node.rs index bcf3772aed018107929adb767208bd314894acd8..06d4ae2636921d48caa95d3395cb7a452097e0c5 100644 --- a/crates/gpui2/src/elements/node.rs +++ b/crates/gpui2/src/elements/node.rs @@ -274,9 +274,7 @@ pub trait InteractiveComponent { } } -pub trait StatefulInteractiveComponent { - fn interactivity(&mut self) -> &mut StatefulInteractivity; - +pub trait StatefulInteractiveComponent: InteractiveComponent { fn active(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self where Self: Sized, @@ -525,23 +523,14 @@ pub struct FocusEvent { } pub struct Node { - style: StyleRefinement, key_context: KeyContext, interactivity: Interactivity, children: Vec>, } -impl Node { - fn compute_style(&self) -> Style { - let mut style = Style::default(); - style.refine(&self.style); - style - } -} - impl Styled for Node { fn style(&mut self) -> &mut StyleRefinement { - &mut self.style + &mut self.interactivity.base_style } } @@ -582,7 +571,7 @@ impl Element for Node { element_state: &mut Self::ElementState, cx: &mut ViewContext, ) -> crate::LayoutId { - let style = self.compute_style(); + let style = self.interactivity().compute_style(None, cx); style.with_text_style(cx, |cx| { element_state.child_layout_ids = self .children @@ -593,20 +582,6 @@ impl Element for Node { }) } - fn prepaint( - &mut self, - bounds: Bounds, - view_state: &mut V, - _: &mut Self::ElementState, - cx: &mut ViewContext, - ) { - for child in &mut self.children { - child.prepaint(view_state, cx); - } - self.interactivity - .refine_style(&mut self.style, bounds, view_state, cx); - } - fn paint( &mut self, bounds: Bounds, @@ -614,7 +589,7 @@ impl Element for Node { element_state: &mut Self::ElementState, cx: &mut ViewContext, ) { - let style = self.compute_style(); + let style = self.interactivity.compute_style(Some(bounds), cx); if style.visibility == Visibility::Hidden { return; } @@ -671,12 +646,37 @@ impl Element for Node { } } +pub struct ComputedStyle { + base: StyleRefinement, + focus: StyleRefinement, + hover: StyleRefinement, + active: StyleRefinement, +} + +pub struct StyleCascade { + pub base: StyleRefinement, + pub focus: StyleRefinement, + pub hover: StyleRefinement, + pub dragged_over: StyleRefinement, + pub active: StyleRefinement, +} + pub struct Interactivity { + pub active: bool, + pub group_active: bool, + pub hovered: bool, + pub group_hovered: bool, + pub focused: bool, + pub scroll_offset: Point, + pub base_style: StyleRefinement, + pub focus_style: StyleRefinement, pub hover_style: StyleRefinement, pub group_hover_style: Option, + pub active_style: StyleRefinement, + pub group_active_style: Option, pub drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>, pub group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>, - group: Option, + pub group: Option, pub dispatch_context: KeyContext, pub mouse_down_listeners: SmallVec<[MouseDownListener; 2]>, pub mouse_up_listeners: SmallVec<[MouseUpListener; 2]>, @@ -685,49 +685,68 @@ pub struct Interactivity { pub key_down_listeners: SmallVec<[KeyDownListener; 2]>, pub key_up_listeners: SmallVec<[KeyUpListener; 2]>, pub action_listeners: SmallVec<[(TypeId, ActionListener); 8]>, - drop_listeners: SmallVec<[(TypeId, Box>); 2]>, - scroll_offset: Point, + pub drop_listeners: SmallVec<[(TypeId, Box>); 2]>, + pub click_listeners: SmallVec<[ClickListener; 2]>, + pub drag_listener: Option>, + pub hover_listener: Option>, + pub tooltip_builder: Option>, } impl Interactivity { - fn refine_style( - &self, - style: &mut StyleRefinement, - bounds: Bounds, - cx: &mut ViewContext, - ) { - let mouse_position = cx.mouse_position(); - if let Some(group_hover) = self.group_hover_style.as_ref() { - if let Some(group_bounds) = GroupBounds::get(&group_hover.group, cx) { - if group_bounds.contains_point(&mouse_position) { - style.refine(&group_hover.style); + fn compute_style(&self, bounds: Option>, cx: &mut ViewContext) -> Style { + let mut style = Style::default(); + style.refine(&self.base_style); + if self.focused { + style.refine(&self.focus_style); + } + + if let Some(bounds) = bounds { + let mouse_position = cx.mouse_position(); + if let Some(group_hover) = self.group_hover_style.as_ref() { + if let Some(group_bounds) = GroupBounds::get(&group_hover.group, cx) { + if group_bounds.contains_point(&mouse_position) { + style.refine(&group_hover.style); + } } } - } - if bounds.contains_point(&mouse_position) { - style.refine(&self.hover_style); - } + if bounds.contains_point(&mouse_position) { + style.refine(&self.hover_style); + } + + if let Some(drag) = cx.active_drag.take() { + for (state_type, group_drag_style) in &self.group_drag_over_styles { + if let Some(group_bounds) = GroupBounds::get(&group_drag_style.group, cx) { + if *state_type == drag.view.entity_type() + && group_bounds.contains_point(&mouse_position) + { + style.refine(&group_drag_style.style); + } + } + } - if let Some(drag) = cx.active_drag.take() { - for (state_type, group_drag_style) in &self.group_drag_over_styles { - if let Some(group_bounds) = GroupBounds::get(&group_drag_style.group, cx) { + for (state_type, drag_over_style) in &self.drag_over_styles { if *state_type == drag.view.entity_type() - && group_bounds.contains_point(&mouse_position) + && bounds.contains_point(&mouse_position) { - style.refine(&group_drag_style.style); + style.refine(drag_over_style); } } + + cx.active_drag = Some(drag); } + } - for (state_type, drag_over_style) in &self.drag_over_styles { - if *state_type == drag.view.entity_type() && bounds.contains_point(&mouse_position) - { - style.refine(drag_over_style); - } + if self.group_active { + if let Some(group) = self.group_active_style.as_ref() { + style.refine(&group.style) } + } - cx.active_drag = Some(drag); + if self.active { + style.refine(&self.active_style) } + + style } fn paint(&mut self, bounds: Bounds, cx: &mut ViewContext) { @@ -863,32 +882,15 @@ impl> InteractiveComponent for Focusab impl> StatefulInteractiveComponent for Focusable { - fn interactivity(&mut self) -> &mut StatefulInteractivity { - self.element.interactivity() - } } pub struct Stateful { id: SharedString, - interactivity: StatefulInteractivity, view_type: PhantomData, element: E, } -pub struct StatefulInteractivity { - click_listeners: SmallVec<[ClickListener; 2]>, - active_style: StyleRefinement, - group_active_style: Option, - drag_listener: Option>, - hover_listener: Option>, - tooltip_builder: Option>, -} - -impl StatefulInteractiveComponent for Stateful { - fn interactivity(&mut self) -> &mut StatefulInteractivity { - &mut self.interactivity - } -} +impl> StatefulInteractiveComponent for Stateful {} impl> InteractiveComponent for Stateful { fn interactivity(&mut self) -> &mut Interactivity { diff --git a/crates/gpui2/src/elements/svg.rs b/crates/gpui2/src/elements/svg.rs index 124c578b28761964bb6e64b7c09c5d7ce15b6d85..bafedb7f2d8469f4c143b59d6f8c743710ebef8e 100644 --- a/crates/gpui2/src/elements/svg.rs +++ b/crates/gpui2/src/elements/svg.rs @@ -84,15 +84,6 @@ where self.base.layout(view_state, element_state, cx) } - fn prepaint( - &mut self, - bounds: Bounds, - view_state: &mut V, - element_state: &mut Self::ElementState, - cx: &mut ViewContext, - ) { - } - fn paint( &mut self, bounds: Bounds, diff --git a/crates/gpui2/src/elements/text.rs b/crates/gpui2/src/elements/text.rs index 0794ef431adbfbfdc0d77afcf49dca359f72eaaf..5c5709d32e5a12e247726789a35dfd21806c6c7c 100644 --- a/crates/gpui2/src/elements/text.rs +++ b/crates/gpui2/src/elements/text.rs @@ -121,15 +121,6 @@ impl Element for Text { layout_id } - fn prepaint( - &mut self, - bounds: Bounds, - view_state: &mut V, - element_state: &mut Self::ElementState, - cx: &mut ViewContext, - ) { - } - fn paint( &mut self, bounds: Bounds, diff --git a/crates/gpui2/src/elements/uniform_list.rs b/crates/gpui2/src/elements/uniform_list.rs index 16abbcf883a45f5c222de8a53054ede499caa2fa..521df8699a47fb4ec7f0590fcff8f8fee83a0fbf 100644 --- a/crates/gpui2/src/elements/uniform_list.rs +++ b/crates/gpui2/src/elements/uniform_list.rs @@ -152,16 +152,6 @@ impl Element for UniformList { ) } - fn prepaint( - &mut self, - bounds: Bounds, - view_state: &mut V, - element_state: &mut Self::ElementState, - cx: &mut ViewContext, - ) { - todo!() - } - fn paint( &mut self, bounds: crate::Bounds, diff --git a/crates/gpui2/src/view.rs b/crates/gpui2/src/view.rs index 9b2a06191f66e257387a9f0a1a5710d94c438e2d..d12d84f43b424f83c5785d7dd0b33c776054bbb3 100644 --- a/crates/gpui2/src/view.rs +++ b/crates/gpui2/src/view.rs @@ -147,7 +147,6 @@ pub struct AnyView { model: AnyModel, initialize: fn(&AnyView, &mut WindowContext) -> AnyBox, layout: fn(&AnyView, &mut AnyBox, &mut WindowContext) -> LayoutId, - prepaint: fn(&AnyView, &mut AnyBox, &mut WindowContext), paint: fn(&AnyView, &mut AnyBox, &mut WindowContext), } @@ -157,7 +156,6 @@ impl AnyView { model: self.model.downgrade(), initialize: self.initialize, layout: self.layout, - prepaint: self.prepaint, paint: self.paint, } } @@ -169,7 +167,6 @@ impl AnyView { model, initialize: self.initialize, layout: self.layout, - prepaint: self.prepaint, paint: self.paint, }), } @@ -201,7 +198,6 @@ impl From> for AnyView { model: value.model.into_any(), initialize: any_view::initialize::, layout: any_view::layout::, - prepaint: any_view::prepaint::, paint: any_view::paint::, } } @@ -232,16 +228,6 @@ impl Element for AnyView { (self.layout)(self, rendered_element, cx) } - fn prepaint( - &mut self, - bounds: Bounds, - view_state: &mut ParentViewState, - rendered_element: &mut Self::ElementState, - cx: &mut ViewContext, - ) { - (self.prepaint)(self, rendered_element, cx) - } - fn paint( &mut self, _bounds: Bounds, @@ -257,7 +243,6 @@ pub struct AnyWeakView { model: AnyWeakModel, initialize: fn(&AnyView, &mut WindowContext) -> AnyBox, layout: fn(&AnyView, &mut AnyBox, &mut WindowContext) -> LayoutId, - prepaint: fn(&AnyView, &mut AnyBox, &mut WindowContext), paint: fn(&AnyView, &mut AnyBox, &mut WindowContext), } @@ -268,7 +253,6 @@ impl AnyWeakView { model, initialize: self.initialize, layout: self.layout, - prepaint: self.prepaint, paint: self.paint, }) } @@ -280,7 +264,6 @@ impl From> for AnyWeakView { model: view.model.into(), initialize: any_view::initialize::, layout: any_view::layout::, - prepaint: any_view::prepaint::, paint: any_view::paint::, } } @@ -326,18 +309,6 @@ mod any_view { }) } - pub(crate) fn prepaint( - view: &AnyView, - element: &mut Box, - cx: &mut WindowContext, - ) { - cx.with_element_id(view.model.entity_id, |_, cx| { - let view = view.clone().downcast::().unwrap(); - let element = element.downcast_mut::>().unwrap(); - view.update(cx, |view, cx| element.prepaint(view, cx)) - }) - } - pub(crate) fn paint( view: &AnyView, element: &mut Box, From 872b5186e20db43727f9cf055a30d7c9fd0841e5 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 13 Nov 2023 19:23:07 -0700 Subject: [PATCH 04/23] Checkpoint --- crates/gpui2/src/elements/node.rs | 132 ++++++++++++++++++++++-------- 1 file changed, 98 insertions(+), 34 deletions(-) diff --git a/crates/gpui2/src/elements/node.rs b/crates/gpui2/src/elements/node.rs index 06d4ae2636921d48caa95d3395cb7a452097e0c5..7133997c48e95f415d2d4901fcd0744d9c05a301 100644 --- a/crates/gpui2/src/elements/node.rs +++ b/crates/gpui2/src/elements/node.rs @@ -386,7 +386,7 @@ pub trait FocusableComponent { where Self: Sized, { - // self.focusability(). (f(StyleRefinement::default())); + self.focusability().in_focus_style = f(StyleRefinement::default()); self } @@ -523,7 +523,6 @@ pub struct FocusEvent { } pub struct Node { - key_context: KeyContext, interactivity: Interactivity, children: Vec>, } @@ -621,24 +620,27 @@ impl Element for Node { (child_max - child_min).into() }; - cx.with_z_index(z_index, |cx| { - cx.with_z_index(0, |cx| { - style.paint(bounds, cx); - self.interactivity.paint(bounds, cx); - }); - cx.with_z_index(1, |cx| { - style.with_text_style(cx, |cx| { - style.apply_overflow(bounds, cx, |cx| { - let scroll_offset = self.interactivity.scroll_offset; - cx.with_element_offset2(scroll_offset, |cx| { - for child in &mut self.children { - child.paint(view_state, cx); - } - }); + let mut interactivity = mem::take(&mut self.interactivity); + interactivity.paint(bounds, cx, |cx| { + cx.with_z_index(z_index, |cx| { + cx.with_z_index(0, |cx| { + style.paint(bounds, cx); + }); + cx.with_z_index(1, |cx| { + style.with_text_style(cx, |cx| { + style.apply_overflow(bounds, cx, |cx| { + let scroll_offset = self.interactivity.scroll_offset; + cx.with_element_offset2(scroll_offset, |cx| { + for child in &mut self.children { + child.paint(view_state, cx); + } + }); + }) }) - }) + }); }); }); + self.interactivity = interactivity; if let Some(group) = self.interactivity.group.as_ref() { GroupBounds::pop(group, cx); @@ -646,19 +648,15 @@ impl Element for Node { } } -pub struct ComputedStyle { - base: StyleRefinement, - focus: StyleRefinement, - hover: StyleRefinement, - active: StyleRefinement, -} - -pub struct StyleCascade { - pub base: StyleRefinement, - pub focus: StyleRefinement, - pub hover: StyleRefinement, - pub dragged_over: StyleRefinement, - pub active: StyleRefinement, +pub enum FocusState { + /// The current element is not focused, and does not contain or descend from the focused element. + None, + /// The current element is focused. + Focus, + /// The current element contains the focused element + FocusIn, + /// The current element descends from the focused element + InFocus, } pub struct Interactivity { @@ -666,10 +664,14 @@ pub struct Interactivity { pub group_active: bool, pub hovered: bool, pub group_hovered: bool, - pub focused: bool, + pub focus: FocusState, + pub key_context: KeyContext, + pub focus_handle: Option, pub scroll_offset: Point, pub base_style: StyleRefinement, pub focus_style: StyleRefinement, + pub focus_in_style: StyleRefinement, + pub in_focus_style: StyleRefinement, pub hover_style: StyleRefinement, pub group_hover_style: Option, pub active_style: StyleRefinement, @@ -696,8 +698,20 @@ impl Interactivity { fn compute_style(&self, bounds: Option>, cx: &mut ViewContext) -> Style { let mut style = Style::default(); style.refine(&self.base_style); - if self.focused { - style.refine(&self.focus_style); + + match self.focus { + FocusState::None => {} + FocusState::Focus => { + style.refine(&self.focus_style); + style.refine(&self.focus_in_style); + style.refine(&self.in_focus_style); + } + FocusState::FocusIn => { + style.refine(&self.focus_in_style); + } + FocusState::InFocus => { + style.refine(&self.in_focus_style); + } } if let Some(bounds) = bounds { @@ -749,7 +763,12 @@ impl Interactivity { style } - fn paint(&mut self, bounds: Bounds, cx: &mut ViewContext) { + fn paint( + &mut self, + bounds: Bounds, + cx: &mut ViewContext, + f: impl FnOnce(&mut ViewContext), + ) { for listener in self.mouse_down_listeners.drain(..) { cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| { listener(state, event, &bounds, phase, cx); @@ -825,6 +844,51 @@ impl Interactivity { } }); } + + cx.with_key_dispatch( + self.key_context.clone(), + self.focus_handle.clone(), + |_, cx| f(cx), + ); + } +} + +impl Default for Interactivity { + fn default() -> Self { + Self { + active: false, + group_active: false, + hovered: false, + group_hovered: false, + focus: FocusState::None, + key_context: KeyContext::default(), + focus_handle: None, + scroll_offset: Point::default(), + base_style: StyleRefinement::default(), + focus_style: StyleRefinement::default(), + focus_in_style: StyleRefinement::default(), + in_focus_style: StyleRefinement::default(), + hover_style: StyleRefinement::default(), + group_hover_style: None, + active_style: StyleRefinement::default(), + group_active_style: None, + drag_over_styles: SmallVec::new(), + group_drag_over_styles: SmallVec::new(), + group: None, + dispatch_context: KeyContext::default(), + mouse_down_listeners: SmallVec::new(), + mouse_up_listeners: SmallVec::new(), + mouse_move_listeners: SmallVec::new(), + scroll_wheel_listeners: SmallVec::new(), + key_down_listeners: SmallVec::new(), + key_up_listeners: SmallVec::new(), + action_listeners: SmallVec::new(), + drop_listeners: SmallVec::new(), + click_listeners: SmallVec::new(), + drag_listener: None, + hover_listener: None, + tooltip_builder: None, + } } } From 044d9679abc53c1dc0865a322ce0029fd7361cfe Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 13 Nov 2023 21:40:02 -0700 Subject: [PATCH 05/23] Checkpoint --- crates/editor2/src/element.rs | 4 +- crates/gpui2/src/element.rs | 2 +- crates/gpui2/src/elements/div.rs | 6 +- crates/gpui2/src/elements/node.rs | 582 ++++++++++++++++++++++++------ crates/gpui2/src/gpui2.rs | 16 +- crates/gpui2/src/style.rs | 44 ++- crates/gpui2/src/window.rs | 47 +-- 7 files changed, 548 insertions(+), 153 deletions(-) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index f8386ee271e658148d7edb9b32fec5c67a044443..630b062d1fb9188b8c1eb3798e95086b278891f4 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -616,7 +616,7 @@ impl EditorElement { let line_end_overshoot = 0.15 * layout.position_map.line_height; let whitespace_setting = editor.buffer.read(cx).settings_at(0, cx).show_whitespaces; - cx.with_content_mask(ContentMask { bounds }, |cx| { + cx.with_content_mask(Some(ContentMask { bounds }), |cx| { // todo!("cursor region") // cx.scene().push_cursor_region(CursorRegion { // bounds, @@ -2659,7 +2659,7 @@ impl Element for EditorElement { // We call with_z_index to establish a new stacking context. cx.with_z_index(0, |cx| { - cx.with_content_mask(ContentMask { bounds }, |cx| { + cx.with_content_mask(Some(ContentMask { bounds }), |cx| { self.paint_mouse_listeners( bounds, gutter_bounds, diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index 9ee9eaa7c335960f3e3c6974b0a8798c3d13f9c4..80ab0abc90fcd36446a2cc244e88c113d28da9bc 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -255,7 +255,7 @@ where // Ignore the element offset when drawing this element, as the origin is already specified // in absolute terms. origin -= cx.element_offset(); - cx.with_element_offset(Some(origin), |cx| self.paint(view_state, cx)) + cx.with_element_offset(origin, |cx| self.paint(view_state, cx)) } } diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 25c13d6980f3c8b3e3cdfd80570e603c574e795d..2b411f76091598e941343b1cbbdc7afab3d192a6 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -252,7 +252,7 @@ where cx: &mut ViewContext, ) -> LayoutId { let style = self.compute_style(Bounds::default(), element_state, cx); - style.with_text_style(cx, |cx| { + style.apply_text_style(cx, |cx| { self.with_element_id(cx, |this, _global_id, cx| { let layout_ids = this .children @@ -318,10 +318,10 @@ where ); }); cx.with_z_index(1, |cx| { - style.with_text_style(cx, |cx| { + style.apply_text_style(cx, |cx| { style.apply_overflow(bounds, cx, |cx| { let scroll_offset = element_state.interactive.scroll_offset(); - cx.with_element_offset(scroll_offset, |cx| { + cx.with_element_offset(scroll_offset.unwrap_or_default(), |cx| { for child in &mut this.children { child.paint(view_state, cx); } diff --git a/crates/gpui2/src/elements/node.rs b/crates/gpui2/src/elements/node.rs index 7133997c48e95f415d2d4901fcd0744d9c05a301..57f825994f20bbebd0e4c03151eea266d71d94fa 100644 --- a/crates/gpui2/src/elements/node.rs +++ b/crates/gpui2/src/elements/node.rs @@ -1,10 +1,12 @@ use crate::{ - point, Action, AnyDrag, AnyElement, AnyView, AppContext, BorrowWindow, Bounds, ClickEvent, - DispatchPhase, Element, FocusHandle, KeyContext, KeyDownEvent, KeyUpEvent, LayoutId, - MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, Point, Render, - ScrollWheelEvent, SharedString, Style, StyleRefinement, Styled, View, ViewContext, Visibility, + point, px, Action, AnyDrag, AnyElement, AnyTooltip, AnyView, AppContext, BorrowAppContext, + BorrowWindow, Bounds, ClickEvent, DispatchPhase, Element, FocusHandle, KeyContext, + KeyDownEvent, KeyUpEvent, LayoutId, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, + Pixels, Point, Render, ScrollWheelEvent, SharedString, Size, Style, StyleRefinement, Styled, + Task, View, ViewContext, Visibility, }; use collections::HashMap; +use parking_lot::Mutex; use refineable::Refineable; use smallvec::SmallVec; use std::{ @@ -12,14 +14,20 @@ use std::{ marker::PhantomData, mem, sync::Arc, + time::Duration, }; +use taffy::style::Overflow; + +const DRAG_THRESHOLD: f64 = 2.; +const TOOLTIP_DELAY: Duration = Duration::from_millis(500); +const TOOLTIP_OFFSET: Point = Point::new(px(10.0), px(8.0)); pub struct GroupStyle { pub group: SharedString, pub style: StyleRefinement, } -pub trait InteractiveComponent { +pub trait InteractiveComponent: Sized + Element { fn interactivity(&mut self) -> &mut Interactivity; fn hover(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self @@ -274,7 +282,7 @@ pub trait InteractiveComponent { } } -pub trait StatefulInteractiveComponent: InteractiveComponent { +pub trait StatefulInteractiveComponent>: InteractiveComponent { fn active(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self where Self: Sized, @@ -541,6 +549,13 @@ impl InteractiveComponent for Node { pub struct NodeState { child_layout_ids: SmallVec<[LayoutId; 4]>, + interactive_state: InteractiveElementState, +} + +impl AsMut for InteractiveElementState { + fn as_mut(&mut self) -> &mut InteractiveElementState { + self + } } impl Element for Node { @@ -553,7 +568,7 @@ impl Element for Node { fn initialize( &mut self, view_state: &mut V, - _: Option, + previous_element_state: Option, cx: &mut ViewContext, ) -> Self::ElementState { for child in &mut self.children { @@ -561,6 +576,9 @@ impl Element for Node { } NodeState { child_layout_ids: SmallVec::new(), + interactive_state: previous_element_state + .map(|s| s.interactive_state) + .unwrap_or_default(), } } @@ -570,15 +588,20 @@ impl Element for Node { element_state: &mut Self::ElementState, cx: &mut ViewContext, ) -> crate::LayoutId { - let style = self.interactivity().compute_style(None, cx); - style.with_text_style(cx, |cx| { - element_state.child_layout_ids = self - .children - .iter_mut() - .map(|child| child.layout(view_state, cx)) - .collect::>(); - cx.request_layout(&style, element_state.child_layout_ids.iter().copied()) - }) + let mut interactivity = mem::take(&mut self.interactivity); + let layout_id = + interactivity.layout(&mut element_state.interactive_state, cx, |style, cx| { + cx.with_text_style(style.text_style().cloned(), |cx| { + element_state.child_layout_ids = self + .children + .iter_mut() + .map(|child| child.layout(view_state, cx)) + .collect::>(); + cx.request_layout(&style, element_state.child_layout_ids.iter().copied()) + }) + }); + self.interactivity = interactivity; + layout_id } fn paint( @@ -588,27 +611,10 @@ impl Element for Node { element_state: &mut Self::ElementState, cx: &mut ViewContext, ) { - let style = self.interactivity.compute_style(Some(bounds), cx); - if style.visibility == Visibility::Hidden { - return; - } - - if let Some(mouse_cursor) = style.mouse_cursor { - let hovered = bounds.contains_point(&cx.mouse_position()); - if hovered { - cx.set_cursor_style(mouse_cursor); - } - } - - if let Some(group) = self.interactivity.group.clone() { - GroupBounds::push(group, bounds, cx); - } - - let z_index = style.z_index.unwrap_or(0); + let mut interactivity = mem::take(&mut self.interactivity); let mut child_min = point(Pixels::MAX, Pixels::MAX); let mut child_max = Point::default(); - let content_size = if element_state.child_layout_ids.is_empty() { bounds.size } else { @@ -620,35 +626,41 @@ impl Element for Node { (child_max - child_min).into() }; - let mut interactivity = mem::take(&mut self.interactivity); - interactivity.paint(bounds, cx, |cx| { - cx.with_z_index(z_index, |cx| { - cx.with_z_index(0, |cx| { - style.paint(bounds, cx); - }); - cx.with_z_index(1, |cx| { - style.with_text_style(cx, |cx| { - style.apply_overflow(bounds, cx, |cx| { - let scroll_offset = self.interactivity.scroll_offset; - cx.with_element_offset2(scroll_offset, |cx| { - for child in &mut self.children { - child.paint(view_state, cx); - } - }); + interactivity.paint( + bounds, + content_size, + &mut element_state.interactive_state, + cx, + |style, scroll_offset, cx| { + if style.visibility == Visibility::Hidden { + return; + } + + let z_index = style.z_index.unwrap_or(0); + + cx.with_z_index(z_index, |cx| { + cx.with_z_index(0, |cx| { + style.paint(bounds, cx); + }); + cx.with_z_index(1, |cx| { + cx.with_text_style(style.text_style().cloned(), |cx| { + cx.with_content_mask(style.overflow_mask(bounds), |cx| { + cx.with_element_offset(scroll_offset, |cx| { + for child in &mut self.children { + child.paint(view_state, cx); + } + }) + }) }) }) - }); - }); - }); + }) + }, + ); self.interactivity = interactivity; - - if let Some(group) = self.interactivity.group.as_ref() { - GroupBounds::pop(group, cx); - } } } -pub enum FocusState { +pub enum FocusStatus { /// The current element is not focused, and does not contain or descend from the focused element. None, /// The current element is focused. @@ -660,56 +672,87 @@ pub enum FocusState { } pub struct Interactivity { - pub active: bool, - pub group_active: bool, - pub hovered: bool, - pub group_hovered: bool, - pub focus: FocusState, - pub key_context: KeyContext, - pub focus_handle: Option, - pub scroll_offset: Point, - pub base_style: StyleRefinement, - pub focus_style: StyleRefinement, - pub focus_in_style: StyleRefinement, - pub in_focus_style: StyleRefinement, - pub hover_style: StyleRefinement, - pub group_hover_style: Option, - pub active_style: StyleRefinement, - pub group_active_style: Option, - pub drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>, - pub group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>, - pub group: Option, - pub dispatch_context: KeyContext, - pub mouse_down_listeners: SmallVec<[MouseDownListener; 2]>, - pub mouse_up_listeners: SmallVec<[MouseUpListener; 2]>, - pub mouse_move_listeners: SmallVec<[MouseMoveListener; 2]>, - pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener; 2]>, - pub key_down_listeners: SmallVec<[KeyDownListener; 2]>, - pub key_up_listeners: SmallVec<[KeyUpListener; 2]>, - pub action_listeners: SmallVec<[(TypeId, ActionListener); 8]>, - pub drop_listeners: SmallVec<[(TypeId, Box>); 2]>, - pub click_listeners: SmallVec<[ClickListener; 2]>, - pub drag_listener: Option>, - pub hover_listener: Option>, - pub tooltip_builder: Option>, + active: Option, + group_active: bool, + hovered: bool, + group_hovered: bool, + focus_status: FocusStatus, + key_context: KeyContext, + focus_handle: Option, + scroll_offset: Point, + base_style: StyleRefinement, + focus_style: StyleRefinement, + focus_in_style: StyleRefinement, + in_focus_style: StyleRefinement, + hover_style: StyleRefinement, + group_hover_style: Option, + active_style: StyleRefinement, + group_active_style: Option, + drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>, + group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>, + group: Option, + dispatch_context: KeyContext, + mouse_down_listeners: SmallVec<[MouseDownListener; 2]>, + mouse_up_listeners: SmallVec<[MouseUpListener; 2]>, + mouse_move_listeners: SmallVec<[MouseMoveListener; 2]>, + scroll_wheel_listeners: SmallVec<[ScrollWheelListener; 2]>, + key_down_listeners: SmallVec<[KeyDownListener; 2]>, + key_up_listeners: SmallVec<[KeyUpListener; 2]>, + action_listeners: SmallVec<[(TypeId, ActionListener); 8]>, + drop_listeners: SmallVec<[(TypeId, Box>); 2]>, + click_listeners: SmallVec<[ClickListener; 2]>, + drag_listener: Option>, + hover_listener: Option>, + tooltip_builder: Option>, +} + +#[derive(Default)] +pub struct InteractiveElementState { + clicked_state: Arc>, + hover_state: Arc>, + pending_mouse_down: Arc>>, + scroll_offset: Option>>>, + active_tooltip: Arc>>, +} + +struct ActiveTooltip { + #[allow(unused)] // used to drop the task + waiting: Option>, + tooltip: Option, } -impl Interactivity { +/// Whether or not the element or a group that contains it is clicked by the mouse. +#[derive(Copy, Clone, Default, Eq, PartialEq)] +struct ElementClickedState { + pub group: bool, + pub element: bool, +} + +impl ElementClickedState { + fn is_clicked(&self) -> bool { + self.group || self.element + } +} + +impl Interactivity +where + V: 'static, +{ fn compute_style(&self, bounds: Option>, cx: &mut ViewContext) -> Style { let mut style = Style::default(); style.refine(&self.base_style); - match self.focus { - FocusState::None => {} - FocusState::Focus => { + match self.focus_status { + FocusStatus::None => {} + FocusStatus::Focus => { style.refine(&self.focus_style); style.refine(&self.focus_in_style); style.refine(&self.in_focus_style); } - FocusState::FocusIn => { + FocusStatus::FocusIn => { style.refine(&self.focus_in_style); } - FocusState::InFocus => { + FocusStatus::InFocus => { style.refine(&self.in_focus_style); } } @@ -756,19 +799,66 @@ impl Interactivity { } } - if self.active { + if self.active.is_some() { style.refine(&self.active_style) } style } + fn layout( + &mut self, + element_state: &mut InteractiveElementState, + cx: &mut ViewContext, + f: impl FnOnce(Style, &mut ViewContext) -> LayoutId, + ) -> LayoutId { + let mut style = Style::default(); + style.refine(&self.base_style); + + if let Some(focus_handle) = self.focus_handle.as_ref() { + if focus_handle.contains_focused(cx) { + style.refine(&self.focus_in_style); + } + + if focus_handle.within_focused(cx) { + style.refine(&self.in_focus_style); + } + + if focus_handle.is_focused(cx) { + style.refine(&self.focus_style); + } + } + + let clicked_state = element_state.clicked_state.lock(); + if clicked_state.group { + if let Some(group_style) = self.group_active_style.as_ref() { + style.refine(&group_style.style); + } + } + if clicked_state.element { + style.refine(&self.active_style); + } + + f(style, cx) + } + fn paint( &mut self, bounds: Bounds, + content_size: Size, + element_state: &mut InteractiveElementState, cx: &mut ViewContext, - f: impl FnOnce(&mut ViewContext), + f: impl FnOnce(Style, Point, &mut ViewContext), ) { + let style = self.compute_style(Some(bounds), cx); + + if let Some(mouse_cursor) = style.mouse_cursor { + let hovered = bounds.contains_point(&cx.mouse_position()); + if hovered { + cx.set_cursor_style(mouse_cursor); + } + } + for listener in self.mouse_down_listeners.drain(..) { cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| { listener(state, event, &bounds, phase, cx); @@ -845,22 +935,212 @@ impl Interactivity { }); } + let mut element_state: &mut InteractiveElementState = element_state.as_mut(); + + let click_listeners = mem::take(&mut self.click_listeners); + let drag_listener = mem::take(&mut self.drag_listener); + + if !click_listeners.is_empty() || drag_listener.is_some() { + let pending_mouse_down = element_state.pending_mouse_down.clone(); + let mouse_down = pending_mouse_down.lock().clone(); + if let Some(mouse_down) = mouse_down { + if let Some(drag_listener) = drag_listener { + let active_state = element_state.clicked_state.clone(); + + cx.on_mouse_event(move |view_state, event: &MouseMoveEvent, phase, cx| { + if cx.active_drag.is_some() { + if phase == DispatchPhase::Capture { + cx.notify(); + } + } else if phase == DispatchPhase::Bubble + && bounds.contains_point(&event.position) + && (event.position - mouse_down.position).magnitude() > DRAG_THRESHOLD + { + *active_state.lock() = ElementClickedState::default(); + let cursor_offset = event.position - bounds.origin; + let drag = drag_listener(view_state, cursor_offset, cx); + cx.active_drag = Some(drag); + cx.notify(); + cx.stop_propagation(); + } + }); + } + + cx.on_mouse_event(move |view_state, event: &MouseUpEvent, phase, cx| { + if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { + let mouse_click = ClickEvent { + down: mouse_down.clone(), + up: event.clone(), + }; + for listener in &click_listeners { + listener(view_state, &mouse_click, cx); + } + } + *pending_mouse_down.lock() = None; + }); + } else { + cx.on_mouse_event(move |_state, event: &MouseDownEvent, phase, _cx| { + if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { + *pending_mouse_down.lock() = Some(event.clone()); + } + }); + } + } + + if let Some(hover_listener) = self.hover_listener.take() { + let was_hovered = element_state.hover_state.clone(); + let has_mouse_down = element_state.pending_mouse_down.clone(); + + cx.on_mouse_event(move |view_state, event: &MouseMoveEvent, phase, cx| { + if phase != DispatchPhase::Bubble { + return; + } + let is_hovered = + bounds.contains_point(&event.position) && has_mouse_down.lock().is_none(); + let mut was_hovered = was_hovered.lock(); + + if is_hovered != was_hovered.clone() { + *was_hovered = is_hovered; + drop(was_hovered); + + hover_listener(view_state, is_hovered, cx); + } + }); + } + + if let Some(tooltip_builder) = self.tooltip_builder.take() { + let active_tooltip = element_state.active_tooltip.clone(); + let pending_mouse_down = element_state.pending_mouse_down.clone(); + + cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| { + if phase != DispatchPhase::Bubble { + return; + } + + let is_hovered = + bounds.contains_point(&event.position) && pending_mouse_down.lock().is_none(); + if !is_hovered { + active_tooltip.lock().take(); + return; + } + + if active_tooltip.lock().is_none() { + let task = cx.spawn({ + let active_tooltip = active_tooltip.clone(); + let tooltip_builder = tooltip_builder.clone(); + + move |view, mut cx| async move { + cx.background_executor().timer(TOOLTIP_DELAY).await; + view.update(&mut cx, move |view_state, cx| { + active_tooltip.lock().replace(ActiveTooltip { + waiting: None, + tooltip: Some(AnyTooltip { + view: tooltip_builder(view_state, cx), + cursor_offset: cx.mouse_position() + TOOLTIP_OFFSET, + }), + }); + cx.notify(); + }) + .ok(); + } + }); + active_tooltip.lock().replace(ActiveTooltip { + waiting: Some(task), + tooltip: None, + }); + } + }); + + if let Some(active_tooltip) = element_state.active_tooltip.lock().as_ref() { + if active_tooltip.tooltip.is_some() { + cx.active_tooltip = active_tooltip.tooltip.clone() + } + } + } + + let active_state = element_state.clicked_state.clone(); + if !active_state.lock().is_clicked() { + cx.on_mouse_event(move |_, _: &MouseUpEvent, phase, cx| { + if phase == DispatchPhase::Capture { + *active_state.lock() = ElementClickedState::default(); + cx.notify(); + } + }); + } else { + let active_group_bounds = self + .group_active_style + .as_ref() + .and_then(|group_active| GroupBounds::get(&group_active.group, cx)); + cx.on_mouse_event(move |_view, down: &MouseDownEvent, phase, cx| { + if phase == DispatchPhase::Bubble { + let group = active_group_bounds + .map_or(false, |bounds| bounds.contains_point(&down.position)); + let element = bounds.contains_point(&down.position); + if group || element { + *active_state.lock() = ElementClickedState { group, element }; + cx.notify(); + } + } + }); + } + + let overflow = style.overflow; + if overflow.x == Overflow::Scroll || overflow.y == Overflow::Scroll { + let scroll_offset = element_state + .scroll_offset + .get_or_insert_with(Arc::default) + .clone(); + let line_height = cx.line_height(); + let scroll_max = (content_size - bounds.size).max(&Size::default()); + + cx.on_mouse_event(move |_, event: &ScrollWheelEvent, phase, cx| { + if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { + let mut scroll_offset = scroll_offset.lock(); + let old_scroll_offset = *scroll_offset; + let delta = event.delta.pixel_delta(line_height); + + if overflow.x == Overflow::Scroll { + scroll_offset.x = + (scroll_offset.x + delta.x).clamp(-scroll_max.width, px(0.)); + } + + if overflow.y == Overflow::Scroll { + scroll_offset.y = + (scroll_offset.y + delta.y).clamp(-scroll_max.height, px(0.)); + } + + if *scroll_offset != old_scroll_offset { + cx.notify(); + cx.stop_propagation(); + } + } + }); + } + + if let Some(group) = self.group.clone() { + GroupBounds::push(group, bounds, cx); + } + cx.with_key_dispatch( self.key_context.clone(), self.focus_handle.clone(), - |_, cx| f(cx), + |_, cx| f(style, self.scroll_offset, cx), ); + + if let Some(group) = self.group.as_ref() { + GroupBounds::pop(group, cx); + } } } impl Default for Interactivity { fn default() -> Self { Self { - active: false, + active: None, group_active: false, hovered: false, group_hovered: false, - focus: FocusState::None, + focus_status: FocusStatus::None, key_context: KeyContext::default(), focus_handle: None, scroll_offset: Point::default(), @@ -937,26 +1217,80 @@ impl FocusableComponent for Focusable { } } -impl> InteractiveComponent for Focusable { +impl InteractiveComponent for Focusable +where + V: 'static, + E: InteractiveComponent, +{ fn interactivity(&mut self) -> &mut Interactivity { self.element.interactivity() } } -impl> StatefulInteractiveComponent +impl> StatefulInteractiveComponent for Focusable { } +impl Element for Focusable +where + V: 'static, + E: Element, +{ + type ElementState = E::ElementState; + + fn id(&self) -> Option { + todo!() + } + + fn initialize( + &mut self, + view_state: &mut V, + element_state: Option, + cx: &mut ViewContext, + ) -> Self::ElementState { + todo!() + } + + fn layout( + &mut self, + view_state: &mut V, + element_state: &mut Self::ElementState, + cx: &mut ViewContext, + ) -> LayoutId { + todo!() + } + + fn paint( + &mut self, + bounds: Bounds, + view_state: &mut V, + element_state: &mut Self::ElementState, + cx: &mut ViewContext, + ) { + todo!() + } +} + pub struct Stateful { id: SharedString, view_type: PhantomData, element: E, } -impl> StatefulInteractiveComponent for Stateful {} +impl StatefulInteractiveComponent for Stateful +where + V: 'static, + E: Element, + Self: InteractiveComponent, +{ +} -impl> InteractiveComponent for Stateful { +impl InteractiveComponent for Stateful +where + V: 'static, + E: InteractiveComponent, +{ fn interactivity(&mut self) -> &mut Interactivity { self.element.interactivity() } @@ -967,3 +1301,43 @@ impl> FocusableComponent for Stateful { self.element.focusability() } } + +impl Element for Stateful +where + V: 'static, + E: Element, +{ + type ElementState = InteractiveElementState; + + fn id(&self) -> Option { + todo!() + } + + fn initialize( + &mut self, + view_state: &mut V, + element_state: Option, + cx: &mut ViewContext, + ) -> Self::ElementState { + todo!() + } + + fn layout( + &mut self, + view_state: &mut V, + element_state: &mut Self::ElementState, + cx: &mut ViewContext, + ) -> LayoutId { + todo!() + } + + fn paint( + &mut self, + bounds: Bounds, + view_state: &mut V, + element_state: &mut Self::ElementState, + cx: &mut ViewContext, + ) { + todo!() + } +} diff --git a/crates/gpui2/src/gpui2.rs b/crates/gpui2/src/gpui2.rs index 87de7998a88f9223386b05308871585eeb779040..323ca5851ba09981a68e65d4ae56171326494429 100644 --- a/crates/gpui2/src/gpui2.rs +++ b/crates/gpui2/src/gpui2.rs @@ -148,7 +148,7 @@ pub enum GlobalKey { } pub trait BorrowAppContext { - fn with_text_style(&mut self, style: TextStyleRefinement, f: F) -> R + fn with_text_style(&mut self, style: Option, f: F) -> R where F: FnOnce(&mut Self) -> R; @@ -159,14 +159,18 @@ impl BorrowAppContext for C where C: BorrowMut, { - fn with_text_style(&mut self, style: TextStyleRefinement, f: F) -> R + fn with_text_style(&mut self, style: Option, f: F) -> R where F: FnOnce(&mut Self) -> R, { - self.borrow_mut().push_text_style(style); - let result = f(self); - self.borrow_mut().pop_text_style(); - result + if let Some(style) = style { + self.borrow_mut().push_text_style(style); + let result = f(self); + self.borrow_mut().pop_text_style(); + result + } else { + f(self) + } } fn set_global(&mut self, global: G) { diff --git a/crates/gpui2/src/style.rs b/crates/gpui2/src/style.rs index 18b92c0b8b7ae8f0bfe83a7f45d56e5b92fe5e51..92959ef05795d441d395c6445f6ba0af0f745c9c 100644 --- a/crates/gpui2/src/style.rs +++ b/crates/gpui2/src/style.rs @@ -2,7 +2,7 @@ use crate::{ black, phi, point, rems, AbsoluteLength, BorrowAppContext, BorrowWindow, Bounds, ContentMask, Corners, CornersRefinement, CursorStyle, DefiniteLength, Edges, EdgesRefinement, Font, FontFeatures, FontStyle, FontWeight, Hsla, Length, Pixels, Point, PointRefinement, Result, - Rgba, SharedString, Size, SizeRefinement, Styled, TextRun, ViewContext, WindowContext, + Rgba, SharedString, Size, SizeRefinement, Styled, TextRun, ViewContext, }; use refineable::{Cascade, Refineable}; use smallvec::SmallVec; @@ -220,7 +220,7 @@ pub struct HighlightStyle { impl Eq for HighlightStyle {} impl Style { - pub fn text_style(&self, _cx: &WindowContext) -> Option<&TextStyleRefinement> { + pub fn text_style(&self) -> Option<&TextStyleRefinement> { if self.text.is_some() { Some(&self.text) } else { @@ -228,13 +228,47 @@ impl Style { } } - pub fn with_text_style(&self, cx: &mut C, f: F) -> R + pub fn overflow_mask(&self, bounds: Bounds) -> Option> { + match self.overflow { + Point { + x: Overflow::Visible, + y: Overflow::Visible, + } => None, + _ => { + let current_mask = bounds; + let min = current_mask.origin; + let max = current_mask.lower_right(); + let bounds = match ( + self.overflow.x == Overflow::Visible, + self.overflow.y == Overflow::Visible, + ) { + // x and y both visible + (true, true) => return None, + // x visible, y hidden + (true, false) => Bounds::from_corners( + point(min.x, bounds.origin.y), + point(max.x, bounds.lower_right().y), + ), + // x hidden, y visible + (false, true) => Bounds::from_corners( + point(bounds.origin.x, min.y), + point(bounds.lower_right().x, max.y), + ), + // both hidden + (false, false) => bounds, + }; + Some(ContentMask { bounds }) + } + } + } + + pub fn apply_text_style(&self, cx: &mut C, f: F) -> R where C: BorrowAppContext, F: FnOnce(&mut C) -> R, { if self.text.is_some() { - cx.with_text_style(self.text.clone(), f) + cx.with_text_style(Some(self.text.clone()), f) } else { f(cx) } @@ -274,7 +308,7 @@ impl Style { bounds: mask_bounds, }; - cx.with_content_mask(mask, f) + cx.with_content_mask(Some(mask), f) } /// Paints the background of an element styled with this style. diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 52c5464e4fe77b5a76a0de922208744e06c5be00..edda71f13fe28136031479f89f1faad10c2ed10f 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -1067,7 +1067,7 @@ impl<'a> WindowContext<'a> { if let Some(active_drag) = self.app.active_drag.take() { self.with_z_index(1, |cx| { let offset = cx.mouse_position() - active_drag.cursor_offset; - cx.with_element_offset(Some(offset), |cx| { + cx.with_element_offset(offset, |cx| { let available_space = size(AvailableSpace::MinContent, AvailableSpace::MinContent); active_drag.view.draw(available_space, cx); @@ -1076,7 +1076,7 @@ impl<'a> WindowContext<'a> { }); } else if let Some(active_tooltip) = self.app.active_tooltip.take() { self.with_z_index(1, |cx| { - cx.with_element_offset(Some(active_tooltip.cursor_offset), |cx| { + cx.with_element_offset(active_tooltip.cursor_offset, |cx| { let available_space = size(AvailableSpace::MinContent, AvailableSpace::MinContent); active_tooltip.view.draw(available_space, cx); @@ -1553,43 +1553,26 @@ pub trait BorrowWindow: BorrowMut + BorrowMut { /// with the current mask. fn with_content_mask( &mut self, - mask: ContentMask, + mask: Option>, f: impl FnOnce(&mut Self) -> R, ) -> R { - let mask = mask.intersect(&self.content_mask()); - self.window_mut() - .current_frame - .content_mask_stack - .push(mask); - let result = f(self); - self.window_mut().current_frame.content_mask_stack.pop(); - result + if let Some(mask) = mask { + let mask = mask.intersect(&self.content_mask()); + self.window_mut() + .current_frame + .content_mask_stack + .push(mask); + let result = f(self); + self.window_mut().current_frame.content_mask_stack.pop(); + result + } else { + f(self) + } } /// Update the global element offset based on the given offset. This is used to implement /// scrolling and position drag handles. fn with_element_offset( - &mut self, - offset: Option>, - f: impl FnOnce(&mut Self) -> R, - ) -> R { - let Some(offset) = offset else { - return f(self); - }; - - let offset = self.element_offset() + offset; - self.window_mut() - .current_frame - .element_offset_stack - .push(offset); - let result = f(self); - self.window_mut().current_frame.element_offset_stack.pop(); - result - } - - /// Update the global element offset based on the given offset. This is used to implement - /// scrolling and position drag handles. - fn with_element_offset2( &mut self, offset: Point, f: impl FnOnce(&mut Self) -> R, From 83a5f74493f349d4cc2c4b921d946445b4775223 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 13 Nov 2023 22:02:05 -0700 Subject: [PATCH 06/23] Checkpoint --- crates/gpui2/src/elements/node.rs | 113 +++++++++++------------------- 1 file changed, 39 insertions(+), 74 deletions(-) diff --git a/crates/gpui2/src/elements/node.rs b/crates/gpui2/src/elements/node.rs index 57f825994f20bbebd0e4c03151eea266d71d94fa..b412038cada8dd9dc571fcc99097b4b0e4d3f624 100644 --- a/crates/gpui2/src/elements/node.rs +++ b/crates/gpui2/src/elements/node.rs @@ -547,17 +547,6 @@ impl InteractiveComponent for Node { } } -pub struct NodeState { - child_layout_ids: SmallVec<[LayoutId; 4]>, - interactive_state: InteractiveElementState, -} - -impl AsMut for InteractiveElementState { - fn as_mut(&mut self) -> &mut InteractiveElementState { - self - } -} - impl Element for Node { type ElementState = NodeState; @@ -660,26 +649,25 @@ impl Element for Node { } } -pub enum FocusStatus { - /// The current element is not focused, and does not contain or descend from the focused element. - None, - /// The current element is focused. - Focus, - /// The current element contains the focused element - FocusIn, - /// The current element descends from the focused element - InFocus, +pub struct NodeState { + child_layout_ids: SmallVec<[LayoutId; 4]>, + interactive_state: InteractiveElementState, +} + +impl AsMut for InteractiveElementState { + fn as_mut(&mut self) -> &mut InteractiveElementState { + self + } } pub struct Interactivity { - active: Option, - group_active: bool, hovered: bool, group_hovered: bool, - focus_status: FocusStatus, key_context: KeyContext, focus_handle: Option, + focusable: bool, scroll_offset: Point, + group: Option, base_style: StyleRefinement, focus_style: StyleRefinement, focus_in_style: StyleRefinement, @@ -690,8 +678,6 @@ pub struct Interactivity { group_active_style: Option, drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>, group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>, - group: Option, - dispatch_context: KeyContext, mouse_down_listeners: SmallVec<[MouseDownListener; 2]>, mouse_up_listeners: SmallVec<[MouseUpListener; 2]>, mouse_move_listeners: SmallVec<[MouseMoveListener; 2]>, @@ -708,6 +694,7 @@ pub struct Interactivity { #[derive(Default)] pub struct InteractiveElementState { + focus_handle: Option, clicked_state: Arc>, hover_state: Arc>, pending_mouse_down: Arc>>, @@ -738,23 +725,27 @@ impl Interactivity where V: 'static, { - fn compute_style(&self, bounds: Option>, cx: &mut ViewContext) -> Style { + fn compute_style( + &self, + bounds: Option>, + element_state: &mut InteractiveElementState, + cx: &mut ViewContext, + ) -> Style { let mut style = Style::default(); style.refine(&self.base_style); - match self.focus_status { - FocusStatus::None => {} - FocusStatus::Focus => { - style.refine(&self.focus_style); - style.refine(&self.focus_in_style); - style.refine(&self.in_focus_style); - } - FocusStatus::FocusIn => { + if let Some(focus_handle) = self.focus_handle.as_ref() { + if focus_handle.contains_focused(cx) { style.refine(&self.focus_in_style); } - FocusStatus::InFocus => { + + if focus_handle.within_focused(cx) { style.refine(&self.in_focus_style); } + + if focus_handle.is_focused(cx) { + style.refine(&self.focus_style); + } } if let Some(bounds) = bounds { @@ -793,13 +784,14 @@ where } } - if self.group_active { + let clicked_state = element_state.clicked_state.lock(); + if clicked_state.group { if let Some(group) = self.group_active_style.as_ref() { style.refine(&group.style) } } - if self.active.is_some() { + if clicked_state.element { style.refine(&self.active_style) } @@ -812,34 +804,12 @@ where cx: &mut ViewContext, f: impl FnOnce(Style, &mut ViewContext) -> LayoutId, ) -> LayoutId { - let mut style = Style::default(); - style.refine(&self.base_style); - - if let Some(focus_handle) = self.focus_handle.as_ref() { - if focus_handle.contains_focused(cx) { - style.refine(&self.focus_in_style); - } - - if focus_handle.within_focused(cx) { - style.refine(&self.in_focus_style); - } - - if focus_handle.is_focused(cx) { - style.refine(&self.focus_style); - } - } - - let clicked_state = element_state.clicked_state.lock(); - if clicked_state.group { - if let Some(group_style) = self.group_active_style.as_ref() { - style.refine(&group_style.style); - } - } - if clicked_state.element { - style.refine(&self.active_style); - } - - f(style, cx) + let style = self.compute_style(None, element_state, cx); + cx.with_key_dispatch( + self.key_context.clone(), + self.focus_handle.clone(), + |_, cx| f(style, cx), + ) } fn paint( @@ -850,7 +820,7 @@ where cx: &mut ViewContext, f: impl FnOnce(Style, Point, &mut ViewContext), ) { - let style = self.compute_style(Some(bounds), cx); + let style = self.compute_style(Some(bounds), element_state, cx); if let Some(mouse_cursor) = style.mouse_cursor { let hovered = bounds.contains_point(&cx.mouse_position()); @@ -935,8 +905,6 @@ where }); } - let mut element_state: &mut InteractiveElementState = element_state.as_mut(); - let click_listeners = mem::take(&mut self.click_listeners); let drag_listener = mem::take(&mut self.drag_listener); @@ -1136,14 +1104,12 @@ where impl Default for Interactivity { fn default() -> Self { Self { - active: None, - group_active: false, hovered: false, group_hovered: false, - focus_status: FocusStatus::None, key_context: KeyContext::default(), focus_handle: None, scroll_offset: Point::default(), + group: None, base_style: StyleRefinement::default(), focus_style: StyleRefinement::default(), focus_in_style: StyleRefinement::default(), @@ -1154,8 +1120,6 @@ impl Default for Interactivity { group_active_style: None, drag_over_styles: SmallVec::new(), group_drag_over_styles: SmallVec::new(), - group: None, - dispatch_context: KeyContext::default(), mouse_down_listeners: SmallVec::new(), mouse_up_listeners: SmallVec::new(), mouse_move_listeners: SmallVec::new(), @@ -1168,6 +1132,7 @@ impl Default for Interactivity { drag_listener: None, hover_listener: None, tooltip_builder: None, + focusable: todo!(), } } } @@ -1240,7 +1205,7 @@ where type ElementState = E::ElementState; fn id(&self) -> Option { - todo!() + self.element.id() } fn initialize( From f71afdb0f2226fae12039b097123867c781b257f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 13 Nov 2023 22:22:09 -0700 Subject: [PATCH 07/23] Checkpoint --- crates/gpui2/src/elements/node.rs | 264 +++++++++++++++++------------- 1 file changed, 153 insertions(+), 111 deletions(-) diff --git a/crates/gpui2/src/elements/node.rs b/crates/gpui2/src/elements/node.rs index b412038cada8dd9dc571fcc99097b4b0e4d3f624..43bac764a9d5574f559b538cac17fd11767ea1c0 100644 --- a/crates/gpui2/src/elements/node.rs +++ b/crates/gpui2/src/elements/node.rs @@ -557,17 +557,20 @@ impl Element for Node { fn initialize( &mut self, view_state: &mut V, - previous_element_state: Option, + element_state: Option, cx: &mut ViewContext, ) -> Self::ElementState { - for child in &mut self.children { - child.initialize(view_state, cx); - } + let interactive_state = + self.interactivity + .initialize(element_state.map(|s| s.interactive_state), cx, |cx| { + for child in &mut self.children { + child.initialize(view_state, cx); + } + }); + NodeState { + interactive_state, child_layout_ids: SmallVec::new(), - interactive_state: previous_element_state - .map(|s| s.interactive_state) - .unwrap_or_default(), } } @@ -664,7 +667,7 @@ pub struct Interactivity { hovered: bool, group_hovered: bool, key_context: KeyContext, - focus_handle: Option, + tracked_focus_handle: Option, focusable: bool, scroll_offset: Point, group: Option, @@ -692,110 +695,29 @@ pub struct Interactivity { tooltip_builder: Option>, } -#[derive(Default)] -pub struct InteractiveElementState { - focus_handle: Option, - clicked_state: Arc>, - hover_state: Arc>, - pending_mouse_down: Arc>>, - scroll_offset: Option>>>, - active_tooltip: Arc>>, -} - -struct ActiveTooltip { - #[allow(unused)] // used to drop the task - waiting: Option>, - tooltip: Option, -} - -/// Whether or not the element or a group that contains it is clicked by the mouse. -#[derive(Copy, Clone, Default, Eq, PartialEq)] -struct ElementClickedState { - pub group: bool, - pub element: bool, -} - -impl ElementClickedState { - fn is_clicked(&self) -> bool { - self.group || self.element - } -} - impl Interactivity where V: 'static, { - fn compute_style( - &self, - bounds: Option>, - element_state: &mut InteractiveElementState, + fn initialize( + &mut self, + element_state: Option, cx: &mut ViewContext, - ) -> Style { - let mut style = Style::default(); - style.refine(&self.base_style); - - if let Some(focus_handle) = self.focus_handle.as_ref() { - if focus_handle.contains_focused(cx) { - style.refine(&self.focus_in_style); - } - - if focus_handle.within_focused(cx) { - style.refine(&self.in_focus_style); - } - - if focus_handle.is_focused(cx) { - style.refine(&self.focus_style); - } - } - - if let Some(bounds) = bounds { - let mouse_position = cx.mouse_position(); - if let Some(group_hover) = self.group_hover_style.as_ref() { - if let Some(group_bounds) = GroupBounds::get(&group_hover.group, cx) { - if group_bounds.contains_point(&mouse_position) { - style.refine(&group_hover.style); - } - } - } - if bounds.contains_point(&mouse_position) { - style.refine(&self.hover_style); - } - - if let Some(drag) = cx.active_drag.take() { - for (state_type, group_drag_style) in &self.group_drag_over_styles { - if let Some(group_bounds) = GroupBounds::get(&group_drag_style.group, cx) { - if *state_type == drag.view.entity_type() - && group_bounds.contains_point(&mouse_position) - { - style.refine(&group_drag_style.style); - } - } - } - - for (state_type, drag_over_style) in &self.drag_over_styles { - if *state_type == drag.view.entity_type() - && bounds.contains_point(&mouse_position) - { - style.refine(drag_over_style); - } - } - - cx.active_drag = Some(drag); - } - } - - let clicked_state = element_state.clicked_state.lock(); - if clicked_state.group { - if let Some(group) = self.group_active_style.as_ref() { - style.refine(&group.style) - } - } - - if clicked_state.element { - style.refine(&self.active_style) + f: impl FnOnce(&mut ViewContext), + ) -> InteractiveElementState { + let mut element_state = element_state.unwrap_or_default(); + // Ensure we store a focus handle in our element state if we're focusable. + // If there's an explicit focus handle we're tracking, use that. Otherwise + // create a new handle and store it in the element state, which lives for as + // as frames contain an element with this id. + if self.focusable { + element_state.focus_handle.get_or_insert_with(|| { + self.tracked_focus_handle + .clone() + .unwrap_or_else(|| cx.focus_handle()) + }); } - - style + element_state } fn layout( @@ -807,7 +729,7 @@ where let style = self.compute_style(None, element_state, cx); cx.with_key_dispatch( self.key_context.clone(), - self.focus_handle.clone(), + self.tracked_focus_handle.clone(), |_, cx| f(style, cx), ) } @@ -1091,14 +1013,105 @@ where cx.with_key_dispatch( self.key_context.clone(), - self.focus_handle.clone(), - |_, cx| f(style, self.scroll_offset, cx), + self.tracked_focus_handle.clone(), + |_, cx| { + for listener in self.key_down_listeners.drain(..) { + cx.on_key_event(move |state, event: &KeyDownEvent, phase, cx| { + listener(state, event, phase, cx); + }) + } + + for listener in self.key_up_listeners.drain(..) { + cx.on_key_event(move |state, event: &KeyUpEvent, phase, cx| { + listener(state, event, phase, cx); + }) + } + + for (action_type, listener) in self.action_listeners.drain(..) { + cx.on_action(action_type, listener) + } + + f(style, self.scroll_offset, cx) + }, ); if let Some(group) = self.group.as_ref() { GroupBounds::pop(group, cx); } } + + fn compute_style( + &self, + bounds: Option>, + element_state: &mut InteractiveElementState, + cx: &mut ViewContext, + ) -> Style { + let mut style = Style::default(); + style.refine(&self.base_style); + + if let Some(focus_handle) = self.tracked_focus_handle.as_ref() { + if focus_handle.contains_focused(cx) { + style.refine(&self.focus_in_style); + } + + if focus_handle.within_focused(cx) { + style.refine(&self.in_focus_style); + } + + if focus_handle.is_focused(cx) { + style.refine(&self.focus_style); + } + } + + if let Some(bounds) = bounds { + let mouse_position = cx.mouse_position(); + if let Some(group_hover) = self.group_hover_style.as_ref() { + if let Some(group_bounds) = GroupBounds::get(&group_hover.group, cx) { + if group_bounds.contains_point(&mouse_position) { + style.refine(&group_hover.style); + } + } + } + if bounds.contains_point(&mouse_position) { + style.refine(&self.hover_style); + } + + if let Some(drag) = cx.active_drag.take() { + for (state_type, group_drag_style) in &self.group_drag_over_styles { + if let Some(group_bounds) = GroupBounds::get(&group_drag_style.group, cx) { + if *state_type == drag.view.entity_type() + && group_bounds.contains_point(&mouse_position) + { + style.refine(&group_drag_style.style); + } + } + } + + for (state_type, drag_over_style) in &self.drag_over_styles { + if *state_type == drag.view.entity_type() + && bounds.contains_point(&mouse_position) + { + style.refine(drag_over_style); + } + } + + cx.active_drag = Some(drag); + } + } + + let clicked_state = element_state.clicked_state.lock(); + if clicked_state.group { + if let Some(group) = self.group_active_style.as_ref() { + style.refine(&group.style) + } + } + + if clicked_state.element { + style.refine(&self.active_style) + } + + style + } } impl Default for Interactivity { @@ -1107,7 +1120,7 @@ impl Default for Interactivity { hovered: false, group_hovered: false, key_context: KeyContext::default(), - focus_handle: None, + tracked_focus_handle: None, scroll_offset: Point::default(), group: None, base_style: StyleRefinement::default(), @@ -1132,11 +1145,40 @@ impl Default for Interactivity { drag_listener: None, hover_listener: None, tooltip_builder: None, - focusable: todo!(), + focusable: false, } } } +#[derive(Default)] +pub struct InteractiveElementState { + focus_handle: Option, + clicked_state: Arc>, + hover_state: Arc>, + pending_mouse_down: Arc>>, + scroll_offset: Option>>>, + active_tooltip: Arc>>, +} + +struct ActiveTooltip { + #[allow(unused)] // used to drop the task + waiting: Option>, + tooltip: Option, +} + +/// Whether or not the element or a group that contains it is clicked by the mouse. +#[derive(Copy, Clone, Default, Eq, PartialEq)] +struct ElementClickedState { + pub group: bool, + pub element: bool, +} + +impl ElementClickedState { + fn is_clicked(&self) -> bool { + self.group || self.element + } +} + #[derive(Default)] pub struct GroupBounds(HashMap; 1]>>); From 54a817a5abd7655910f7c4e9f57e0d78ba14b7a3 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 13 Nov 2023 22:28:33 -0700 Subject: [PATCH 08/23] Checkpoint --- crates/gpui2/src/elements/node.rs | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/crates/gpui2/src/elements/node.rs b/crates/gpui2/src/elements/node.rs index 43bac764a9d5574f559b538cac17fd11767ea1c0..d5bfd63647c2f433c2455915e383713ea8ed5d88 100644 --- a/crates/gpui2/src/elements/node.rs +++ b/crates/gpui2/src/elements/node.rs @@ -603,8 +603,6 @@ impl Element for Node { element_state: &mut Self::ElementState, cx: &mut ViewContext, ) { - let mut interactivity = mem::take(&mut self.interactivity); - let mut child_min = point(Pixels::MAX, Pixels::MAX); let mut child_max = Point::default(); let content_size = if element_state.child_layout_ids.is_empty() { @@ -618,6 +616,7 @@ impl Element for Node { (child_max - child_min).into() }; + let mut interactivity = mem::take(&mut self.interactivity); interactivity.paint( bounds, content_size, @@ -664,8 +663,6 @@ impl AsMut for InteractiveElementState { } pub struct Interactivity { - hovered: bool, - group_hovered: bool, key_context: KeyContext, tracked_focus_handle: Option, focusable: bool, @@ -1117,8 +1114,6 @@ where impl Default for Interactivity { fn default() -> Self { Self { - hovered: false, - group_hovered: false, key_context: KeyContext::default(), tracked_focus_handle: None, scroll_offset: Point::default(), @@ -1256,7 +1251,7 @@ where element_state: Option, cx: &mut ViewContext, ) -> Self::ElementState { - todo!() + self.element.initialize(view_state, element_state, cx) } fn layout( @@ -1265,7 +1260,7 @@ where element_state: &mut Self::ElementState, cx: &mut ViewContext, ) -> LayoutId { - todo!() + self.element.layout(view_state, element_state, cx) } fn paint( @@ -1275,7 +1270,7 @@ where element_state: &mut Self::ElementState, cx: &mut ViewContext, ) { - todo!() + self.element.paint(bounds, view_state, element_state, cx); } } @@ -1314,10 +1309,10 @@ where V: 'static, E: Element, { - type ElementState = InteractiveElementState; + type ElementState = E::ElementState; fn id(&self) -> Option { - todo!() + self.element.id() } fn initialize( @@ -1326,7 +1321,7 @@ where element_state: Option, cx: &mut ViewContext, ) -> Self::ElementState { - todo!() + self.element.initialize(view_state, element_state, cx) } fn layout( @@ -1335,7 +1330,7 @@ where element_state: &mut Self::ElementState, cx: &mut ViewContext, ) -> LayoutId { - todo!() + self.element.layout(view_state, element_state, cx) } fn paint( @@ -1345,6 +1340,6 @@ where element_state: &mut Self::ElementState, cx: &mut ViewContext, ) { - todo!() + self.element.paint(bounds, view_state, element_state, cx) } } From 4a3a1ad0c35ff622eb8c966e984652f4f0968db2 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 13 Nov 2023 22:42:19 -0700 Subject: [PATCH 09/23] Checkpoint --- crates/editor2/src/element.rs | 2 +- crates/gpui2/src/elements/div.rs | 40 +++++++++++-------------------- crates/gpui2/src/elements/node.rs | 2 ++ crates/gpui2/src/view.rs | 6 ++--- crates/gpui2/src/window.rs | 25 +++++++++++-------- 5 files changed, 35 insertions(+), 40 deletions(-) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 630b062d1fb9188b8c1eb3798e95086b278891f4..8ee99e19af4848c95efcf913ec4a7c5e263f6ae7 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -2455,7 +2455,7 @@ impl Element for EditorElement { editor.style = Some(self.style.clone()); // Long-term, we'd like to eliminate this. let dispatch_context = editor.dispatch_context(cx); - cx.with_element_id(cx.view().entity_id(), |global_id, cx| { + cx.with_element_id(Some(cx.view().entity_id()), |cx| { cx.with_key_dispatch( dispatch_context, Some(editor.focus_handle.clone()), diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 2b411f76091598e941343b1cbbdc7afab3d192a6..1d85450c29f5190d2f4e341205782615558b2b57 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -2,7 +2,7 @@ use std::fmt::Debug; use crate::{ point, AnyElement, BorrowWindow, Bounds, Component, Element, ElementId, ElementInteractivity, - FocusHandle, FocusListeners, Focusable, FocusableKeyDispatch, GlobalElementId, GroupBounds, + FocusHandle, FocusListeners, Focusable, FocusableKeyDispatch, GroupBounds, InteractiveElementState, KeyContext, KeyDispatch, LayoutId, NonFocusableKeyDispatch, Overflow, ParentElement, Pixels, Point, SharedString, StatefulInteractive, StatefulInteractivity, StatelessInteractive, StatelessInteractivity, Style, StyleRefinement, Styled, ViewContext, @@ -93,18 +93,6 @@ where self } - fn with_element_id( - &mut self, - cx: &mut ViewContext, - f: impl FnOnce(&mut Self, Option, &mut ViewContext) -> R, - ) -> R { - if let Some(id) = self.id() { - cx.with_element_id(id, |global_id, cx| f(self, Some(global_id), cx)) - } else { - f(self, None, cx) - } - } - pub fn compute_style( &self, bounds: Bounds, @@ -229,14 +217,14 @@ where cx: &mut ViewContext, ) -> Self::ElementState { let mut element_state = element_state.unwrap_or_default(); - self.with_element_id(cx, |this, _global_id, cx| { - this.key_dispatch.initialize( + cx.with_element_id(self.id(), |cx| { + self.key_dispatch.initialize( element_state.focus_handle.take(), cx, |focus_handle, cx| { - this.interactivity.initialize(cx); + self.interactivity.initialize(cx); element_state.focus_handle = focus_handle; - for child in &mut this.children { + for child in &mut self.children { child.initialize(view_state, cx); } }, @@ -253,8 +241,8 @@ where ) -> LayoutId { let style = self.compute_style(Bounds::default(), element_state, cx); style.apply_text_style(cx, |cx| { - self.with_element_id(cx, |this, _global_id, cx| { - let layout_ids = this + cx.with_element_id(self.id(), |cx| { + let layout_ids = self .children .iter_mut() .map(|child| child.layout(view_state, cx)) @@ -272,8 +260,8 @@ where element_state: &mut Self::ElementState, cx: &mut ViewContext, ) { - self.with_element_id(cx, |this, _global_id, cx| { - let style = this.compute_style(bounds, element_state, cx); + cx.with_element_id(self.id(), |cx| { + let style = self.compute_style(bounds, element_state, cx); if style.visibility == Visibility::Hidden { return; } @@ -285,7 +273,7 @@ where } } - if let Some(group) = this.group.clone() { + if let Some(group) = self.group.clone() { GroupBounds::push(group, bounds, cx); } @@ -308,8 +296,8 @@ where cx.with_z_index(z_index, |cx| { cx.with_z_index(0, |cx| { style.paint(bounds, cx); - this.key_dispatch.paint(bounds, cx); - this.interactivity.handle_events( + self.key_dispatch.paint(bounds, cx); + self.interactivity.handle_events( bounds, content_size, style.overflow, @@ -322,7 +310,7 @@ where style.apply_overflow(bounds, cx, |cx| { let scroll_offset = element_state.interactive.scroll_offset(); cx.with_element_offset(scroll_offset.unwrap_or_default(), |cx| { - for child in &mut this.children { + for child in &mut self.children { child.paint(view_state, cx); } }); @@ -331,7 +319,7 @@ where }); }); - if let Some(group) = this.group.as_ref() { + if let Some(group) = self.group.as_ref() { GroupBounds::pop(group, cx); } }) diff --git a/crates/gpui2/src/elements/node.rs b/crates/gpui2/src/elements/node.rs index d5bfd63647c2f433c2455915e383713ea8ed5d88..f3d2b38dfb14055321d2d5a669109dba3c5f95eb 100644 --- a/crates/gpui2/src/elements/node.rs +++ b/crates/gpui2/src/elements/node.rs @@ -1008,6 +1008,8 @@ where GroupBounds::push(group, bounds, cx); } + todo!(); + // cx.with_element_id(self.i, f); cx.with_key_dispatch( self.key_context.clone(), self.tracked_focus_handle.clone(), diff --git a/crates/gpui2/src/view.rs b/crates/gpui2/src/view.rs index d12d84f43b424f83c5785d7dd0b33c776054bbb3..3299ce7d45e91e3bfe477eb2f39e04fcc9a14058 100644 --- a/crates/gpui2/src/view.rs +++ b/crates/gpui2/src/view.rs @@ -286,7 +286,7 @@ mod any_view { use std::any::Any; pub(crate) fn initialize(view: &AnyView, cx: &mut WindowContext) -> Box { - cx.with_element_id(view.model.entity_id, |_, cx| { + cx.with_element_id(Some(view.model.entity_id), |cx| { let view = view.clone().downcast::().unwrap(); let element = view.update(cx, |view, cx| { let mut element = AnyElement::new(view.render(cx)); @@ -302,7 +302,7 @@ mod any_view { element: &mut Box, cx: &mut WindowContext, ) -> LayoutId { - cx.with_element_id(view.model.entity_id, |_, cx| { + cx.with_element_id(Some(view.model.entity_id), |cx| { let view = view.clone().downcast::().unwrap(); let element = element.downcast_mut::>().unwrap(); view.update(cx, |view, cx| element.layout(view, cx)) @@ -314,7 +314,7 @@ mod any_view { element: &mut Box, cx: &mut WindowContext, ) { - cx.with_element_id(view.model.entity_id, |_, cx| { + cx.with_element_id(Some(view.model.entity_id), |cx| { let view = view.clone().downcast::().unwrap(); let element = element.downcast_mut::>().unwrap(); view.update(cx, |view, cx| element.paint(view, cx)) diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index edda71f13fe28136031479f89f1faad10c2ed10f..c5d794aa3d846718229f9da540a61cb8cc51aa26 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -1537,16 +1537,19 @@ pub trait BorrowWindow: BorrowMut + BorrowMut { /// used to associate state with identified elements across separate frames. fn with_element_id( &mut self, - id: impl Into, - f: impl FnOnce(GlobalElementId, &mut Self) -> R, + id: Option>, + f: impl FnOnce(&mut Self) -> R, ) -> R { - let window = self.window_mut(); - window.element_id_stack.push(id.into()); - let global_id = window.element_id_stack.clone(); - let result = f(global_id, self); - let window: &mut Window = self.borrow_mut(); - window.element_id_stack.pop(); - result + if let Some(id) = id.map(Into::into) { + let window = self.window_mut(); + window.element_id_stack.push(id.into()); + let result = f(self); + let window: &mut Window = self.borrow_mut(); + window.element_id_stack.pop(); + result + } else { + f(self) + } } /// Invoke the given function with the given content mask after intersecting it @@ -1613,7 +1616,9 @@ pub trait BorrowWindow: BorrowMut + BorrowMut { where S: 'static, { - self.with_element_id(id, |global_id, cx| { + self.with_element_id(Some(id), |cx| { + let global_id = cx.window().element_id_stack.clone(); + if let Some(any) = cx .window_mut() .current_frame From 16683307645a355c95df6b39ac6ab87c3c73242e Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 13 Nov 2023 22:51:44 -0700 Subject: [PATCH 10/23] Checkpoint --- crates/gpui2/src/elements/node.rs | 89 +++++++++++++++---------------- 1 file changed, 43 insertions(+), 46 deletions(-) diff --git a/crates/gpui2/src/elements/node.rs b/crates/gpui2/src/elements/node.rs index f3d2b38dfb14055321d2d5a669109dba3c5f95eb..7129220e6a714c9389299b3c63251bcf63f9c6c0 100644 --- a/crates/gpui2/src/elements/node.rs +++ b/crates/gpui2/src/elements/node.rs @@ -1,6 +1,6 @@ use crate::{ point, px, Action, AnyDrag, AnyElement, AnyTooltip, AnyView, AppContext, BorrowAppContext, - BorrowWindow, Bounds, ClickEvent, DispatchPhase, Element, FocusHandle, KeyContext, + BorrowWindow, Bounds, ClickEvent, DispatchPhase, Element, ElementId, FocusHandle, KeyContext, KeyDownEvent, KeyUpEvent, LayoutId, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, Point, Render, ScrollWheelEvent, SharedString, Size, Style, StyleRefinement, Styled, Task, View, ViewContext, Visibility, @@ -550,8 +550,8 @@ impl InteractiveComponent for Node { impl Element for Node { type ElementState = NodeState; - fn id(&self) -> Option { - None + fn id(&self) -> Option { + self.interactivity.element_id.clone() } fn initialize( @@ -560,13 +560,12 @@ impl Element for Node { element_state: Option, cx: &mut ViewContext, ) -> Self::ElementState { - let interactive_state = - self.interactivity - .initialize(element_state.map(|s| s.interactive_state), cx, |cx| { - for child in &mut self.children { - child.initialize(view_state, cx); - } - }); + let interactive_state = self + .interactivity + .initialize(element_state.map(|s| s.interactive_state), cx); + for child in &mut self.children { + child.initialize(view_state, cx); + } NodeState { interactive_state, @@ -656,13 +655,8 @@ pub struct NodeState { interactive_state: InteractiveElementState, } -impl AsMut for InteractiveElementState { - fn as_mut(&mut self) -> &mut InteractiveElementState { - self - } -} - pub struct Interactivity { + element_id: Option, key_context: KeyContext, tracked_focus_handle: Option, focusable: bool, @@ -700,9 +694,9 @@ where &mut self, element_state: Option, cx: &mut ViewContext, - f: impl FnOnce(&mut ViewContext), ) -> InteractiveElementState { let mut element_state = element_state.unwrap_or_default(); + // Ensure we store a focus handle in our element state if we're focusable. // If there's an explicit focus handle we're tracking, use that. Otherwise // create a new handle and store it in the element state, which lives for as @@ -724,11 +718,13 @@ where f: impl FnOnce(Style, &mut ViewContext) -> LayoutId, ) -> LayoutId { let style = self.compute_style(None, element_state, cx); - cx.with_key_dispatch( - self.key_context.clone(), - self.tracked_focus_handle.clone(), - |_, cx| f(style, cx), - ) + cx.with_element_id(self.element_id.clone(), |cx| { + cx.with_key_dispatch( + self.key_context.clone(), + self.tracked_focus_handle.clone(), + |_, cx| f(style, cx), + ) + }) } fn paint( @@ -1008,31 +1004,31 @@ where GroupBounds::push(group, bounds, cx); } - todo!(); - // cx.with_element_id(self.i, f); - cx.with_key_dispatch( - self.key_context.clone(), - self.tracked_focus_handle.clone(), - |_, cx| { - for listener in self.key_down_listeners.drain(..) { - cx.on_key_event(move |state, event: &KeyDownEvent, phase, cx| { - listener(state, event, phase, cx); - }) - } + cx.with_element_id(self.element_id.clone(), |cx| { + cx.with_key_dispatch( + self.key_context.clone(), + self.tracked_focus_handle.clone(), + |_, cx| { + for listener in self.key_down_listeners.drain(..) { + cx.on_key_event(move |state, event: &KeyDownEvent, phase, cx| { + listener(state, event, phase, cx); + }) + } - for listener in self.key_up_listeners.drain(..) { - cx.on_key_event(move |state, event: &KeyUpEvent, phase, cx| { - listener(state, event, phase, cx); - }) - } + for listener in self.key_up_listeners.drain(..) { + cx.on_key_event(move |state, event: &KeyUpEvent, phase, cx| { + listener(state, event, phase, cx); + }) + } - for (action_type, listener) in self.action_listeners.drain(..) { - cx.on_action(action_type, listener) - } + for (action_type, listener) in self.action_listeners.drain(..) { + cx.on_action(action_type, listener) + } - f(style, self.scroll_offset, cx) - }, - ); + f(style, self.scroll_offset, cx) + }, + ); + }); if let Some(group) = self.group.as_ref() { GroupBounds::pop(group, cx); @@ -1116,6 +1112,7 @@ where impl Default for Interactivity { fn default() -> Self { Self { + element_id: None, key_context: KeyContext::default(), tracked_focus_handle: None, scroll_offset: Point::default(), @@ -1243,7 +1240,7 @@ where { type ElementState = E::ElementState; - fn id(&self) -> Option { + fn id(&self) -> Option { self.element.id() } @@ -1313,7 +1310,7 @@ where { type ElementState = E::ElementState; - fn id(&self) -> Option { + fn id(&self) -> Option { self.element.id() } From 9382a304c4fe4404920905ff7436cf72e1a0620a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 13 Nov 2023 23:03:14 -0700 Subject: [PATCH 11/23] Checkpoint --- crates/gpui2/src/elements/node.rs | 94 +++++++++++++----------------- crates/ui2/src/components/modal.rs | 2 +- 2 files changed, 41 insertions(+), 55 deletions(-) diff --git a/crates/gpui2/src/elements/node.rs b/crates/gpui2/src/elements/node.rs index 7129220e6a714c9389299b3c63251bcf63f9c6c0..f69ad25ab0e4c2aae8dfa577c0af1b9c04c50979 100644 --- a/crates/gpui2/src/elements/node.rs +++ b/crates/gpui2/src/elements/node.rs @@ -1,9 +1,9 @@ use crate::{ point, px, Action, AnyDrag, AnyElement, AnyTooltip, AnyView, AppContext, BorrowAppContext, - BorrowWindow, Bounds, ClickEvent, DispatchPhase, Element, ElementId, FocusHandle, KeyContext, - KeyDownEvent, KeyUpEvent, LayoutId, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, - Pixels, Point, Render, ScrollWheelEvent, SharedString, Size, Style, StyleRefinement, Styled, - Task, View, ViewContext, Visibility, + BorrowWindow, Bounds, ClickEvent, DispatchPhase, Element, ElementId, FocusEvent, FocusHandle, + KeyContext, KeyDownEvent, KeyUpEvent, LayoutId, MouseButton, MouseDownEvent, MouseMoveEvent, + MouseUpEvent, Pixels, Point, Render, ScrollWheelEvent, SharedString, Size, Style, + StyleRefinement, Styled, Task, View, ViewContext, Visibility, }; use collections::HashMap; use parking_lot::Mutex; @@ -371,14 +371,12 @@ pub trait StatefulInteractiveComponent>: InteractiveCo } } -pub trait FocusableComponent { - fn focusability(&mut self) -> &mut Focusability; - +pub trait FocusableComponent: InteractiveComponent { fn focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self where Self: Sized, { - self.focusability().focus_style = f(StyleRefinement::default()); + self.interactivity().focus_style = f(StyleRefinement::default()); self } @@ -386,7 +384,7 @@ pub trait FocusableComponent { where Self: Sized, { - self.focusability().focus_in_style = f(StyleRefinement::default()); + self.interactivity().focus_in_style = f(StyleRefinement::default()); self } @@ -394,7 +392,7 @@ pub trait FocusableComponent { where Self: Sized, { - self.focusability().in_focus_style = f(StyleRefinement::default()); + self.interactivity().in_focus_style = f(StyleRefinement::default()); self } @@ -405,13 +403,13 @@ pub trait FocusableComponent { where Self: Sized, { - self.focusability() - .focus_listeners - .push(Box::new(move |view, focus_handle, event, cx| { + self.interactivity().focus_listeners.push(Box::new( + move |view, focus_handle, event, cx| { if event.focused.as_ref() == Some(focus_handle) { listener(view, event, cx) } - })); + }, + )); self } @@ -422,13 +420,13 @@ pub trait FocusableComponent { where Self: Sized, { - self.focusability() - .focus_listeners - .push(Box::new(move |view, focus_handle, event, cx| { + self.interactivity().focus_listeners.push(Box::new( + move |view, focus_handle, event, cx| { if event.blurred.as_ref() == Some(focus_handle) { listener(view, event, cx) } - })); + }, + )); self } @@ -439,9 +437,8 @@ pub trait FocusableComponent { where Self: Sized, { - self.focusability() - .focus_listeners - .push(Box::new(move |view, focus_handle, event, cx| { + self.interactivity().focus_listeners.push(Box::new( + move |view, focus_handle, event, cx| { let descendant_blurred = event .blurred .as_ref() @@ -454,7 +451,8 @@ pub trait FocusableComponent { if !descendant_blurred && descendant_focused { listener(view, event, cx) } - })); + }, + )); self } @@ -465,9 +463,8 @@ pub trait FocusableComponent { where Self: Sized, { - self.focusability() - .focus_listeners - .push(Box::new(move |view, focus_handle, event, cx| { + self.interactivity().focus_listeners.push(Box::new( + move |view, focus_handle, event, cx| { let descendant_blurred = event .blurred .as_ref() @@ -479,7 +476,8 @@ pub trait FocusableComponent { if descendant_blurred && !descendant_focused { listener(view, event, cx) } - })); + }, + )); self } } @@ -525,11 +523,6 @@ pub type KeyUpListener = pub type ActionListener = Box) + 'static>; -pub struct FocusEvent { - pub blurred: Option, - pub focused: Option, -} - pub struct Node { interactivity: Interactivity, children: Vec>, @@ -658,8 +651,9 @@ pub struct NodeState { pub struct Interactivity { element_id: Option, key_context: KeyContext, - tracked_focus_handle: Option, focusable: bool, + tracked_focus_handle: Option, + focus_listeners: FocusListeners, scroll_offset: Point, group: Option, base_style: StyleRefinement, @@ -1007,7 +1001,7 @@ where cx.with_element_id(self.element_id.clone(), |cx| { cx.with_key_dispatch( self.key_context.clone(), - self.tracked_focus_handle.clone(), + element_state.focus_handle.clone(), |_, cx| { for listener in self.key_down_listeners.drain(..) { cx.on_key_event(move |state, event: &KeyDownEvent, phase, cx| { @@ -1025,6 +1019,15 @@ where cx.on_action(action_type, listener) } + if let Some(focus_handle) = element_state.focus_handle.as_ref() { + for listener in self.focus_listeners.drain(..) { + let focus_handle = focus_handle.clone(); + cx.on_focus_changed(move |view, event, cx| { + listener(view, &focus_handle, event, cx) + }); + } + } + f(style, self.scroll_offset, cx) }, ); @@ -1114,7 +1117,9 @@ impl Default for Interactivity { Self { element_id: None, key_context: KeyContext::default(), + focusable: false, tracked_focus_handle: None, + focus_listeners: SmallVec::default(), scroll_offset: Point::default(), group: None, base_style: StyleRefinement::default(), @@ -1139,7 +1144,6 @@ impl Default for Interactivity { drag_listener: None, hover_listener: None, tooltip_builder: None, - focusable: false, } } } @@ -1199,24 +1203,11 @@ impl GroupBounds { } pub struct Focusable { - focusability: Focusability, view_type: PhantomData, element: E, } -pub struct Focusability { - focus_handle: Option, - focus_listeners: FocusListeners, - focus_style: StyleRefinement, - focus_in_style: StyleRefinement, - in_focus_style: StyleRefinement, -} - -impl FocusableComponent for Focusable { - fn focusability(&mut self) -> &mut Focusability { - &mut self.focusability - } -} +impl> FocusableComponent for Focusable {} impl InteractiveComponent for Focusable where @@ -1274,7 +1265,6 @@ where } pub struct Stateful { - id: SharedString, view_type: PhantomData, element: E, } @@ -1297,11 +1287,7 @@ where } } -impl> FocusableComponent for Stateful { - fn focusability(&mut self) -> &mut Focusability { - self.element.focusability() - } -} +impl> FocusableComponent for Stateful {} impl Element for Stateful where diff --git a/crates/ui2/src/components/modal.rs b/crates/ui2/src/components/modal.rs index 805bbe95b2b4d4798a380efad6e2bc68f623f3fa..75528b5c3460defeb139f7a16d8d311d87a5093b 100644 --- a/crates/ui2/src/components/modal.rs +++ b/crates/ui2/src/components/modal.rs @@ -1,4 +1,4 @@ -use gpui::{AnyElement, Pixels}; +use gpui::AnyElement; use smallvec::SmallVec; use crate::{h_stack, prelude::*, v_stack, Button, Icon, IconButton, Label}; From ce30a689a0df57ef0b501ac63c8872c4fff2e55f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 13 Nov 2023 23:15:45 -0700 Subject: [PATCH 12/23] Checkpoint --- crates/gpui2/src/elements/node.rs | 118 +++++++++++++++--------------- 1 file changed, 58 insertions(+), 60 deletions(-) diff --git a/crates/gpui2/src/elements/node.rs b/crates/gpui2/src/elements/node.rs index f69ad25ab0e4c2aae8dfa577c0af1b9c04c50979..82a952fc16c5df4df611067fa90c5c3c7f8409bf 100644 --- a/crates/gpui2/src/elements/node.rs +++ b/crates/gpui2/src/elements/node.rs @@ -11,12 +11,14 @@ use refineable::Refineable; use smallvec::SmallVec; use std::{ any::{Any, TypeId}, + fmt::Debug, marker::PhantomData, mem, sync::Arc, time::Duration, }; use taffy::style::Overflow; +use util::ResultExt; const DRAG_THRESHOLD: f64 = 2.; const TOOLTIP_DELAY: Duration = Duration::from_millis(500); @@ -30,10 +32,36 @@ pub struct GroupStyle { pub trait InteractiveComponent: Sized + Element { fn interactivity(&mut self) -> &mut Interactivity; - fn hover(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self + fn id(mut self, id: impl Into) -> Stateful { + self.interactivity().element_id = Some(id.into()); + + Stateful { + element: self, + view_type: PhantomData, + } + } + + fn track_focus(mut self, focus_handle: FocusHandle) -> Focusable { + self.interactivity().focusable = true; + self.interactivity().tracked_focus_handle = Some(focus_handle); + Focusable { + element: self, + view_type: PhantomData, + } + } + + fn key_context(mut self, key_context: C) -> Self where - Self: Sized, + C: TryInto, + E: Debug, { + if let Some(key_context) = key_context.try_into().log_err() { + self.interactivity().key_context = key_context; + } + self + } + + fn hover(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self { self.interactivity().hover_style = f(StyleRefinement::default()); self } @@ -42,10 +70,7 @@ pub trait InteractiveComponent: Sized + Element { mut self, group_name: impl Into, f: impl FnOnce(StyleRefinement) -> StyleRefinement, - ) -> Self - where - Self: Sized, - { + ) -> Self { self.interactivity().group_hover_style = Some(GroupStyle { group: group_name.into(), style: f(StyleRefinement::default()), @@ -57,10 +82,7 @@ pub trait InteractiveComponent: Sized + Element { mut self, button: MouseButton, handler: impl Fn(&mut V, &MouseDownEvent, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { + ) -> Self { self.interactivity().mouse_down_listeners.push(Box::new( move |view, event, bounds, phase, cx| { if phase == DispatchPhase::Bubble @@ -78,10 +100,7 @@ pub trait InteractiveComponent: Sized + Element { mut self, button: MouseButton, handler: impl Fn(&mut V, &MouseUpEvent, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { + ) -> Self { self.interactivity().mouse_up_listeners.push(Box::new( move |view, event, bounds, phase, cx| { if phase == DispatchPhase::Bubble @@ -98,10 +117,7 @@ pub trait InteractiveComponent: Sized + Element { fn on_mouse_down_out( mut self, handler: impl Fn(&mut V, &MouseDownEvent, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { + ) -> Self { self.interactivity().mouse_down_listeners.push(Box::new( move |view, event, bounds, phase, cx| { if phase == DispatchPhase::Capture && !bounds.contains_point(&event.position) { @@ -116,10 +132,7 @@ pub trait InteractiveComponent: Sized + Element { mut self, button: MouseButton, handler: impl Fn(&mut V, &MouseUpEvent, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { + ) -> Self { self.interactivity().mouse_up_listeners.push(Box::new( move |view, event, bounds, phase, cx| { if phase == DispatchPhase::Capture @@ -136,10 +149,7 @@ pub trait InteractiveComponent: Sized + Element { fn on_mouse_move( mut self, handler: impl Fn(&mut V, &MouseMoveEvent, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { + ) -> Self { self.interactivity().mouse_move_listeners.push(Box::new( move |view, event, bounds, phase, cx| { if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { @@ -153,10 +163,7 @@ pub trait InteractiveComponent: Sized + Element { fn on_scroll_wheel( mut self, handler: impl Fn(&mut V, &ScrollWheelEvent, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { + ) -> Self { self.interactivity().scroll_wheel_listeners.push(Box::new( move |view, event, bounds, phase, cx| { if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { @@ -171,10 +178,7 @@ pub trait InteractiveComponent: Sized + Element { fn capture_action( mut self, listener: impl Fn(&mut V, &A, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { + ) -> Self { self.interactivity().action_listeners.push(( TypeId::of::(), Box::new(move |view, action, phase, cx| { @@ -191,10 +195,7 @@ pub trait InteractiveComponent: Sized + Element { fn on_action( mut self, listener: impl Fn(&mut V, &A, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { + ) -> Self { self.interactivity().action_listeners.push(( TypeId::of::(), Box::new(move |view, action, phase, cx| { @@ -210,10 +211,7 @@ pub trait InteractiveComponent: Sized + Element { fn on_key_down( mut self, listener: impl Fn(&mut V, &KeyDownEvent, DispatchPhase, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { + ) -> Self { self.interactivity() .key_down_listeners .push(Box::new(move |view, event, phase, cx| { @@ -225,10 +223,7 @@ pub trait InteractiveComponent: Sized + Element { fn on_key_up( mut self, listener: impl Fn(&mut V, &KeyUpEvent, DispatchPhase, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { + ) -> Self { self.interactivity() .key_up_listeners .push(Box::new(move |view, event, phase, cx| { @@ -237,10 +232,7 @@ pub trait InteractiveComponent: Sized + Element { self } - fn drag_over(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self - where - Self: Sized, - { + fn drag_over(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self { self.interactivity() .drag_over_styles .push((TypeId::of::(), f(StyleRefinement::default()))); @@ -251,10 +243,7 @@ pub trait InteractiveComponent: Sized + Element { mut self, group_name: impl Into, f: impl FnOnce(StyleRefinement) -> StyleRefinement, - ) -> Self - where - Self: Sized, - { + ) -> Self { self.interactivity().group_drag_over_styles.push(( TypeId::of::(), GroupStyle { @@ -268,10 +257,7 @@ pub trait InteractiveComponent: Sized + Element { fn on_drop( mut self, listener: impl Fn(&mut V, View, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { + ) -> Self { self.interactivity().drop_listeners.push(( TypeId::of::(), Box::new(move |view, dragged_view, cx| { @@ -283,6 +269,11 @@ pub trait InteractiveComponent: Sized + Element { } pub trait StatefulInteractiveComponent>: InteractiveComponent { + fn focusable(mut self) -> Self { + self.interactivity().focusable = true; + self + } + fn active(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self where Self: Sized, @@ -523,6 +514,13 @@ pub type KeyUpListener = pub type ActionListener = Box) + 'static>; +pub fn node() -> Node { + Node { + interactivity: Interactivity::default(), + children: Vec::default(), + } +} + pub struct Node { interactivity: Interactivity, children: Vec>, @@ -1203,8 +1201,8 @@ impl GroupBounds { } pub struct Focusable { - view_type: PhantomData, element: E, + view_type: PhantomData, } impl> FocusableComponent for Focusable {} @@ -1265,8 +1263,8 @@ where } pub struct Stateful { - view_type: PhantomData, element: E, + view_type: PhantomData, } impl StatefulInteractiveComponent for Stateful From 27fb381ccab269685dbae629c3db91ab1138a7f3 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 14 Nov 2023 01:15:48 -0700 Subject: [PATCH 13/23] Checkpoint --- .../command_palette2/src/command_palette.rs | 10 +- crates/editor2/src/editor.rs | 10 +- crates/editor2/src/element.rs | 2 +- crates/editor2/src/items.rs | 2 +- crates/go_to_line2/src/go_to_line.rs | 8 +- crates/gpui2/src/element.rs | 12 +- crates/gpui2/src/elements.rs | 5 +- crates/gpui2/src/elements/div.rs | 42 - crates/gpui2/src/elements/img.rs | 170 +--- crates/gpui2/src/elements/node.rs | 217 +++-- crates/gpui2/src/elements/svg.rs | 125 +-- crates/gpui2/src/elements/text.rs | 2 +- crates/gpui2/src/elements/uniform_list.rs | 219 +++-- crates/gpui2/src/interactive.rs | 920 +----------------- crates/gpui2/src/key_dispatch.rs | 118 +-- crates/gpui2/src/prelude.rs | 5 +- crates/gpui2/src/styled.rs | 288 ++---- crates/gpui2/src/view.rs | 2 +- crates/gpui2_macros/src/style_helpers.rs | 4 +- crates/picker2/src/picker2.rs | 6 +- crates/storybook2/src/stories/colors.rs | 4 +- crates/storybook2/src/stories/focus.rs | 11 +- crates/storybook2/src/stories/kitchen_sink.rs | 4 +- crates/storybook2/src/stories/picker.rs | 12 +- crates/storybook2/src/stories/scroll.rs | 5 +- crates/storybook2/src/stories/text.rs | 4 +- crates/storybook2/src/stories/z_index.rs | 6 +- crates/storybook2/src/storybook2.rs | 4 +- crates/theme2/src/players.rs | 4 +- crates/theme2/src/story.rs | 4 +- crates/ui2/src/components/avatar.rs | 4 +- crates/ui2/src/components/button.rs | 6 +- crates/ui2/src/components/checkbox.rs | 10 +- crates/ui2/src/components/context_menu.rs | 4 +- crates/ui2/src/components/details.rs | 4 +- crates/ui2/src/components/elevated_surface.rs | 6 +- crates/ui2/src/components/facepile.rs | 4 +- crates/ui2/src/components/icon.rs | 4 +- crates/ui2/src/components/icon_button.rs | 6 +- crates/ui2/src/components/input.rs | 9 +- crates/ui2/src/components/keybinding.rs | 4 +- crates/ui2/src/components/label.rs | 4 +- crates/ui2/src/components/modal.rs | 2 +- crates/ui2/src/components/palette.rs | 8 +- crates/ui2/src/components/panel.rs | 8 +- crates/ui2/src/components/stack.rs | 6 +- crates/ui2/src/components/tab.rs | 6 +- crates/ui2/src/components/toast.rs | 11 +- crates/ui2/src/components/toggle.rs | 2 +- crates/ui2/src/components/tooltip.rs | 4 +- crates/ui2/src/prelude.rs | 4 +- crates/ui2/src/story.rs | 4 +- crates/ui2/src/styled_ext.rs | 11 +- crates/ui2/src/to_extract/assistant_panel.rs | 6 +- crates/ui2/src/to_extract/breadcrumb.rs | 10 +- crates/ui2/src/to_extract/buffer.rs | 4 +- crates/ui2/src/to_extract/buffer_search.rs | 6 +- crates/ui2/src/to_extract/chat_panel.rs | 9 +- crates/ui2/src/to_extract/collab_panel.rs | 9 +- crates/ui2/src/to_extract/command_palette.rs | 4 +- crates/ui2/src/to_extract/copilot.rs | 4 +- crates/ui2/src/to_extract/editor_pane.rs | 6 +- .../ui2/src/to_extract/language_selector.rs | 4 +- crates/ui2/src/to_extract/multi_buffer.rs | 4 +- .../ui2/src/to_extract/notifications_panel.rs | 13 +- crates/ui2/src/to_extract/panes.rs | 2 +- crates/ui2/src/to_extract/project_panel.rs | 9 +- crates/ui2/src/to_extract/recent_projects.rs | 4 +- crates/ui2/src/to_extract/tab_bar.rs | 8 +- crates/ui2/src/to_extract/terminal.rs | 4 +- crates/ui2/src/to_extract/theme_selector.rs | 4 +- crates/ui2/src/to_extract/title_bar.rs | 10 +- crates/ui2/src/to_extract/toolbar.rs | 4 +- crates/ui2/src/to_extract/traffic_lights.rs | 4 +- crates/ui2/src/to_extract/workspace.rs | 8 +- crates/workspace2/src/dock.rs | 12 +- crates/workspace2/src/modal_layer.rs | 6 +- crates/workspace2/src/notifications.rs | 4 +- crates/workspace2/src/pane.rs | 12 +- crates/workspace2/src/status_bar.rs | 6 +- crates/workspace2/src/toolbar.rs | 4 +- crates/workspace2/src/workspace2.rs | 30 +- 82 files changed, 660 insertions(+), 1906 deletions(-) diff --git a/crates/command_palette2/src/command_palette.rs b/crates/command_palette2/src/command_palette.rs index c7a6c9ee834b81685ca94a0227202a97daaeae8d..139d8a16c76602c0f9e8aee4a93e802e5273aeb4 100644 --- a/crates/command_palette2/src/command_palette.rs +++ b/crates/command_palette2/src/command_palette.rs @@ -1,9 +1,9 @@ use collections::{CommandPaletteFilter, HashMap}; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{ - actions, div, Action, AppContext, Component, Div, EventEmitter, FocusHandle, Keystroke, - ParentElement, Render, StatelessInteractive, Styled, View, ViewContext, VisualContext, - WeakView, WindowContext, + actions, div, prelude::*, Action, AppContext, Component, EventEmitter, FocusHandle, Keystroke, + Node, ParentComponent, Render, Styled, View, ViewContext, VisualContext, WeakView, + WindowContext, }; use picker::{Picker, PickerDelegate}; use std::{ @@ -77,7 +77,7 @@ impl Modal for CommandPalette { } impl Render for CommandPalette { - type Element = Div; + type Element = Node; fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { v_stack().w_96().child(self.picker.clone()) @@ -148,7 +148,7 @@ impl CommandPaletteDelegate { } impl PickerDelegate for CommandPaletteDelegate { - type ListItem = Div>; + type ListItem = Node>; fn placeholder_text(&self) -> Arc { "Execute a command...".into() diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index 654aa73feea7429a4b4dd58f8222c1a78dec2315..f4e4146f1a094c2dca6e9f25b5a0a04f0240c4d5 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -39,12 +39,12 @@ use futures::FutureExt; use fuzzy::{StringMatch, StringMatchCandidate}; use git::diff_hunk_to_display; use gpui::{ - action, actions, div, point, px, relative, rems, size, uniform_list, AnyElement, AppContext, - AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Component, Context, + action, actions, div, point, prelude::*, px, relative, rems, size, uniform_list, AnyElement, + AppContext, AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Component, Context, EventEmitter, FocusHandle, FontFeatures, FontStyle, FontWeight, HighlightStyle, Hsla, - InputHandler, KeyContext, Model, MouseButton, ParentElement, Pixels, Render, - StatelessInteractive, Styled, Subscription, Task, TextStyle, UniformListScrollHandle, View, - ViewContext, VisualContext, WeakView, WindowContext, + InputHandler, KeyContext, Model, MouseButton, ParentComponent, Pixels, Render, Styled, + Subscription, Task, TextStyle, UniformListScrollHandle, View, ViewContext, VisualContext, + WeakView, WindowContext, }; use highlight_matching_bracket::refresh_matching_bracket_highlights; use hover_popover::{hide_hover, HoverState}; diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 8ee99e19af4848c95efcf913ec4a7c5e263f6ae7..ba2dcb431a6ccf68b5da662c4fc31c0028d43fd8 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -2442,7 +2442,7 @@ enum Invisible { impl Element for EditorElement { type ElementState = (); - fn id(&self) -> Option { + fn element_id(&self) -> Option { None } diff --git a/crates/editor2/src/items.rs b/crates/editor2/src/items.rs index 25e9f91608fc857ea30191f25bbfc75aac6117ef..b1fc69ecac8cbd427ce3696d3c97bddee15ef980 100644 --- a/crates/editor2/src/items.rs +++ b/crates/editor2/src/items.rs @@ -9,7 +9,7 @@ use collections::HashSet; use futures::future::try_join_all; use gpui::{ div, point, AnyElement, AppContext, AsyncAppContext, Entity, EntityId, EventEmitter, - FocusHandle, Model, ParentElement, Pixels, SharedString, Styled, Subscription, Task, View, + FocusHandle, Model, ParentComponent, Pixels, SharedString, Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView, }; use language::{ diff --git a/crates/go_to_line2/src/go_to_line.rs b/crates/go_to_line2/src/go_to_line.rs index 50592901b5396ca6cc11aa86b3f3c75820c0a2f1..9f2ba6db219e899d4cf6df1f91575943cf9427aa 100644 --- a/crates/go_to_line2/src/go_to_line.rs +++ b/crates/go_to_line2/src/go_to_line.rs @@ -1,7 +1,7 @@ use editor::{display_map::ToDisplayPoint, scroll::autoscroll::Autoscroll, Editor}; use gpui::{ - actions, div, AppContext, Div, EventEmitter, ParentElement, Render, SharedString, - StatelessInteractive, Styled, Subscription, View, ViewContext, VisualContext, WindowContext, + actions, div, prelude::*, AppContext, EventEmitter, Node, ParentComponent, Render, + SharedString, Styled, Subscription, View, ViewContext, VisualContext, WindowContext, }; use text::{Bias, Point}; use theme::ActiveTheme; @@ -145,11 +145,11 @@ impl GoToLine { } impl Render for GoToLine { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { modal(cx) - .context("GoToLine") + .key_context("GoToLine") .on_action(Self::cancel) .on_action(Self::confirm) .w_96() diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index 80ab0abc90fcd36446a2cc244e88c113d28da9bc..46ea5c6cd21b5a297b65c4de1b783b68435d7296 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -8,7 +8,7 @@ use std::{any::Any, mem}; pub trait Element { type ElementState: 'static; - fn id(&self) -> Option; + fn element_id(&self) -> Option; /// Called to initialize this element for the current frame. If this /// element had state in a previous frame, it will be passed in for the 3rd argument. @@ -38,7 +38,7 @@ pub trait Element { #[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)] pub struct GlobalElementId(SmallVec<[ElementId; 32]>); -pub trait ParentElement { +pub trait ParentComponent { fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]>; fn child(mut self, child: impl Component) -> Self @@ -120,7 +120,7 @@ where E::ElementState: 'static, { fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext) { - let frame_state = if let Some(id) = self.element.id() { + let frame_state = if let Some(id) = self.element.element_id() { cx.with_element_state(id, |element_state, cx| { let element_state = self.element.initialize(view_state, element_state, cx); ((), element_state) @@ -142,7 +142,7 @@ where frame_state: initial_frame_state, } => { frame_state = initial_frame_state; - if let Some(id) = self.element.id() { + if let Some(id) = self.element.element_id() { layout_id = cx.with_element_state(id, |element_state, cx| { let mut element_state = element_state.unwrap(); let layout_id = self.element.layout(state, &mut element_state, cx); @@ -181,7 +181,7 @@ where .. } => { let bounds = cx.layout_bounds(layout_id); - if let Some(id) = self.element.id() { + if let Some(id) = self.element.element_id() { cx.with_element_state(id, |element_state, cx| { let mut element_state = element_state.unwrap(); self.element @@ -351,7 +351,7 @@ where { type ElementState = AnyElement; - fn id(&self) -> Option { + fn element_id(&self) -> Option { None } diff --git a/crates/gpui2/src/elements.rs b/crates/gpui2/src/elements.rs index e0e155fb0390c15faf34c28af0d41d6130c55512..5bf9e6202b1a81374592bb1e03b9b277ce3365fa 100644 --- a/crates/gpui2/src/elements.rs +++ b/crates/gpui2/src/elements.rs @@ -1,12 +1,13 @@ -mod div; +// mod div; mod img; mod node; mod svg; mod text; mod uniform_list; -pub use div::*; +// pub use div::*; pub use img::*; +pub use node::*; pub use svg::*; pub use text::*; pub use uniform_list::*; diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 1d85450c29f5190d2f4e341205782615558b2b57..537c14633948d4077becf489ce1095403f7945c5 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -55,16 +55,6 @@ where I: ElementInteractivity, F: KeyDispatch, { - pub fn group(mut self, group: impl Into) -> Self { - self.group = Some(group.into()); - self - } - - pub fn z_index(mut self, z_index: u32) -> Self { - self.base_style.z_index = Some(z_index); - self - } - pub fn context(mut self, context: C) -> Self where Self: Sized, @@ -77,22 +67,6 @@ where self } - pub fn overflow_hidden(mut self) -> Self { - self.base_style.overflow.x = Some(Overflow::Hidden); - self.base_style.overflow.y = Some(Overflow::Hidden); - self - } - - pub fn overflow_hidden_x(mut self) -> Self { - self.base_style.overflow.x = Some(Overflow::Hidden); - self - } - - pub fn overflow_hidden_y(mut self) -> Self { - self.base_style.overflow.y = Some(Overflow::Hidden); - self - } - pub fn compute_style( &self, bounds: Bounds, @@ -135,22 +109,6 @@ impl Div, NonFocusableKeyDispatch> { base_style: self.base_style, } } - - pub fn overflow_scroll(mut self) -> Self { - self.base_style.overflow.x = Some(Overflow::Scroll); - self.base_style.overflow.y = Some(Overflow::Scroll); - self - } - - pub fn overflow_x_scroll(mut self) -> Self { - self.base_style.overflow.x = Some(Overflow::Scroll); - self - } - - pub fn overflow_y_scroll(mut self) -> Self { - self.base_style.overflow.y = Some(Overflow::Scroll); - self - } } impl Div, NonFocusableKeyDispatch> { diff --git a/crates/gpui2/src/elements/img.rs b/crates/gpui2/src/elements/img.rs index 1ff088c1afc4a2098dc2ba41e37d0ae2ff6eef55..bfa3c6cfae26f71b50d329c9f64628fab7950ed5 100644 --- a/crates/gpui2/src/elements/img.rs +++ b/crates/gpui2/src/elements/img.rs @@ -1,35 +1,28 @@ use crate::{ - div, AnyElement, BorrowWindow, Bounds, Component, Div, DivState, Element, ElementId, - ElementInteractivity, FocusListeners, Focusable, FocusableKeyDispatch, KeyDispatch, LayoutId, - NonFocusableKeyDispatch, Pixels, SharedString, StatefulInteractive, StatefulInteractivity, - StatelessInteractive, StatelessInteractivity, StyleRefinement, Styled, ViewContext, + AnyElement, BorrowWindow, Bounds, Component, Element, InteractiveComponent, + InteractiveElementState, Interactivity, LayoutId, Pixels, SharedString, StyleRefinement, + Styled, ViewContext, }; use futures::FutureExt; use util::ResultExt; -pub struct Img< - V: 'static, - I: ElementInteractivity = StatelessInteractivity, - F: KeyDispatch = NonFocusableKeyDispatch, -> { - base: Div, +pub struct Img { + interactivity: Interactivity, uri: Option, grayscale: bool, } -pub fn img() -> Img, NonFocusableKeyDispatch> { +pub fn img() -> Img { Img { - base: div(), + interactivity: Interactivity::default(), uri: None, grayscale: false, } } -impl Img +impl Img where V: 'static, - I: ElementInteractivity, - F: KeyDispatch, { pub fn uri(mut self, uri: impl Into) -> Self { self.uri = Some(uri.into()); @@ -42,38 +35,17 @@ where } } -impl Img, F> -where - F: KeyDispatch, -{ - pub fn id(self, id: impl Into) -> Img, F> { - Img { - base: self.base.id(id), - uri: self.uri, - grayscale: self.grayscale, - } - } -} - -impl Component for Img -where - I: ElementInteractivity, - F: KeyDispatch, -{ +impl Component for Img { fn render(self) -> AnyElement { AnyElement::new(self) } } -impl Element for Img -where - I: ElementInteractivity, - F: KeyDispatch, -{ - type ElementState = DivState; +impl Element for Img { + type ElementState = InteractiveElementState; - fn id(&self) -> Option { - self.base.id() + fn element_id(&self) -> Option { + self.interactivity.element_id.clone() } fn initialize( @@ -82,7 +54,7 @@ where element_state: Option, cx: &mut ViewContext, ) -> Self::ElementState { - self.base.initialize(view_state, element_state, cx) + self.interactivity.initialize(element_state, cx) } fn layout( @@ -91,7 +63,9 @@ where element_state: &mut Self::ElementState, cx: &mut ViewContext, ) -> LayoutId { - self.base.layout(view_state, element_state, cx) + self.interactivity.layout(element_state, cx, |style, cx| { + cx.request_layout(&style, None) + }) } fn paint( @@ -101,86 +75,50 @@ where element_state: &mut Self::ElementState, cx: &mut ViewContext, ) { - cx.with_z_index(0, |cx| { - self.base.paint(bounds, view, element_state, cx); - }); - - let style = self.base.compute_style(bounds, element_state, cx); - let corner_radii = style.corner_radii; - - if let Some(uri) = self.uri.clone() { - // eprintln!(">>> image_cache.get({uri}"); - let image_future = cx.image_cache.get(uri.clone()); - // eprintln!("<<< image_cache.get({uri}"); - if let Some(data) = image_future - .clone() - .now_or_never() - .and_then(ResultExt::log_err) - { - let corner_radii = corner_radii.to_pixels(bounds.size, cx.rem_size()); - cx.with_z_index(1, |cx| { - cx.paint_image(bounds, corner_radii, data, self.grayscale) - .log_err() - }); - } else { - cx.spawn(|_, mut cx| async move { - if image_future.await.log_err().is_some() { - cx.on_next_frame(|cx| cx.notify()); + self.interactivity.paint( + bounds, + bounds.size, + element_state, + cx, + |style, scroll_offset, cx| { + let corner_radii = style.corner_radii; + + if let Some(uri) = self.uri.clone() { + // eprintln!(">>> image_cache.get({uri}"); + let image_future = cx.image_cache.get(uri.clone()); + // eprintln!("<<< image_cache.get({uri}"); + if let Some(data) = image_future + .clone() + .now_or_never() + .and_then(ResultExt::log_err) + { + let corner_radii = corner_radii.to_pixels(bounds.size, cx.rem_size()); + cx.with_z_index(1, |cx| { + cx.paint_image(bounds, corner_radii, data, self.grayscale) + .log_err() + }); + } else { + cx.spawn(|_, mut cx| async move { + if image_future.await.log_err().is_some() { + cx.on_next_frame(|cx| cx.notify()); + } + }) + .detach() } - }) - .detach() - } - } + } + }, + ) } } -impl Styled for Img -where - I: ElementInteractivity, - F: KeyDispatch, -{ +impl Styled for Img { fn style(&mut self) -> &mut StyleRefinement { - self.base.style() + &mut self.interactivity.base_style } } -impl StatelessInteractive for Img -where - I: ElementInteractivity, - F: KeyDispatch, -{ - fn stateless_interactivity(&mut self) -> &mut StatelessInteractivity { - self.base.stateless_interactivity() - } -} - -impl StatefulInteractive for Img, F> -where - F: KeyDispatch, -{ - fn stateful_interactivity(&mut self) -> &mut StatefulInteractivity { - self.base.stateful_interactivity() - } -} - -impl Focusable for Img> -where - V: 'static, - I: ElementInteractivity, -{ - fn focus_listeners(&mut self) -> &mut FocusListeners { - self.base.focus_listeners() - } - - fn set_focus_style(&mut self, style: StyleRefinement) { - self.base.set_focus_style(style) - } - - fn set_focus_in_style(&mut self, style: StyleRefinement) { - self.base.set_focus_in_style(style) - } - - fn set_in_focus_style(&mut self, style: StyleRefinement) { - self.base.set_in_focus_style(style) +impl InteractiveComponent for Img { + fn interactivity(&mut self) -> &mut Interactivity { + &mut self.interactivity } } diff --git a/crates/gpui2/src/elements/node.rs b/crates/gpui2/src/elements/node.rs index 82a952fc16c5df4df611067fa90c5c3c7f8409bf..49c447254e62f0a72a4880beec2700e3e7a67442 100644 --- a/crates/gpui2/src/elements/node.rs +++ b/crates/gpui2/src/elements/node.rs @@ -1,9 +1,9 @@ use crate::{ point, px, Action, AnyDrag, AnyElement, AnyTooltip, AnyView, AppContext, BorrowAppContext, - BorrowWindow, Bounds, ClickEvent, DispatchPhase, Element, ElementId, FocusEvent, FocusHandle, - KeyContext, KeyDownEvent, KeyUpEvent, LayoutId, MouseButton, MouseDownEvent, MouseMoveEvent, - MouseUpEvent, Pixels, Point, Render, ScrollWheelEvent, SharedString, Size, Style, - StyleRefinement, Styled, Task, View, ViewContext, Visibility, + BorrowWindow, Bounds, ClickEvent, Component, DispatchPhase, Element, ElementId, FocusEvent, + FocusHandle, KeyContext, KeyDownEvent, KeyUpEvent, LayoutId, MouseButton, MouseDownEvent, + MouseMoveEvent, MouseUpEvent, ParentComponent, Pixels, Point, Render, ScrollWheelEvent, + SharedString, Size, Style, StyleRefinement, Styled, Task, View, ViewContext, Visibility, }; use collections::HashMap; use parking_lot::Mutex; @@ -32,6 +32,11 @@ pub struct GroupStyle { pub trait InteractiveComponent: Sized + Element { fn interactivity(&mut self) -> &mut Interactivity; + fn group(mut self, group: impl Into) -> Self { + self.interactivity().group = Some(group.into()); + self + } + fn id(mut self, id: impl Into) -> Stateful { self.interactivity().element_id = Some(id.into()); @@ -41,9 +46,9 @@ pub trait InteractiveComponent: Sized + Element { } } - fn track_focus(mut self, focus_handle: FocusHandle) -> Focusable { + fn track_focus(mut self, focus_handle: &FocusHandle) -> Focusable { self.interactivity().focusable = true; - self.interactivity().tracked_focus_handle = Some(focus_handle); + self.interactivity().tracked_focus_handle = Some(focus_handle.clone()); Focusable { element: self, view_type: PhantomData, @@ -269,8 +274,27 @@ pub trait InteractiveComponent: Sized + Element { } pub trait StatefulInteractiveComponent>: InteractiveComponent { - fn focusable(mut self) -> Self { + fn focusable(mut self) -> Focusable { self.interactivity().focusable = true; + Focusable { + element: self, + view_type: PhantomData, + } + } + + fn overflow_scroll(mut self) -> Self { + self.interactivity().base_style.overflow.x = Some(Overflow::Scroll); + self.interactivity().base_style.overflow.y = Some(Overflow::Scroll); + self + } + + fn overflow_x_scroll(mut self) -> Self { + self.interactivity().base_style.overflow.x = Some(Overflow::Scroll); + self + } + + fn overflow_y_scroll(mut self) -> Self { + self.interactivity().base_style.overflow.y = Some(Overflow::Scroll); self } @@ -514,16 +538,16 @@ pub type KeyUpListener = pub type ActionListener = Box) + 'static>; -pub fn node() -> Node { +pub fn div() -> Node { Node { interactivity: Interactivity::default(), - children: Vec::default(), + children: SmallVec::default(), } } pub struct Node { interactivity: Interactivity, - children: Vec>, + children: SmallVec<[AnyElement; 2]>, } impl Styled for Node { @@ -538,10 +562,16 @@ impl InteractiveComponent for Node { } } +impl ParentComponent for Node { + fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { + &mut self.children + } +} + impl Element for Node { type ElementState = NodeState; - fn id(&self) -> Option { + fn element_id(&self) -> Option { self.interactivity.element_id.clone() } @@ -641,48 +671,54 @@ impl Element for Node { } } +impl Component for Node { + fn render(self) -> AnyElement { + AnyElement::new(self) + } +} + pub struct NodeState { child_layout_ids: SmallVec<[LayoutId; 4]>, interactive_state: InteractiveElementState, } pub struct Interactivity { - element_id: Option, - key_context: KeyContext, - focusable: bool, - tracked_focus_handle: Option, - focus_listeners: FocusListeners, - scroll_offset: Point, - group: Option, - base_style: StyleRefinement, - focus_style: StyleRefinement, - focus_in_style: StyleRefinement, - in_focus_style: StyleRefinement, - hover_style: StyleRefinement, - group_hover_style: Option, - active_style: StyleRefinement, - group_active_style: Option, - drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>, - group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>, - mouse_down_listeners: SmallVec<[MouseDownListener; 2]>, - mouse_up_listeners: SmallVec<[MouseUpListener; 2]>, - mouse_move_listeners: SmallVec<[MouseMoveListener; 2]>, - scroll_wheel_listeners: SmallVec<[ScrollWheelListener; 2]>, - key_down_listeners: SmallVec<[KeyDownListener; 2]>, - key_up_listeners: SmallVec<[KeyUpListener; 2]>, - action_listeners: SmallVec<[(TypeId, ActionListener); 8]>, - drop_listeners: SmallVec<[(TypeId, Box>); 2]>, - click_listeners: SmallVec<[ClickListener; 2]>, - drag_listener: Option>, - hover_listener: Option>, - tooltip_builder: Option>, + pub element_id: Option, + pub key_context: KeyContext, + pub focusable: bool, + pub tracked_focus_handle: Option, + pub focus_listeners: FocusListeners, + // pub scroll_offset: Point, + pub group: Option, + pub base_style: StyleRefinement, + pub focus_style: StyleRefinement, + pub focus_in_style: StyleRefinement, + pub in_focus_style: StyleRefinement, + pub hover_style: StyleRefinement, + pub group_hover_style: Option, + pub active_style: StyleRefinement, + pub group_active_style: Option, + pub drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>, + pub group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>, + pub mouse_down_listeners: SmallVec<[MouseDownListener; 2]>, + pub mouse_up_listeners: SmallVec<[MouseUpListener; 2]>, + pub mouse_move_listeners: SmallVec<[MouseMoveListener; 2]>, + pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener; 2]>, + pub key_down_listeners: SmallVec<[KeyDownListener; 2]>, + pub key_up_listeners: SmallVec<[KeyUpListener; 2]>, + pub action_listeners: SmallVec<[(TypeId, ActionListener); 8]>, + pub drop_listeners: SmallVec<[(TypeId, Box>); 2]>, + pub click_listeners: SmallVec<[ClickListener; 2]>, + pub drag_listener: Option>, + pub hover_listener: Option>, + pub tooltip_builder: Option>, } impl Interactivity where V: 'static, { - fn initialize( + pub fn initialize( &mut self, element_state: Option, cx: &mut ViewContext, @@ -703,7 +739,7 @@ where element_state } - fn layout( + pub fn layout( &mut self, element_state: &mut InteractiveElementState, cx: &mut ViewContext, @@ -719,7 +755,7 @@ where }) } - fn paint( + pub fn paint( &mut self, bounds: Bounds, content_size: Size, @@ -996,6 +1032,11 @@ where GroupBounds::push(group, bounds, cx); } + let scroll_offset = element_state + .scroll_offset + .as_ref() + .map(|scroll_offset| *scroll_offset.lock()); + cx.with_element_id(self.element_id.clone(), |cx| { cx.with_key_dispatch( self.key_context.clone(), @@ -1026,7 +1067,7 @@ where } } - f(style, self.scroll_offset, cx) + f(style, scroll_offset.unwrap_or_default(), cx) }, ); }); @@ -1036,7 +1077,7 @@ where } } - fn compute_style( + pub fn compute_style( &self, bounds: Option>, element_state: &mut InteractiveElementState, @@ -1118,7 +1159,7 @@ impl Default for Interactivity { focusable: false, tracked_focus_handle: None, focus_listeners: SmallVec::default(), - scroll_offset: Point::default(), + // scroll_offset: Point::default(), group: None, base_style: StyleRefinement::default(), focus_style: StyleRefinement::default(), @@ -1148,15 +1189,15 @@ impl Default for Interactivity { #[derive(Default)] pub struct InteractiveElementState { - focus_handle: Option, - clicked_state: Arc>, - hover_state: Arc>, - pending_mouse_down: Arc>>, - scroll_offset: Option>>>, - active_tooltip: Arc>>, + pub focus_handle: Option, + pub clicked_state: Arc>, + pub hover_state: Arc>, + pub pending_mouse_down: Arc>>, + pub scroll_offset: Option>>>, + pub active_tooltip: Arc>>, } -struct ActiveTooltip { +pub struct ActiveTooltip { #[allow(unused)] // used to drop the task waiting: Option>, tooltip: Option, @@ -1164,7 +1205,7 @@ struct ActiveTooltip { /// Whether or not the element or a group that contains it is clicked by the mouse. #[derive(Copy, Clone, Default, Eq, PartialEq)] -struct ElementClickedState { +pub struct ElementClickedState { pub group: bool, pub element: bool, } @@ -1222,6 +1263,16 @@ impl> StatefulInteractiveCompo { } +impl Styled for Focusable +where + V: 'static, + E: Styled, +{ + fn style(&mut self) -> &mut StyleRefinement { + self.element.style() + } +} + impl Element for Focusable where V: 'static, @@ -1229,8 +1280,8 @@ where { type ElementState = E::ElementState; - fn id(&self) -> Option { - self.element.id() + fn element_id(&self) -> Option { + self.element.element_id() } fn initialize( @@ -1262,11 +1313,41 @@ where } } +impl Component for Focusable +where + V: 'static, + E: 'static + Element, +{ + fn render(self) -> AnyElement { + AnyElement::new(self) + } +} + +impl ParentComponent for Focusable +where + V: 'static, + E: ParentComponent, +{ + fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { + self.element.children_mut() + } +} + pub struct Stateful { element: E, view_type: PhantomData, } +impl Styled for Stateful +where + V: 'static, + E: Styled, +{ + fn style(&mut self) -> &mut StyleRefinement { + self.element.style() + } +} + impl StatefulInteractiveComponent for Stateful where V: 'static, @@ -1294,8 +1375,8 @@ where { type ElementState = E::ElementState; - fn id(&self) -> Option { - self.element.id() + fn element_id(&self) -> Option { + self.element.element_id() } fn initialize( @@ -1326,3 +1407,23 @@ where self.element.paint(bounds, view_state, element_state, cx) } } + +impl Component for Stateful +where + V: 'static, + E: 'static + Element, +{ + fn render(self) -> AnyElement { + AnyElement::new(self) + } +} + +impl ParentComponent for Stateful +where + V: 'static, + E: ParentComponent, +{ + fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { + self.element.children_mut() + } +} diff --git a/crates/gpui2/src/elements/svg.rs b/crates/gpui2/src/elements/svg.rs index bafedb7f2d8469f4c143b59d6f8c743710ebef8e..d0b321c0e2619deb31c04efbff63954712037f53 100644 --- a/crates/gpui2/src/elements/svg.rs +++ b/crates/gpui2/src/elements/svg.rs @@ -1,69 +1,40 @@ use crate::{ - div, AnyElement, Bounds, Component, Div, DivState, Element, ElementId, ElementInteractivity, - FocusListeners, Focusable, FocusableKeyDispatch, KeyDispatch, LayoutId, - NonFocusableKeyDispatch, Pixels, SharedString, StatefulInteractive, StatefulInteractivity, - StatelessInteractive, StatelessInteractivity, StyleRefinement, Styled, ViewContext, + AnyElement, Bounds, Component, Element, ElementId, InteractiveComponent, + InteractiveElementState, Interactivity, LayoutId, Pixels, SharedString, StyleRefinement, + Styled, ViewContext, }; use util::ResultExt; -pub struct Svg< - V: 'static, - I: ElementInteractivity = StatelessInteractivity, - F: KeyDispatch = NonFocusableKeyDispatch, -> { - base: Div, +pub struct Svg { + interactivity: Interactivity, path: Option, } -pub fn svg() -> Svg, NonFocusableKeyDispatch> { +pub fn svg() -> Svg { Svg { - base: div(), + interactivity: Interactivity::default(), path: None, } } -impl Svg -where - I: ElementInteractivity, - F: KeyDispatch, -{ +impl Svg { pub fn path(mut self, path: impl Into) -> Self { self.path = Some(path.into()); self } } -impl Svg, F> -where - F: KeyDispatch, -{ - pub fn id(self, id: impl Into) -> Svg, F> { - Svg { - base: self.base.id(id), - path: self.path, - } - } -} - -impl Component for Svg -where - I: ElementInteractivity, - F: KeyDispatch, -{ +impl Component for Svg { fn render(self) -> AnyElement { AnyElement::new(self) } } -impl Element for Svg -where - I: ElementInteractivity, - F: KeyDispatch, -{ - type ElementState = DivState; +impl Element for Svg { + type ElementState = InteractiveElementState; - fn id(&self) -> Option { - self.base.id() + fn element_id(&self) -> Option { + self.interactivity.element_id.clone() } fn initialize( @@ -72,7 +43,7 @@ where element_state: Option, cx: &mut ViewContext, ) -> Self::ElementState { - self.base.initialize(view_state, element_state, cx) + self.interactivity.initialize(element_state, cx) } fn layout( @@ -81,7 +52,9 @@ where element_state: &mut Self::ElementState, cx: &mut ViewContext, ) -> LayoutId { - self.base.layout(view_state, element_state, cx) + self.interactivity.layout(element_state, cx, |style, cx| { + cx.request_layout(&style, None) + }) } fn paint( @@ -93,65 +66,23 @@ where ) where Self: Sized, { - self.base.paint(bounds, view, element_state, cx); - let color = self - .base - .compute_style(bounds, element_state, cx) - .text - .color; - if let Some((path, color)) = self.path.as_ref().zip(color) { - cx.paint_svg(bounds, path.clone(), color).log_err(); - } + self.interactivity + .paint(bounds, bounds.size, element_state, cx, |style, _, cx| { + if let Some((path, color)) = self.path.as_ref().zip(style.text.color) { + cx.paint_svg(bounds, path.clone(), color).log_err(); + } + }) } } -impl Styled for Svg -where - I: ElementInteractivity, - F: KeyDispatch, -{ +impl Styled for Svg { fn style(&mut self) -> &mut StyleRefinement { - self.base.style() - } -} - -impl StatelessInteractive for Svg -where - I: ElementInteractivity, - F: KeyDispatch, -{ - fn stateless_interactivity(&mut self) -> &mut StatelessInteractivity { - self.base.stateless_interactivity() + &mut self.interactivity.base_style } } -impl StatefulInteractive for Svg, F> -where - V: 'static, - F: KeyDispatch, -{ - fn stateful_interactivity(&mut self) -> &mut StatefulInteractivity { - self.base.stateful_interactivity() - } -} - -impl Focusable for Svg> -where - I: ElementInteractivity, -{ - fn focus_listeners(&mut self) -> &mut FocusListeners { - self.base.focus_listeners() - } - - fn set_focus_style(&mut self, style: StyleRefinement) { - self.base.set_focus_style(style) - } - - fn set_focus_in_style(&mut self, style: StyleRefinement) { - self.base.set_focus_in_style(style) - } - - fn set_in_focus_style(&mut self, style: StyleRefinement) { - self.base.set_in_focus_style(style) +impl InteractiveComponent for Svg { + fn interactivity(&mut self) -> &mut Interactivity { + &mut self.interactivity } } diff --git a/crates/gpui2/src/elements/text.rs b/crates/gpui2/src/elements/text.rs index 5c5709d32e5a12e247726789a35dfd21806c6c7c..8688581cb8c12e1a03ef0765f7aea0396143e33d 100644 --- a/crates/gpui2/src/elements/text.rs +++ b/crates/gpui2/src/elements/text.rs @@ -53,7 +53,7 @@ impl Component for Text { impl Element for Text { type ElementState = Arc>>; - fn id(&self) -> Option { + fn element_id(&self) -> Option { None } diff --git a/crates/gpui2/src/elements/uniform_list.rs b/crates/gpui2/src/elements/uniform_list.rs index 521df8699a47fb4ec7f0590fcff8f8fee83a0fbf..2f6584cda5b25599f8b916fb271b490824f36a27 100644 --- a/crates/gpui2/src/elements/uniform_list.rs +++ b/crates/gpui2/src/elements/uniform_list.rs @@ -1,24 +1,23 @@ use crate::{ point, px, size, AnyElement, AvailableSpace, BorrowWindow, Bounds, Component, Element, - ElementId, ElementInteractivity, InteractiveElementState, LayoutId, Pixels, Point, Size, - StatefulInteractive, StatefulInteractivity, StatelessInteractive, StatelessInteractivity, - StyleRefinement, Styled, ViewContext, + ElementId, InteractiveComponent, InteractiveElementState, Interactivity, LayoutId, Pixels, + Point, Size, StyleRefinement, Styled, ViewContext, }; use parking_lot::Mutex; use smallvec::SmallVec; -use std::{cmp, ops::Range, sync::Arc}; +use std::{cmp, mem, ops::Range, sync::Arc}; use taffy::style::Overflow; /// uniform_list provides lazy rendering for a set of items that are of uniform height. /// When rendered into a container with overflow-y: hidden and a fixed (or max) height, /// uniform_list will only render the visibile subset of items. -pub fn uniform_list( - id: Id, +pub fn uniform_list( + id: I, item_count: usize, f: impl 'static + Fn(&mut V, Range, &mut ViewContext) -> SmallVec<[C; 64]>, ) -> UniformList where - Id: Into, + I: Into, V: 'static, C: Component, { @@ -37,7 +36,10 @@ where .map(|component| component.render()) .collect() }), - interactivity: StatefulInteractivity::new(id, StatelessInteractivity::default()), + interactivity: Interactivity { + element_id: Some(id.into()), + ..Default::default() + }, scroll_handle: None, } } @@ -54,7 +56,7 @@ pub struct UniformList { &'a mut ViewContext, ) -> SmallVec<[AnyElement; 64]>, >, - interactivity: StatefulInteractivity, + interactivity: Interactivity, scroll_handle: Option, } @@ -103,7 +105,7 @@ pub struct UniformListState { impl Element for UniformList { type ElementState = UniformListState; - fn id(&self) -> Option { + fn element_id(&self) -> Option { Some(self.id.clone()) } @@ -113,13 +115,18 @@ impl Element for UniformList { element_state: Option, cx: &mut ViewContext, ) -> Self::ElementState { - element_state.unwrap_or_else(|| { + if let Some(mut element_state) = element_state { + element_state.interactive = self + .interactivity + .initialize(Some(element_state.interactive), cx); + element_state + } else { let item_size = self.measure_item(view_state, None, cx); UniformListState { - interactive: InteractiveElementState::default(), + interactive: self.interactivity.initialize(None, cx), item_size, } - }) + } } fn layout( @@ -132,35 +139,44 @@ impl Element for UniformList { let item_size = element_state.item_size; let rem_size = cx.rem_size(); - cx.request_measured_layout( - self.computed_style(), - rem_size, - move |known_dimensions: Size>, available_space: Size| { - let desired_height = item_size.height * max_items; - let width = known_dimensions - .width - .unwrap_or(match available_space.width { - AvailableSpace::Definite(x) => x, - AvailableSpace::MinContent | AvailableSpace::MaxContent => item_size.width, - }); - let height = match available_space.height { - AvailableSpace::Definite(x) => desired_height.min(x), - AvailableSpace::MinContent | AvailableSpace::MaxContent => desired_height, - }; - size(width, height) - }, - ) + self.interactivity + .layout(&mut element_state.interactive, cx, |style, cx| { + cx.request_measured_layout( + style, + rem_size, + move |known_dimensions: Size>, + available_space: Size| { + let desired_height = item_size.height * max_items; + let width = known_dimensions + .width + .unwrap_or(match available_space.width { + AvailableSpace::Definite(x) => x, + AvailableSpace::MinContent | AvailableSpace::MaxContent => { + item_size.width + } + }); + let height = match available_space.height { + AvailableSpace::Definite(x) => desired_height.min(x), + AvailableSpace::MinContent | AvailableSpace::MaxContent => { + desired_height + } + }; + size(width, height) + }, + ) + }) } fn paint( &mut self, - bounds: crate::Bounds, + bounds: Bounds, view_state: &mut V, element_state: &mut Self::ElementState, cx: &mut ViewContext, ) { - let style = self.computed_style(); - + let style = + self.interactivity + .compute_style(Some(bounds), &mut element_state.interactive, cx); let border = style.border_widths.to_pixels(cx.rem_size()); let padding = style.padding.to_pixels(bounds.size.into(), cx.rem_size()); @@ -170,74 +186,75 @@ impl Element for UniformList { - point(border.right + padding.right, border.bottom + padding.bottom), ); - cx.with_z_index(style.z_index.unwrap_or(0), |cx| { - style.paint(bounds, cx); + let item_size = element_state.item_size; + let content_size = Size { + width: padded_bounds.size.width, + height: item_size.height * self.item_count, + }; - let content_size; - if self.item_count > 0 { - let item_height = self - .measure_item(view_state, Some(padded_bounds.size.width), cx) - .height; - if let Some(scroll_handle) = self.scroll_handle.clone() { - scroll_handle.0.lock().replace(ScrollHandleState { - item_height, - list_height: padded_bounds.size.height, - scroll_offset: element_state.interactive.track_scroll_offset(), - }); - } - let visible_item_count = if item_height > px(0.) { - (padded_bounds.size.height / item_height).ceil() as usize + 1 - } else { - 0 - }; - let scroll_offset = element_state - .interactive - .scroll_offset() - .map_or((0.0).into(), |offset| offset.y); - let first_visible_element_ix = (-scroll_offset / item_height).floor() as usize; - let visible_range = first_visible_element_ix - ..cmp::min( - first_visible_element_ix + visible_item_count, - self.item_count, - ); + let mut interactivity = mem::take(&mut self.interactivity); + let shared_scroll_offset = element_state.interactive.scroll_offset.clone().unwrap(); - let mut items = (self.render_items)(view_state, visible_range.clone(), cx); + interactivity.paint( + bounds, + content_size, + &mut element_state.interactive, + cx, + |style, scroll_offset, cx| { + let border = style.border_widths.to_pixels(cx.rem_size()); + let padding = style.padding.to_pixels(bounds.size.into(), cx.rem_size()); - content_size = Size { - width: padded_bounds.size.width, - height: item_height * self.item_count, - }; + let padded_bounds = Bounds::from_corners( + bounds.origin + point(border.left + padding.left, border.top + padding.top), + bounds.lower_right() + - point(border.right + padding.right, border.bottom + padding.bottom), + ); - cx.with_z_index(1, |cx| { - for (item, ix) in items.iter_mut().zip(visible_range) { - let item_origin = - padded_bounds.origin + point(px(0.), item_height * ix + scroll_offset); - let available_space = size( - AvailableSpace::Definite(padded_bounds.size.width), - AvailableSpace::Definite(item_height), - ); - item.draw(item_origin, available_space, view_state, cx); - } - }); - } else { - content_size = Size { - width: bounds.size.width, - height: px(0.), - }; - } + cx.with_z_index(style.z_index.unwrap_or(0), |cx| { + style.paint(bounds, cx); - let overflow = point(style.overflow.x, Overflow::Scroll); + if self.item_count > 0 { + let item_height = self + .measure_item(view_state, Some(padded_bounds.size.width), cx) + .height; + if let Some(scroll_handle) = self.scroll_handle.clone() { + scroll_handle.0.lock().replace(ScrollHandleState { + item_height, + list_height: padded_bounds.size.height, + scroll_offset: shared_scroll_offset, + }); + } + let visible_item_count = if item_height > px(0.) { + (padded_bounds.size.height / item_height).ceil() as usize + 1 + } else { + 0 + }; - cx.with_z_index(0, |cx| { - self.interactivity.handle_events( - bounds, - content_size, - overflow, - &mut element_state.interactive, - cx, - ); - }); - }) + let first_visible_element_ix = + (-scroll_offset.y / item_height).floor() as usize; + let visible_range = first_visible_element_ix + ..cmp::min( + first_visible_element_ix + visible_item_count, + self.item_count, + ); + + let mut items = (self.render_items)(view_state, visible_range.clone(), cx); + cx.with_z_index(1, |cx| { + for (item, ix) in items.iter_mut().zip(visible_range) { + let item_origin = padded_bounds.origin + + point(px(0.), item_height * ix + scroll_offset.y); + let available_space = size( + AvailableSpace::Definite(padded_bounds.size.width), + AvailableSpace::Definite(item_height), + ); + item.draw(item_origin, available_space, view_state, cx); + } + }); + } + }) + }, + ); + self.interactivity = interactivity; } } @@ -275,14 +292,8 @@ impl UniformList { } } -impl StatelessInteractive for UniformList { - fn stateless_interactivity(&mut self) -> &mut StatelessInteractivity { - self.interactivity.as_stateless_mut() - } -} - -impl StatefulInteractive for UniformList { - fn stateful_interactivity(&mut self) -> &mut StatefulInteractivity { +impl InteractiveComponent for UniformList { + fn interactivity(&mut self) -> &mut crate::Interactivity { &mut self.interactivity } } diff --git a/crates/gpui2/src/interactive.rs b/crates/gpui2/src/interactive.rs index f896bfc439c1c09c58a281d9e900a60e3589004f..702a7ca5dbfacf0849e5496f991e8effa3183815 100644 --- a/crates/gpui2/src/interactive.rs +++ b/crates/gpui2/src/interactive.rs @@ -1,915 +1,17 @@ use crate::{ - div, point, px, Action, AnyDrag, AnyTooltip, AnyView, AppContext, Bounds, Component, - DispatchPhase, Div, Element, ElementId, FocusHandle, KeyContext, Keystroke, Modifiers, - Overflow, Pixels, Point, Render, SharedString, Size, Style, StyleRefinement, Task, View, - ViewContext, + div, point, px, AnyDrag, AnyTooltip, AnyView, AppContext, Bounds, Component, DispatchPhase, + FocusHandle, Keystroke, Modifiers, Node, Pixels, Point, Render, SharedString, StyleRefinement, + Task, ViewContext, }; -use collections::HashMap; -use derive_more::{Deref, DerefMut}; -use parking_lot::Mutex; -use refineable::Refineable; use smallvec::SmallVec; use std::{ - any::{Any, TypeId}, - fmt::Debug, - marker::PhantomData, - mem, - ops::Deref, - path::PathBuf, - sync::Arc, - time::Duration, + any::Any, fmt::Debug, marker::PhantomData, ops::Deref, path::PathBuf, sync::Arc, time::Duration, }; const DRAG_THRESHOLD: f64 = 2.; const TOOLTIP_DELAY: Duration = Duration::from_millis(500); const TOOLTIP_OFFSET: Point = Point::new(px(10.0), px(8.0)); -pub trait StatelessInteractive: Element { - fn stateless_interactivity(&mut self) -> &mut StatelessInteractivity; - - fn hover(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self - where - Self: Sized, - { - self.stateless_interactivity().hover_style = f(StyleRefinement::default()); - self - } - - fn group_hover( - mut self, - group_name: impl Into, - f: impl FnOnce(StyleRefinement) -> StyleRefinement, - ) -> Self - where - Self: Sized, - { - self.stateless_interactivity().group_hover_style = Some(GroupStyle { - group: group_name.into(), - style: f(StyleRefinement::default()), - }); - self - } - - fn on_mouse_down( - mut self, - button: MouseButton, - handler: impl Fn(&mut V, &MouseDownEvent, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { - self.stateless_interactivity() - .mouse_down_listeners - .push(Box::new(move |view, event, bounds, phase, cx| { - if phase == DispatchPhase::Bubble - && event.button == button - && bounds.contains_point(&event.position) - { - handler(view, event, cx) - } - })); - self - } - - fn on_mouse_up( - mut self, - button: MouseButton, - handler: impl Fn(&mut V, &MouseUpEvent, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { - self.stateless_interactivity() - .mouse_up_listeners - .push(Box::new(move |view, event, bounds, phase, cx| { - if phase == DispatchPhase::Bubble - && event.button == button - && bounds.contains_point(&event.position) - { - handler(view, event, cx) - } - })); - self - } - - fn on_mouse_down_out( - mut self, - handler: impl Fn(&mut V, &MouseDownEvent, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { - self.stateless_interactivity() - .mouse_down_listeners - .push(Box::new(move |view, event, bounds, phase, cx| { - if phase == DispatchPhase::Capture && !bounds.contains_point(&event.position) { - handler(view, event, cx) - } - })); - self - } - - fn on_mouse_up_out( - mut self, - button: MouseButton, - handler: impl Fn(&mut V, &MouseUpEvent, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { - self.stateless_interactivity() - .mouse_up_listeners - .push(Box::new(move |view, event, bounds, phase, cx| { - if phase == DispatchPhase::Capture - && event.button == button - && !bounds.contains_point(&event.position) - { - handler(view, event, cx); - } - })); - self - } - - fn on_mouse_move( - mut self, - handler: impl Fn(&mut V, &MouseMoveEvent, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { - self.stateless_interactivity() - .mouse_move_listeners - .push(Box::new(move |view, event, bounds, phase, cx| { - if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { - handler(view, event, cx); - } - })); - self - } - - fn on_scroll_wheel( - mut self, - handler: impl Fn(&mut V, &ScrollWheelEvent, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { - self.stateless_interactivity() - .scroll_wheel_listeners - .push(Box::new(move |view, event, bounds, phase, cx| { - if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { - handler(view, event, cx); - } - })); - self - } - - /// Capture the given action, fires during the capture phase - fn capture_action( - mut self, - listener: impl Fn(&mut V, &A, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { - self.stateless_interactivity().action_listeners.push(( - TypeId::of::(), - Box::new(move |view, action, phase, cx| { - let action = action.downcast_ref().unwrap(); - if phase == DispatchPhase::Capture { - listener(view, action, cx) - } - }), - )); - self - } - - /// Add a listener for the given action, fires during the bubble event phase - fn on_action( - mut self, - listener: impl Fn(&mut V, &A, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { - self.stateless_interactivity().action_listeners.push(( - TypeId::of::(), - Box::new(move |view, action, phase, cx| { - let action = action.downcast_ref().unwrap(); - if phase == DispatchPhase::Bubble { - listener(view, action, cx) - } - }), - )); - self - } - - fn on_key_down( - mut self, - listener: impl Fn(&mut V, &KeyDownEvent, DispatchPhase, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { - self.stateless_interactivity() - .key_down_listeners - .push(Box::new(move |view, event, phase, cx| { - listener(view, event, phase, cx) - })); - self - } - - fn on_key_up( - mut self, - listener: impl Fn(&mut V, &KeyUpEvent, DispatchPhase, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { - self.stateless_interactivity() - .key_up_listeners - .push(Box::new(move |view, event, phase, cx| { - listener(view, event, phase, cx) - })); - self - } - - fn drag_over(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self - where - Self: Sized, - { - self.stateless_interactivity() - .drag_over_styles - .push((TypeId::of::(), f(StyleRefinement::default()))); - self - } - - fn group_drag_over( - mut self, - group_name: impl Into, - f: impl FnOnce(StyleRefinement) -> StyleRefinement, - ) -> Self - where - Self: Sized, - { - self.stateless_interactivity().group_drag_over_styles.push(( - TypeId::of::(), - GroupStyle { - group: group_name.into(), - style: f(StyleRefinement::default()), - }, - )); - self - } - - fn on_drop( - mut self, - listener: impl Fn(&mut V, View, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { - self.stateless_interactivity().drop_listeners.push(( - TypeId::of::(), - Box::new(move |view, dragged_view, cx| { - listener(view, dragged_view.downcast().unwrap(), cx); - }), - )); - self - } -} - -pub trait StatefulInteractive: StatelessInteractive { - fn stateful_interactivity(&mut self) -> &mut StatefulInteractivity; - - fn active(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self - where - Self: Sized, - { - self.stateful_interactivity().active_style = f(StyleRefinement::default()); - self - } - - fn group_active( - mut self, - group_name: impl Into, - f: impl FnOnce(StyleRefinement) -> StyleRefinement, - ) -> Self - where - Self: Sized, - { - self.stateful_interactivity().group_active_style = Some(GroupStyle { - group: group_name.into(), - style: f(StyleRefinement::default()), - }); - self - } - - fn on_click( - mut self, - listener: impl Fn(&mut V, &ClickEvent, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { - self.stateful_interactivity() - .click_listeners - .push(Box::new(move |view, event, cx| listener(view, event, cx))); - self - } - - fn on_drag( - mut self, - listener: impl Fn(&mut V, &mut ViewContext) -> View + 'static, - ) -> Self - where - Self: Sized, - W: 'static + Render, - { - debug_assert!( - self.stateful_interactivity().drag_listener.is_none(), - "calling on_drag more than once on the same element is not supported" - ); - self.stateful_interactivity().drag_listener = - Some(Box::new(move |view_state, cursor_offset, cx| AnyDrag { - view: listener(view_state, cx).into(), - cursor_offset, - })); - self - } - - fn on_hover(mut self, listener: impl 'static + Fn(&mut V, bool, &mut ViewContext)) -> Self - where - Self: Sized, - { - debug_assert!( - self.stateful_interactivity().hover_listener.is_none(), - "calling on_hover more than once on the same element is not supported" - ); - self.stateful_interactivity().hover_listener = Some(Box::new(listener)); - self - } - - fn tooltip( - mut self, - build_tooltip: impl Fn(&mut V, &mut ViewContext) -> View + 'static, - ) -> Self - where - Self: Sized, - W: 'static + Render, - { - debug_assert!( - self.stateful_interactivity().tooltip_builder.is_none(), - "calling tooltip more than once on the same element is not supported" - ); - self.stateful_interactivity().tooltip_builder = Some(Arc::new(move |view_state, cx| { - build_tooltip(view_state, cx).into() - })); - - self - } -} - -pub trait ElementInteractivity: 'static { - fn as_stateless(&self) -> &StatelessInteractivity; - fn as_stateless_mut(&mut self) -> &mut StatelessInteractivity; - fn as_stateful(&self) -> Option<&StatefulInteractivity>; - fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteractivity>; - - fn refine_style( - &self, - style: &mut Style, - bounds: Bounds, - element_state: &InteractiveElementState, - cx: &mut ViewContext, - ) { - let mouse_position = cx.mouse_position(); - let stateless = self.as_stateless(); - if let Some(group_hover) = stateless.group_hover_style.as_ref() { - if let Some(group_bounds) = GroupBounds::get(&group_hover.group, cx) { - if group_bounds.contains_point(&mouse_position) { - style.refine(&group_hover.style); - } - } - } - if bounds.contains_point(&mouse_position) { - style.refine(&stateless.hover_style); - } - - if let Some(drag) = cx.active_drag.take() { - for (state_type, group_drag_style) in &self.as_stateless().group_drag_over_styles { - if let Some(group_bounds) = GroupBounds::get(&group_drag_style.group, cx) { - if *state_type == drag.view.entity_type() - && group_bounds.contains_point(&mouse_position) - { - style.refine(&group_drag_style.style); - } - } - } - - for (state_type, drag_over_style) in &self.as_stateless().drag_over_styles { - if *state_type == drag.view.entity_type() && bounds.contains_point(&mouse_position) - { - style.refine(drag_over_style); - } - } - - cx.active_drag = Some(drag); - } - - if let Some(stateful) = self.as_stateful() { - let active_state = element_state.active_state.lock(); - if active_state.group { - if let Some(group_style) = stateful.group_active_style.as_ref() { - style.refine(&group_style.style); - } - } - if active_state.element { - style.refine(&stateful.active_style); - } - } - } - - fn initialize(&mut self, cx: &mut ViewContext) { - let stateless = self.as_stateless_mut(); - - for listener in stateless.key_down_listeners.drain(..) { - cx.on_key_event(move |state, event: &KeyDownEvent, phase, cx| { - listener(state, event, phase, cx); - }) - } - - for listener in stateless.key_up_listeners.drain(..) { - cx.on_key_event(move |state, event: &KeyUpEvent, phase, cx| { - listener(state, event, phase, cx); - }) - } - - for (action_type, listener) in stateless.action_listeners.drain(..) { - cx.on_action(action_type, listener) - } - } - - fn handle_events( - &mut self, - bounds: Bounds, - content_size: Size, - overflow: Point, - element_state: &mut InteractiveElementState, - cx: &mut ViewContext, - ) { - let stateless = self.as_stateless_mut(); - for listener in stateless.mouse_down_listeners.drain(..) { - cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| { - listener(state, event, &bounds, phase, cx); - }) - } - - for listener in stateless.mouse_up_listeners.drain(..) { - cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| { - listener(state, event, &bounds, phase, cx); - }) - } - - for listener in stateless.mouse_move_listeners.drain(..) { - cx.on_mouse_event(move |state, event: &MouseMoveEvent, phase, cx| { - listener(state, event, &bounds, phase, cx); - }) - } - - for listener in stateless.scroll_wheel_listeners.drain(..) { - cx.on_mouse_event(move |state, event: &ScrollWheelEvent, phase, cx| { - listener(state, event, &bounds, phase, cx); - }) - } - - let hover_group_bounds = stateless - .group_hover_style - .as_ref() - .and_then(|group_hover| GroupBounds::get(&group_hover.group, cx)); - - if let Some(group_bounds) = hover_group_bounds { - let hovered = group_bounds.contains_point(&cx.mouse_position()); - cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| { - if phase == DispatchPhase::Capture { - if group_bounds.contains_point(&event.position) != hovered { - cx.notify(); - } - } - }); - } - - if stateless.hover_style.is_some() - || (cx.active_drag.is_some() && !stateless.drag_over_styles.is_empty()) - { - let hovered = bounds.contains_point(&cx.mouse_position()); - cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| { - if phase == DispatchPhase::Capture { - if bounds.contains_point(&event.position) != hovered { - cx.notify(); - } - } - }); - } - - if cx.active_drag.is_some() { - let drop_listeners = mem::take(&mut stateless.drop_listeners); - cx.on_mouse_event(move |view, event: &MouseUpEvent, phase, cx| { - if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { - if let Some(drag_state_type) = - cx.active_drag.as_ref().map(|drag| drag.view.entity_type()) - { - for (drop_state_type, listener) in &drop_listeners { - if *drop_state_type == drag_state_type { - let drag = cx - .active_drag - .take() - .expect("checked for type drag state type above"); - listener(view, drag.view.clone(), cx); - cx.notify(); - cx.stop_propagation(); - } - } - } - } - }); - } - - if let Some(stateful) = self.as_stateful_mut() { - let click_listeners = mem::take(&mut stateful.click_listeners); - let drag_listener = mem::take(&mut stateful.drag_listener); - - if !click_listeners.is_empty() || drag_listener.is_some() { - let pending_mouse_down = element_state.pending_mouse_down.clone(); - let mouse_down = pending_mouse_down.lock().clone(); - if let Some(mouse_down) = mouse_down { - if let Some(drag_listener) = drag_listener { - let active_state = element_state.active_state.clone(); - - cx.on_mouse_event(move |view_state, event: &MouseMoveEvent, phase, cx| { - if cx.active_drag.is_some() { - if phase == DispatchPhase::Capture { - cx.notify(); - } - } else if phase == DispatchPhase::Bubble - && bounds.contains_point(&event.position) - && (event.position - mouse_down.position).magnitude() - > DRAG_THRESHOLD - { - *active_state.lock() = ActiveState::default(); - let cursor_offset = event.position - bounds.origin; - let drag = drag_listener(view_state, cursor_offset, cx); - cx.active_drag = Some(drag); - cx.notify(); - cx.stop_propagation(); - } - }); - } - - cx.on_mouse_event(move |view_state, event: &MouseUpEvent, phase, cx| { - if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) - { - let mouse_click = ClickEvent { - down: mouse_down.clone(), - up: event.clone(), - }; - for listener in &click_listeners { - listener(view_state, &mouse_click, cx); - } - } - *pending_mouse_down.lock() = None; - }); - } else { - cx.on_mouse_event(move |_state, event: &MouseDownEvent, phase, _cx| { - if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) - { - *pending_mouse_down.lock() = Some(event.clone()); - } - }); - } - } - - if let Some(hover_listener) = stateful.hover_listener.take() { - let was_hovered = element_state.hover_state.clone(); - let has_mouse_down = element_state.pending_mouse_down.clone(); - - cx.on_mouse_event(move |view_state, event: &MouseMoveEvent, phase, cx| { - if phase != DispatchPhase::Bubble { - return; - } - let is_hovered = - bounds.contains_point(&event.position) && has_mouse_down.lock().is_none(); - let mut was_hovered = was_hovered.lock(); - - if is_hovered != was_hovered.clone() { - *was_hovered = is_hovered; - drop(was_hovered); - - hover_listener(view_state, is_hovered, cx); - } - }); - } - - if let Some(tooltip_builder) = stateful.tooltip_builder.take() { - let active_tooltip = element_state.active_tooltip.clone(); - let pending_mouse_down = element_state.pending_mouse_down.clone(); - - cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| { - if phase != DispatchPhase::Bubble { - return; - } - - let is_hovered = bounds.contains_point(&event.position) - && pending_mouse_down.lock().is_none(); - if !is_hovered { - active_tooltip.lock().take(); - return; - } - - if active_tooltip.lock().is_none() { - let task = cx.spawn({ - let active_tooltip = active_tooltip.clone(); - let tooltip_builder = tooltip_builder.clone(); - - move |view, mut cx| async move { - cx.background_executor().timer(TOOLTIP_DELAY).await; - view.update(&mut cx, move |view_state, cx| { - active_tooltip.lock().replace(ActiveTooltip { - waiting: None, - tooltip: Some(AnyTooltip { - view: tooltip_builder(view_state, cx), - cursor_offset: cx.mouse_position() + TOOLTIP_OFFSET, - }), - }); - cx.notify(); - }) - .ok(); - } - }); - active_tooltip.lock().replace(ActiveTooltip { - waiting: Some(task), - tooltip: None, - }); - } - }); - - if let Some(active_tooltip) = element_state.active_tooltip.lock().as_ref() { - if active_tooltip.tooltip.is_some() { - cx.active_tooltip = active_tooltip.tooltip.clone() - } - } - } - - let active_state = element_state.active_state.clone(); - if active_state.lock().is_none() { - let active_group_bounds = stateful - .group_active_style - .as_ref() - .and_then(|group_active| GroupBounds::get(&group_active.group, cx)); - cx.on_mouse_event(move |_view, down: &MouseDownEvent, phase, cx| { - if phase == DispatchPhase::Bubble { - let group = active_group_bounds - .map_or(false, |bounds| bounds.contains_point(&down.position)); - let element = bounds.contains_point(&down.position); - if group || element { - *active_state.lock() = ActiveState { group, element }; - cx.notify(); - } - } - }); - } else { - cx.on_mouse_event(move |_, _: &MouseUpEvent, phase, cx| { - if phase == DispatchPhase::Capture { - *active_state.lock() = ActiveState::default(); - cx.notify(); - } - }); - } - - if overflow.x == Overflow::Scroll || overflow.y == Overflow::Scroll { - let scroll_offset = element_state - .scroll_offset - .get_or_insert_with(Arc::default) - .clone(); - let line_height = cx.line_height(); - let scroll_max = (content_size - bounds.size).max(&Size::default()); - - cx.on_mouse_event(move |_, event: &ScrollWheelEvent, phase, cx| { - if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { - let mut scroll_offset = scroll_offset.lock(); - let old_scroll_offset = *scroll_offset; - let delta = event.delta.pixel_delta(line_height); - - if overflow.x == Overflow::Scroll { - scroll_offset.x = - (scroll_offset.x + delta.x).clamp(-scroll_max.width, px(0.)); - } - - if overflow.y == Overflow::Scroll { - scroll_offset.y = - (scroll_offset.y + delta.y).clamp(-scroll_max.height, px(0.)); - } - - if *scroll_offset != old_scroll_offset { - cx.notify(); - cx.stop_propagation(); - } - } - }); - } - } - } -} - -#[derive(Deref, DerefMut)] -pub struct StatefulInteractivity { - pub id: ElementId, - #[deref] - #[deref_mut] - stateless: StatelessInteractivity, - click_listeners: SmallVec<[ClickListener; 2]>, - active_style: StyleRefinement, - group_active_style: Option, - drag_listener: Option>, - hover_listener: Option>, - tooltip_builder: Option>, -} - -impl StatefulInteractivity { - pub fn new(id: ElementId, stateless: StatelessInteractivity) -> Self { - Self { - id, - stateless, - click_listeners: SmallVec::new(), - active_style: StyleRefinement::default(), - group_active_style: None, - drag_listener: None, - hover_listener: None, - tooltip_builder: None, - } - } -} - -impl ElementInteractivity for StatefulInteractivity { - fn as_stateful(&self) -> Option<&StatefulInteractivity> { - Some(self) - } - - fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteractivity> { - Some(self) - } - - fn as_stateless(&self) -> &StatelessInteractivity { - &self.stateless - } - - fn as_stateless_mut(&mut self) -> &mut StatelessInteractivity { - &mut self.stateless - } -} - -type DropListener = dyn Fn(&mut V, AnyView, &mut ViewContext) + 'static; - -pub struct StatelessInteractivity { - pub dispatch_context: KeyContext, - pub mouse_down_listeners: SmallVec<[MouseDownListener; 2]>, - pub mouse_up_listeners: SmallVec<[MouseUpListener; 2]>, - pub mouse_move_listeners: SmallVec<[MouseMoveListener; 2]>, - pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener; 2]>, - pub key_down_listeners: SmallVec<[KeyDownListener; 2]>, - pub key_up_listeners: SmallVec<[KeyUpListener; 2]>, - pub action_listeners: SmallVec<[(TypeId, ActionListener); 8]>, - pub hover_style: StyleRefinement, - pub group_hover_style: Option, - drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>, - group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>, - drop_listeners: SmallVec<[(TypeId, Box>); 2]>, -} - -impl StatelessInteractivity { - pub fn into_stateful(self, id: impl Into) -> StatefulInteractivity { - StatefulInteractivity { - id: id.into(), - stateless: self, - click_listeners: SmallVec::new(), - drag_listener: None, - hover_listener: None, - tooltip_builder: None, - active_style: StyleRefinement::default(), - group_active_style: None, - } - } -} - -pub struct GroupStyle { - pub group: SharedString, - pub style: StyleRefinement, -} - -#[derive(Default)] -pub struct GroupBounds(HashMap; 1]>>); - -impl GroupBounds { - pub fn get(name: &SharedString, cx: &mut AppContext) -> Option> { - cx.default_global::() - .0 - .get(name) - .and_then(|bounds_stack| bounds_stack.last()) - .cloned() - } - - pub fn push(name: SharedString, bounds: Bounds, cx: &mut AppContext) { - cx.default_global::() - .0 - .entry(name) - .or_default() - .push(bounds); - } - - pub fn pop(name: &SharedString, cx: &mut AppContext) { - cx.default_global::().0.get_mut(name).unwrap().pop(); - } -} - -#[derive(Copy, Clone, Default, Eq, PartialEq)] -struct ActiveState { - pub group: bool, - pub element: bool, -} - -impl ActiveState { - pub fn is_none(&self) -> bool { - !self.group && !self.element - } -} - -#[derive(Default)] -pub struct InteractiveElementState { - active_state: Arc>, - hover_state: Arc>, - pending_mouse_down: Arc>>, - scroll_offset: Option>>>, - active_tooltip: Arc>>, -} - -struct ActiveTooltip { - #[allow(unused)] // used to drop the task - waiting: Option>, - tooltip: Option, -} - -impl InteractiveElementState { - pub fn scroll_offset(&self) -> Option> { - self.scroll_offset - .as_ref() - .map(|offset| offset.lock().clone()) - } - - pub fn track_scroll_offset(&mut self) -> Arc>> { - self.scroll_offset - .get_or_insert_with(|| Arc::new(Mutex::new(Default::default()))) - .clone() - } -} - -impl Default for StatelessInteractivity { - fn default() -> Self { - Self { - dispatch_context: KeyContext::default(), - mouse_down_listeners: SmallVec::new(), - mouse_up_listeners: SmallVec::new(), - mouse_move_listeners: SmallVec::new(), - scroll_wheel_listeners: SmallVec::new(), - key_down_listeners: SmallVec::new(), - key_up_listeners: SmallVec::new(), - action_listeners: SmallVec::new(), - hover_style: StyleRefinement::default(), - group_hover_style: None, - drag_over_styles: SmallVec::new(), - group_drag_over_styles: SmallVec::new(), - drop_listeners: SmallVec::new(), - } - } -} - -impl ElementInteractivity for StatelessInteractivity { - fn as_stateful(&self) -> Option<&StatefulInteractivity> { - None - } - - fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteractivity> { - None - } - - fn as_stateless(&self) -> &StatelessInteractivity { - self - } - - fn as_stateless_mut(&mut self) -> &mut StatelessInteractivity { - self - } -} - #[derive(Clone, Debug, Eq, PartialEq)] pub struct KeyDownEvent { pub keystroke: Keystroke, @@ -991,10 +93,6 @@ where } } -// impl Render for Drag { -// // fn render(&mut self, cx: ViewContext) -> -// } - #[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)] pub enum MouseButton { Left, @@ -1103,7 +201,7 @@ impl Deref for MouseExitEvent { pub struct ExternalPaths(pub(crate) SmallVec<[PathBuf; 2]>); impl Render for ExternalPaths { - type Element = Div; + type Element = Node; fn render(&mut self, _: &mut ViewContext) -> Self::Element { div() // Intentionally left empty because the platform will render icons for the dragged files @@ -1229,8 +327,8 @@ pub type ActionListener = #[cfg(test)] mod test { use crate::{ - self as gpui, div, Div, FocusHandle, KeyBinding, Keystroke, ParentElement, Render, - StatefulInteractivity, StatelessInteractive, TestAppContext, VisualContext, + self as gpui, div, FocusHandle, InteractiveComponent, KeyBinding, Keystroke, Node, + ParentComponent, Render, Stateful, TestAppContext, VisualContext, }; struct TestView { @@ -1242,12 +340,12 @@ mod test { actions!(TestAction); impl Render for TestView { - type Element = Div>; + type Element = Stateful>; fn render(&mut self, _: &mut gpui::ViewContext) -> Self::Element { div().id("testview").child( div() - .context("test") + .key_context("test") .track_focus(&self.focus_handle) .on_key_down(|this: &mut TestView, _, _, _| this.saw_key_down = true) .on_action(|this: &mut TestView, _: &TestAction, _| this.saw_action = true), diff --git a/crates/gpui2/src/key_dispatch.rs b/crates/gpui2/src/key_dispatch.rs index 8ace4188aed99f0594feddbd6e5b963df7005ebe..afe0b0f3e22e44e34476cb990d1a38e640f9a221 100644 --- a/crates/gpui2/src/key_dispatch.rs +++ b/crates/gpui2/src/key_dispatch.rs @@ -1,7 +1,7 @@ use crate::{ - build_action_from_type, Action, Bounds, DispatchPhase, Element, FocusEvent, FocusHandle, - FocusId, KeyContext, KeyMatch, Keymap, Keystroke, KeystrokeMatcher, MouseDownEvent, Pixels, - Style, StyleRefinement, ViewContext, WindowContext, + build_action_from_type, Action, Bounds, DispatchPhase, FocusEvent, FocusHandle, FocusId, + KeyContext, KeyMatch, Keymap, Keystroke, KeystrokeMatcher, MouseDownEvent, Pixels, Style, + StyleRefinement, ViewContext, WindowContext, }; use collections::HashMap; use parking_lot::Mutex; @@ -342,115 +342,3 @@ impl KeyDispatch for NonFocusableKeyDispatch { &mut self.key_context } } - -pub trait Focusable: Element { - fn focus_listeners(&mut self) -> &mut FocusListeners; - fn set_focus_style(&mut self, style: StyleRefinement); - fn set_focus_in_style(&mut self, style: StyleRefinement); - fn set_in_focus_style(&mut self, style: StyleRefinement); - - fn focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self - where - Self: Sized, - { - self.set_focus_style(f(StyleRefinement::default())); - self - } - - fn focus_in(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self - where - Self: Sized, - { - self.set_focus_in_style(f(StyleRefinement::default())); - self - } - - fn in_focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self - where - Self: Sized, - { - self.set_in_focus_style(f(StyleRefinement::default())); - self - } - - fn on_focus( - mut self, - listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { - self.focus_listeners() - .push(Box::new(move |view, focus_handle, event, cx| { - if event.focused.as_ref() == Some(focus_handle) { - listener(view, event, cx) - } - })); - self - } - - fn on_blur( - mut self, - listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { - self.focus_listeners() - .push(Box::new(move |view, focus_handle, event, cx| { - if event.blurred.as_ref() == Some(focus_handle) { - listener(view, event, cx) - } - })); - self - } - - fn on_focus_in( - mut self, - listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { - self.focus_listeners() - .push(Box::new(move |view, focus_handle, event, cx| { - let descendant_blurred = event - .blurred - .as_ref() - .map_or(false, |blurred| focus_handle.contains(blurred, cx)); - let descendant_focused = event - .focused - .as_ref() - .map_or(false, |focused| focus_handle.contains(focused, cx)); - - if !descendant_blurred && descendant_focused { - listener(view, event, cx) - } - })); - self - } - - fn on_focus_out( - mut self, - listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext) + 'static, - ) -> Self - where - Self: Sized, - { - self.focus_listeners() - .push(Box::new(move |view, focus_handle, event, cx| { - let descendant_blurred = event - .blurred - .as_ref() - .map_or(false, |blurred| focus_handle.contains(blurred, cx)); - let descendant_focused = event - .focused - .as_ref() - .map_or(false, |focused| focus_handle.contains(focused, cx)); - if descendant_blurred && !descendant_focused { - listener(view, event, cx) - } - })); - self - } -} diff --git a/crates/gpui2/src/prelude.rs b/crates/gpui2/src/prelude.rs index bc998fc1f45e144a22fd7f0103db44b27622b884..7c2ad3f07ff8877d83342f1ac60087b9859eacbc 100644 --- a/crates/gpui2/src/prelude.rs +++ b/crates/gpui2/src/prelude.rs @@ -1 +1,4 @@ -pub use crate::{Context, ParentElement, Refineable}; +pub use crate::{ + BorrowAppContext, BorrowWindow, Component, Context, FocusableComponent, InteractiveComponent, + ParentComponent, Refineable, Render, StatefulInteractiveComponent, Styled, VisualContext, +}; diff --git a/crates/gpui2/src/styled.rs b/crates/gpui2/src/styled.rs index 3f1fa843f99abb689ca609940dd2cbc55fb16dbd..71e38efd9b74e7a4cdf5731c28e15a3311dd2378 100644 --- a/crates/gpui2/src/styled.rs +++ b/crates/gpui2/src/styled.rs @@ -6,21 +6,20 @@ use crate::{ use crate::{BoxShadow, TextStyleRefinement}; use refineable::Refineable; use smallvec::{smallvec, SmallVec}; +use taffy::style::Overflow; -pub trait Styled { +pub trait Styled: Sized { fn style(&mut self) -> &mut StyleRefinement; - fn computed_style(&mut self) -> Style { - Style::default().refined(self.style().clone()) - } - gpui2_macros::style_helpers!(); + fn z_index(mut self, z_index: u32) -> Self { + self.style().z_index = Some(z_index); + self + } + /// Sets the size of the element to the full width and height. - fn full(mut self) -> Self - where - Self: Sized, - { + fn full(mut self) -> Self { self.style().size.width = Some(relative(1.).into()); self.style().size.height = Some(relative(1.).into()); self @@ -28,118 +27,98 @@ pub trait Styled { /// Sets the position of the element to `relative`. /// [Docs](https://tailwindcss.com/docs/position) - fn relative(mut self) -> Self - where - Self: Sized, - { + fn relative(mut self) -> Self { self.style().position = Some(Position::Relative); self } /// Sets the position of the element to `absolute`. /// [Docs](https://tailwindcss.com/docs/position) - fn absolute(mut self) -> Self - where - Self: Sized, - { + fn absolute(mut self) -> Self { self.style().position = Some(Position::Absolute); self } /// Sets the display type of the element to `block`. /// [Docs](https://tailwindcss.com/docs/display) - fn block(mut self) -> Self - where - Self: Sized, - { + fn block(mut self) -> Self { self.style().display = Some(Display::Block); self } /// Sets the display type of the element to `flex`. /// [Docs](https://tailwindcss.com/docs/display) - fn flex(mut self) -> Self - where - Self: Sized, - { + fn flex(mut self) -> Self { self.style().display = Some(Display::Flex); self } /// Sets the visibility of the element to `visible`. /// [Docs](https://tailwindcss.com/docs/visibility) - fn visible(mut self) -> Self - where - Self: Sized, - { + fn visible(mut self) -> Self { self.style().visibility = Some(Visibility::Visible); self } /// Sets the visibility of the element to `hidden`. /// [Docs](https://tailwindcss.com/docs/visibility) - fn invisible(mut self) -> Self - where - Self: Sized, - { + fn invisible(mut self) -> Self { self.style().visibility = Some(Visibility::Hidden); self } - fn cursor(mut self, cursor: CursorStyle) -> Self - where - Self: Sized, - { + fn overflow_hidden(mut self) -> Self { + self.style().overflow.x = Some(Overflow::Hidden); + self.style().overflow.y = Some(Overflow::Hidden); + self + } + + fn overflow_hidden_x(mut self) -> Self { + self.style().overflow.x = Some(Overflow::Hidden); + self + } + + fn overflow_hidden_y(mut self) -> Self { + self.style().overflow.y = Some(Overflow::Hidden); + self + } + + fn cursor(mut self, cursor: CursorStyle) -> Self { self.style().mouse_cursor = Some(cursor); self } /// Sets the cursor style when hovering an element to `default`. /// [Docs](https://tailwindcss.com/docs/cursor) - fn cursor_default(mut self) -> Self - where - Self: Sized, - { + fn cursor_default(mut self) -> Self { self.style().mouse_cursor = Some(CursorStyle::Arrow); self } /// Sets the cursor style when hovering an element to `pointer`. /// [Docs](https://tailwindcss.com/docs/cursor) - fn cursor_pointer(mut self) -> Self - where - Self: Sized, - { + fn cursor_pointer(mut self) -> Self { self.style().mouse_cursor = Some(CursorStyle::PointingHand); self } /// Sets the flex direction of the element to `column`. /// [Docs](https://tailwindcss.com/docs/flex-direction#column) - fn flex_col(mut self) -> Self - where - Self: Sized, - { + fn flex_col(mut self) -> Self { self.style().flex_direction = Some(FlexDirection::Column); self } /// Sets the flex direction of the element to `row`. /// [Docs](https://tailwindcss.com/docs/flex-direction#row) - fn flex_row(mut self) -> Self - where - Self: Sized, - { + fn flex_row(mut self) -> Self { self.style().flex_direction = Some(FlexDirection::Row); self } /// Sets the element to allow a flex item to grow and shrink as needed, ignoring its initial size. /// [Docs](https://tailwindcss.com/docs/flex#flex-1) - fn flex_1(mut self) -> Self - where - Self: Sized, - { + fn flex_1(mut self) -> Self { self.style().flex_grow = Some(1.); self.style().flex_shrink = Some(1.); self.style().flex_basis = Some(relative(0.).into()); @@ -148,10 +127,7 @@ pub trait Styled { /// Sets the element to allow a flex item to grow and shrink, taking into account its initial size. /// [Docs](https://tailwindcss.com/docs/flex#auto) - fn flex_auto(mut self) -> Self - where - Self: Sized, - { + fn flex_auto(mut self) -> Self { self.style().flex_grow = Some(1.); self.style().flex_shrink = Some(1.); self.style().flex_basis = Some(Length::Auto); @@ -160,10 +136,7 @@ pub trait Styled { /// Sets the element to allow a flex item to shrink but not grow, taking into account its initial size. /// [Docs](https://tailwindcss.com/docs/flex#initial) - fn flex_initial(mut self) -> Self - where - Self: Sized, - { + fn flex_initial(mut self) -> Self { self.style().flex_grow = Some(0.); self.style().flex_shrink = Some(1.); self.style().flex_basis = Some(Length::Auto); @@ -172,10 +145,7 @@ pub trait Styled { /// Sets the element to prevent a flex item from growing or shrinking. /// [Docs](https://tailwindcss.com/docs/flex#none) - fn flex_none(mut self) -> Self - where - Self: Sized, - { + fn flex_none(mut self) -> Self { self.style().flex_grow = Some(0.); self.style().flex_shrink = Some(0.); self @@ -183,40 +153,28 @@ pub trait Styled { /// Sets the element to allow a flex item to grow to fill any available space. /// [Docs](https://tailwindcss.com/docs/flex-grow) - fn grow(mut self) -> Self - where - Self: Sized, - { + fn grow(mut self) -> Self { self.style().flex_grow = Some(1.); self } /// Sets the element to align flex items to the start of the container's cross axis. /// [Docs](https://tailwindcss.com/docs/align-items#start) - fn items_start(mut self) -> Self - where - Self: Sized, - { + fn items_start(mut self) -> Self { self.style().align_items = Some(AlignItems::FlexStart); self } /// Sets the element to align flex items to the end of the container's cross axis. /// [Docs](https://tailwindcss.com/docs/align-items#end) - fn items_end(mut self) -> Self - where - Self: Sized, - { + fn items_end(mut self) -> Self { self.style().align_items = Some(AlignItems::FlexEnd); self } /// Sets the element to align flex items along the center of the container's cross axis. /// [Docs](https://tailwindcss.com/docs/align-items#center) - fn items_center(mut self) -> Self - where - Self: Sized, - { + fn items_center(mut self) -> Self { self.style().align_items = Some(AlignItems::Center); self } @@ -224,40 +182,28 @@ pub trait Styled { /// Sets the element to justify flex items along the container's main axis /// such that there is an equal amount of space between each item. /// [Docs](https://tailwindcss.com/docs/justify-content#space-between) - fn justify_between(mut self) -> Self - where - Self: Sized, - { + fn justify_between(mut self) -> Self { self.style().justify_content = Some(JustifyContent::SpaceBetween); self } /// Sets the element to justify flex items along the center of the container's main axis. /// [Docs](https://tailwindcss.com/docs/justify-content#center) - fn justify_center(mut self) -> Self - where - Self: Sized, - { + fn justify_center(mut self) -> Self { self.style().justify_content = Some(JustifyContent::Center); self } /// Sets the element to justify flex items against the start of the container's main axis. /// [Docs](https://tailwindcss.com/docs/justify-content#start) - fn justify_start(mut self) -> Self - where - Self: Sized, - { + fn justify_start(mut self) -> Self { self.style().justify_content = Some(JustifyContent::Start); self } /// Sets the element to justify flex items against the end of the container's main axis. /// [Docs](https://tailwindcss.com/docs/justify-content#end) - fn justify_end(mut self) -> Self - where - Self: Sized, - { + fn justify_end(mut self) -> Self { self.style().justify_content = Some(JustifyContent::End); self } @@ -265,10 +211,7 @@ pub trait Styled { /// Sets the element to justify items along the container's main axis such /// that there is an equal amount of space on each side of each item. /// [Docs](https://tailwindcss.com/docs/justify-content#space-around) - fn justify_around(mut self) -> Self - where - Self: Sized, - { + fn justify_around(mut self) -> Self { self.style().justify_content = Some(JustifyContent::SpaceAround); self } @@ -295,30 +238,21 @@ pub trait Styled { /// Sets the box shadow of the element. /// [Docs](https://tailwindcss.com/docs/box-shadow) - fn shadow(mut self, shadows: SmallVec<[BoxShadow; 2]>) -> Self - where - Self: Sized, - { + fn shadow(mut self, shadows: SmallVec<[BoxShadow; 2]>) -> Self { self.style().box_shadow = Some(shadows); self } /// Clears the box shadow of the element. /// [Docs](https://tailwindcss.com/docs/box-shadow) - fn shadow_none(mut self) -> Self - where - Self: Sized, - { + fn shadow_none(mut self) -> Self { self.style().box_shadow = Some(Default::default()); self } /// Sets the box shadow of the element. /// [Docs](https://tailwindcss.com/docs/box-shadow) - fn shadow_sm(mut self) -> Self - where - Self: Sized, - { + fn shadow_sm(mut self) -> Self { self.style().box_shadow = Some(smallvec::smallvec![BoxShadow { color: hsla(0., 0., 0., 0.05), offset: point(px(0.), px(1.)), @@ -330,10 +264,7 @@ pub trait Styled { /// Sets the box shadow of the element. /// [Docs](https://tailwindcss.com/docs/box-shadow) - fn shadow_md(mut self) -> Self - where - Self: Sized, - { + fn shadow_md(mut self) -> Self { self.style().box_shadow = Some(smallvec![ BoxShadow { color: hsla(0.5, 0., 0., 0.1), @@ -353,10 +284,7 @@ pub trait Styled { /// Sets the box shadow of the element. /// [Docs](https://tailwindcss.com/docs/box-shadow) - fn shadow_lg(mut self) -> Self - where - Self: Sized, - { + fn shadow_lg(mut self) -> Self { self.style().box_shadow = Some(smallvec![ BoxShadow { color: hsla(0., 0., 0., 0.1), @@ -376,10 +304,7 @@ pub trait Styled { /// Sets the box shadow of the element. /// [Docs](https://tailwindcss.com/docs/box-shadow) - fn shadow_xl(mut self) -> Self - where - Self: Sized, - { + fn shadow_xl(mut self) -> Self { self.style().box_shadow = Some(smallvec![ BoxShadow { color: hsla(0., 0., 0., 0.1), @@ -399,10 +324,7 @@ pub trait Styled { /// Sets the box shadow of the element. /// [Docs](https://tailwindcss.com/docs/box-shadow) - fn shadow_2xl(mut self) -> Self - where - Self: Sized, - { + fn shadow_2xl(mut self) -> Self { self.style().box_shadow = Some(smallvec![BoxShadow { color: hsla(0., 0., 0., 0.25), offset: point(px(0.), px(25.)), @@ -417,198 +339,138 @@ pub trait Styled { &mut style.text } - fn text_color(mut self, color: impl Into) -> Self - where - Self: Sized, - { + fn text_color(mut self, color: impl Into) -> Self { self.text_style().get_or_insert_with(Default::default).color = Some(color.into()); self } - fn text_size(mut self, size: impl Into) -> Self - where - Self: Sized, - { + fn text_size(mut self, size: impl Into) -> Self { self.text_style() .get_or_insert_with(Default::default) .font_size = Some(size.into()); self } - fn text_xs(mut self) -> Self - where - Self: Sized, - { + fn text_xs(mut self) -> Self { self.text_style() .get_or_insert_with(Default::default) .font_size = Some(rems(0.75).into()); self } - fn text_sm(mut self) -> Self - where - Self: Sized, - { + fn text_sm(mut self) -> Self { self.text_style() .get_or_insert_with(Default::default) .font_size = Some(rems(0.875).into()); self } - fn text_base(mut self) -> Self - where - Self: Sized, - { + fn text_base(mut self) -> Self { self.text_style() .get_or_insert_with(Default::default) .font_size = Some(rems(1.0).into()); self } - fn text_lg(mut self) -> Self - where - Self: Sized, - { + fn text_lg(mut self) -> Self { self.text_style() .get_or_insert_with(Default::default) .font_size = Some(rems(1.125).into()); self } - fn text_xl(mut self) -> Self - where - Self: Sized, - { + fn text_xl(mut self) -> Self { self.text_style() .get_or_insert_with(Default::default) .font_size = Some(rems(1.25).into()); self } - fn text_2xl(mut self) -> Self - where - Self: Sized, - { + fn text_2xl(mut self) -> Self { self.text_style() .get_or_insert_with(Default::default) .font_size = Some(rems(1.5).into()); self } - fn text_3xl(mut self) -> Self - where - Self: Sized, - { + fn text_3xl(mut self) -> Self { self.text_style() .get_or_insert_with(Default::default) .font_size = Some(rems(1.875).into()); self } - fn text_decoration_none(mut self) -> Self - where - Self: Sized, - { + fn text_decoration_none(mut self) -> Self { self.text_style() .get_or_insert_with(Default::default) .underline = None; self } - fn text_decoration_color(mut self, color: impl Into) -> Self - where - Self: Sized, - { + fn text_decoration_color(mut self, color: impl Into) -> Self { let style = self.text_style().get_or_insert_with(Default::default); let underline = style.underline.get_or_insert_with(Default::default); underline.color = Some(color.into()); self } - fn text_decoration_solid(mut self) -> Self - where - Self: Sized, - { + fn text_decoration_solid(mut self) -> Self { let style = self.text_style().get_or_insert_with(Default::default); let underline = style.underline.get_or_insert_with(Default::default); underline.wavy = false; self } - fn text_decoration_wavy(mut self) -> Self - where - Self: Sized, - { + fn text_decoration_wavy(mut self) -> Self { let style = self.text_style().get_or_insert_with(Default::default); let underline = style.underline.get_or_insert_with(Default::default); underline.wavy = true; self } - fn text_decoration_0(mut self) -> Self - where - Self: Sized, - { + fn text_decoration_0(mut self) -> Self { let style = self.text_style().get_or_insert_with(Default::default); let underline = style.underline.get_or_insert_with(Default::default); underline.thickness = px(0.); self } - fn text_decoration_1(mut self) -> Self - where - Self: Sized, - { + fn text_decoration_1(mut self) -> Self { let style = self.text_style().get_or_insert_with(Default::default); let underline = style.underline.get_or_insert_with(Default::default); underline.thickness = px(1.); self } - fn text_decoration_2(mut self) -> Self - where - Self: Sized, - { + fn text_decoration_2(mut self) -> Self { let style = self.text_style().get_or_insert_with(Default::default); let underline = style.underline.get_or_insert_with(Default::default); underline.thickness = px(2.); self } - fn text_decoration_4(mut self) -> Self - where - Self: Sized, - { + fn text_decoration_4(mut self) -> Self { let style = self.text_style().get_or_insert_with(Default::default); let underline = style.underline.get_or_insert_with(Default::default); underline.thickness = px(4.); self } - fn text_decoration_8(mut self) -> Self - where - Self: Sized, - { + fn text_decoration_8(mut self) -> Self { let style = self.text_style().get_or_insert_with(Default::default); let underline = style.underline.get_or_insert_with(Default::default); underline.thickness = px(8.); self } - fn font(mut self, family_name: impl Into) -> Self - where - Self: Sized, - { + fn font(mut self, family_name: impl Into) -> Self { self.text_style() .get_or_insert_with(Default::default) .font_family = Some(family_name.into()); self } - fn line_height(mut self, line_height: impl Into) -> Self - where - Self: Sized, - { + fn line_height(mut self, line_height: impl Into) -> Self { self.text_style() .get_or_insert_with(Default::default) .line_height = Some(line_height.into()); diff --git a/crates/gpui2/src/view.rs b/crates/gpui2/src/view.rs index 3299ce7d45e91e3bfe477eb2f39e04fcc9a14058..801d8ceb0bc5b07018aeb7fc282186d9c5faab7b 100644 --- a/crates/gpui2/src/view.rs +++ b/crates/gpui2/src/view.rs @@ -206,7 +206,7 @@ impl From> for AnyView { impl Element for AnyView { type ElementState = Box; - fn id(&self) -> Option { + fn element_id(&self) -> Option { Some(self.model.entity_id.into()) } diff --git a/crates/gpui2_macros/src/style_helpers.rs b/crates/gpui2_macros/src/style_helpers.rs index 57aef03afa55276293d48f610458c5d29ddf9862..181311807c8832a3e48dc05c445e489b7c9b22b0 100644 --- a/crates/gpui2_macros/src/style_helpers.rs +++ b/crates/gpui2_macros/src/style_helpers.rs @@ -130,7 +130,7 @@ fn generate_predefined_setter( let method = quote! { #[doc = #doc_string] - fn #method_name(mut self) -> Self where Self: std::marker::Sized { + fn #method_name(mut self) -> Self { let style = self.style(); #(#field_assignments)* self @@ -163,7 +163,7 @@ fn generate_custom_value_setter( let method = quote! { #[doc = #doc_string] - fn #method_name(mut self, length: impl std::clone::Clone + Into) -> Self where Self: std::marker::Sized { + fn #method_name(mut self, length: impl std::clone::Clone + Into) -> Self { let style = self.style(); #(#field_assignments)* self diff --git a/crates/picker2/src/picker2.rs b/crates/picker2/src/picker2.rs index e1979f1b13455eedd07f9d9ca07609642a3a0b83..189c07b49afde5c06fe327aa1de10422d35a878b 100644 --- a/crates/picker2/src/picker2.rs +++ b/crates/picker2/src/picker2.rs @@ -1,6 +1,6 @@ use editor::Editor; use gpui::{ - div, uniform_list, Component, Div, ParentElement, Render, StatelessInteractive, Styled, Task, + div, uniform_list, Component, Node, ParentComponent, Render, Styled, Task, UniformListScrollHandle, View, ViewContext, VisualContext, WindowContext, }; use std::{cmp, sync::Arc}; @@ -139,11 +139,11 @@ impl Picker { } impl Render for Picker { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { div() - .context("picker") + .key_context("picker") .size_full() .elevation_2(cx) .on_action(Self::select_next) diff --git a/crates/storybook2/src/stories/colors.rs b/crates/storybook2/src/stories/colors.rs index 13b7b36a8c67c1674f34d54a003a1b6d6788aeb9..a5e9efc0da505973f2d5106352a9108d40d3c085 100644 --- a/crates/storybook2/src/stories/colors.rs +++ b/crates/storybook2/src/stories/colors.rs @@ -1,12 +1,12 @@ use crate::story::Story; -use gpui::{px, Div, Render}; +use gpui::{prelude::*, px, Node, Render}; use theme2::{default_color_scales, ColorScaleStep}; use ui::prelude::*; pub struct ColorsStory; impl Render for ColorsStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let color_scales = default_color_scales(); diff --git a/crates/storybook2/src/stories/focus.rs b/crates/storybook2/src/stories/focus.rs index bba798d9fe26403257d8a42fd2842ff8a89526d9..a6b27c460df399e14a42a43561ac4cb79bd33769 100644 --- a/crates/storybook2/src/stories/focus.rs +++ b/crates/storybook2/src/stories/focus.rs @@ -1,6 +1,5 @@ use gpui::{ - actions, div, Div, FocusHandle, Focusable, FocusableKeyDispatch, KeyBinding, ParentElement, - Render, StatefulInteractivity, StatelessInteractive, Styled, View, VisualContext, + actions, div, prelude::*, FocusHandle, Focusable, KeyBinding, Node, Render, Stateful, View, WindowContext, }; use theme2::ActiveTheme; @@ -28,7 +27,7 @@ impl FocusStory { } impl Render for FocusStory { - type Element = Div, FocusableKeyDispatch>; + type Element = Focusable>>; fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { let theme = cx.theme(); @@ -42,7 +41,7 @@ impl Render for FocusStory { div() .id("parent") .focusable() - .context("parent") + .key_context("parent") .on_action(|_, action: &ActionA, cx| { println!("Action A dispatched on parent"); }) @@ -62,7 +61,7 @@ impl Render for FocusStory { .child( div() .track_focus(&self.child_1_focus) - .context("child-1") + .key_context("child-1") .on_action(|_, action: &ActionB, cx| { println!("Action B dispatched on child 1 during"); }) @@ -82,7 +81,7 @@ impl Render for FocusStory { .child( div() .track_focus(&self.child_2_focus) - .context("child-2") + .key_context("child-2") .on_action(|_, action: &ActionC, cx| { println!("Action C dispatched on child 2"); }) diff --git a/crates/storybook2/src/stories/kitchen_sink.rs b/crates/storybook2/src/stories/kitchen_sink.rs index 6831ae27220ca4691f5f8ac371c0f43e6dd7b013..0a165eff7496fb6a536a7d69a8f813080bb294b1 100644 --- a/crates/storybook2/src/stories/kitchen_sink.rs +++ b/crates/storybook2/src/stories/kitchen_sink.rs @@ -1,5 +1,5 @@ use crate::{story::Story, story_selector::ComponentStory}; -use gpui::{Div, Render, StatefulInteractivity, View, VisualContext}; +use gpui::{prelude::*, Node, Render, Stateful, View}; use strum::IntoEnumIterator; use ui::prelude::*; @@ -12,7 +12,7 @@ impl KitchenSinkStory { } impl Render for KitchenSinkStory { - type Element = Div>; + type Element = Stateful>; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let component_stories = ComponentStory::iter() diff --git a/crates/storybook2/src/stories/picker.rs b/crates/storybook2/src/stories/picker.rs index 067c190575acebad345479b88fe6cf164c19ef81..bba8ae9990c36ea6c6d3d312f77bacaf9a05f059 100644 --- a/crates/storybook2/src/stories/picker.rs +++ b/crates/storybook2/src/stories/picker.rs @@ -1,11 +1,7 @@ -use std::sync::Arc; - use fuzzy::StringMatchCandidate; -use gpui::{ - div, Component, Div, KeyBinding, ParentElement, Render, StatelessInteractive, Styled, Task, - View, VisualContext, WindowContext, -}; +use gpui::{div, prelude::*, KeyBinding, Node, Render, Styled, Task, View, WindowContext}; use picker::{Picker, PickerDelegate}; +use std::sync::Arc; use theme2::ActiveTheme; pub struct PickerStory { @@ -38,7 +34,7 @@ impl Delegate { } impl PickerDelegate for Delegate { - type ListItem = Div>; + type ListItem = Node>; fn match_count(&self) -> usize { self.candidates.len() @@ -207,7 +203,7 @@ impl PickerStory { } impl Render for PickerStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { div() diff --git a/crates/storybook2/src/stories/scroll.rs b/crates/storybook2/src/stories/scroll.rs index 296dc50cb491a1def608c050f65cf7ff33cedb2b..c5675b5681ca1af1208be4fbaa67a8d44fd6c561 100644 --- a/crates/storybook2/src/stories/scroll.rs +++ b/crates/storybook2/src/stories/scroll.rs @@ -1,6 +1,5 @@ use gpui::{ - div, px, Component, Div, ParentElement, Render, SharedString, StatefulInteractivity, Styled, - View, VisualContext, WindowContext, + div, prelude::*, px, Node, Render, SharedString, Stateful, Styled, View, WindowContext, }; use theme2::ActiveTheme; @@ -13,7 +12,7 @@ impl ScrollStory { } impl Render for ScrollStory { - type Element = Div>; + type Element = Stateful>; fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { let theme = cx.theme(); diff --git a/crates/storybook2/src/stories/text.rs b/crates/storybook2/src/stories/text.rs index b4a4c86e7eed15fb774ea1586e4ab36a1ea5aafe..86ab2fce9998cdd4edbbb2fb07800b0e2a3eea6b 100644 --- a/crates/storybook2/src/stories/text.rs +++ b/crates/storybook2/src/stories/text.rs @@ -1,4 +1,4 @@ -use gpui::{div, white, Div, ParentElement, Render, Styled, View, VisualContext, WindowContext}; +use gpui::{div, white, Node, ParentComponent, Render, Styled, View, VisualContext, WindowContext}; pub struct TextStory; @@ -9,7 +9,7 @@ impl TextStory { } impl Render for TextStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { div().size_full().bg(white()).child(concat!( diff --git a/crates/storybook2/src/stories/z_index.rs b/crates/storybook2/src/stories/z_index.rs index 46ec0f4a3511ea2b3a3cc7999e203a62d35a01d6..259685b9fa7f402a3b2eec3b8b9c1e4d8e165cf2 100644 --- a/crates/storybook2/src/stories/z_index.rs +++ b/crates/storybook2/src/stories/z_index.rs @@ -1,4 +1,4 @@ -use gpui::{px, rgb, Div, Hsla, Render}; +use gpui::{px, rgb, Hsla, Node, Render}; use ui::prelude::*; use crate::story::Story; @@ -8,7 +8,7 @@ use crate::story::Story; pub struct ZIndexStory; impl Render for ZIndexStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) @@ -77,7 +77,7 @@ trait Styles: Styled + Sized { } } -impl Styles for Div {} +impl Styles for Node {} #[derive(Component)] struct ZIndexExample { diff --git a/crates/storybook2/src/storybook2.rs b/crates/storybook2/src/storybook2.rs index f0ba124162d546bcdbdc1fce12e986364f950dad..f20aa5909554761b47d40d8a4a11115dbd8f11c8 100644 --- a/crates/storybook2/src/storybook2.rs +++ b/crates/storybook2/src/storybook2.rs @@ -9,7 +9,7 @@ use std::sync::Arc; use clap::Parser; use gpui::{ - div, px, size, AnyView, AppContext, Bounds, Div, Render, ViewContext, VisualContext, + div, px, size, AnyView, AppContext, Bounds, Node, Render, ViewContext, VisualContext, WindowBounds, WindowOptions, }; use log::LevelFilter; @@ -107,7 +107,7 @@ impl StoryWrapper { } impl Render for StoryWrapper { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { div() diff --git a/crates/theme2/src/players.rs b/crates/theme2/src/players.rs index 0e36ff594732c67ac7f1fd455e849aa259084bc7..32b3504b65f9004e1d6555170cb4bfdd5a406506 100644 --- a/crates/theme2/src/players.rs +++ b/crates/theme2/src/players.rs @@ -40,12 +40,12 @@ pub use stories::*; mod stories { use super::*; use crate::{ActiveTheme, Story}; - use gpui::{div, img, px, Div, ParentElement, Render, Styled, ViewContext}; + use gpui::{div, img, px, Node, ParentComponent, Render, Styled, ViewContext}; pub struct PlayerStory; impl Render for PlayerStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx).child( diff --git a/crates/theme2/src/story.rs b/crates/theme2/src/story.rs index 8b3754b59e9799f00cc60f3cb3f45fb84fcd0cff..00cb20df9268c36d1235a7c3c4b88ba796ba133a 100644 --- a/crates/theme2/src/story.rs +++ b/crates/theme2/src/story.rs @@ -1,11 +1,11 @@ -use gpui::{div, Component, Div, ParentElement, Styled, ViewContext}; +use gpui::{div, Component, Node, ParentComponent, Styled, ViewContext}; use crate::ActiveTheme; pub struct Story {} impl Story { - pub fn container(cx: &mut ViewContext) -> Div { + pub fn container(cx: &mut ViewContext) -> Node { div() .size_full() .flex() diff --git a/crates/ui2/src/components/avatar.rs b/crates/ui2/src/components/avatar.rs index d083d8fd463e144e236e5c625caa92f237f3fce4..d270f2fd323c69ee3e9fffbee12ae9117c1f6473 100644 --- a/crates/ui2/src/components/avatar.rs +++ b/crates/ui2/src/components/avatar.rs @@ -44,12 +44,12 @@ pub use stories::*; mod stories { use super::*; use crate::Story; - use gpui::{Div, Render}; + use gpui::{Node, Render}; pub struct AvatarStory; impl Render for AvatarStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/components/button.rs b/crates/ui2/src/components/button.rs index 5787616832e354a501e1f2e10ddf6fec6e480bea..eeb8ddb90687766f67277ff01f340b91b25a91a7 100644 --- a/crates/ui2/src/components/button.rs +++ b/crates/ui2/src/components/button.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use gpui::{div, DefiniteLength, Hsla, MouseButton, WindowContext}; +use gpui::{div, DefiniteLength, Hsla, MouseButton, StatefulInteractiveComponent, WindowContext}; use crate::{ h_stack, prelude::*, Icon, IconButton, IconColor, IconElement, Label, LabelColor, @@ -236,13 +236,13 @@ pub use stories::*; mod stories { use super::*; use crate::{h_stack, v_stack, LabelColor, Story}; - use gpui::{rems, Div, Render}; + use gpui::{rems, Node, Render}; use strum::IntoEnumIterator; pub struct ButtonStory; impl Render for ButtonStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let states = InteractionState::iter(); diff --git a/crates/ui2/src/components/checkbox.rs b/crates/ui2/src/components/checkbox.rs index 20dad747124ca2a652679324f04590dbf9d3f05d..c2a0cfdc2f539f60846739793260e35c71156e69 100644 --- a/crates/ui2/src/components/checkbox.rs +++ b/crates/ui2/src/components/checkbox.rs @@ -1,9 +1,5 @@ +use gpui::{div, prelude::*, Component, ElementId, Styled, ViewContext}; use std::sync::Arc; - -use gpui::{ - div, Component, ElementId, ParentElement, StatefulInteractive, StatelessInteractive, Styled, - ViewContext, -}; use theme2::ActiveTheme; use crate::{Icon, IconColor, IconElement, Selection}; @@ -175,12 +171,12 @@ pub use stories::*; mod stories { use super::*; use crate::{h_stack, Story}; - use gpui::{Div, Render}; + use gpui::{Node, Render}; pub struct CheckboxStory; impl Render for CheckboxStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/components/context_menu.rs b/crates/ui2/src/components/context_menu.rs index 117be127798bd56f9d0c3963f8119832aa170550..a33f10c296f92e3ebd25123e0b1a3a8b160de816 100644 --- a/crates/ui2/src/components/context_menu.rs +++ b/crates/ui2/src/components/context_menu.rs @@ -65,12 +65,12 @@ pub use stories::*; mod stories { use super::*; use crate::story::Story; - use gpui::{Div, Render}; + use gpui::{Node, Render}; pub struct ContextMenuStory; impl Render for ContextMenuStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/components/details.rs b/crates/ui2/src/components/details.rs index f138290f17fd3b6fc325f0972f62f6aa6f996ed1..44c433179a94b291145dcb363f4cc4d69c869180 100644 --- a/crates/ui2/src/components/details.rs +++ b/crates/ui2/src/components/details.rs @@ -47,12 +47,12 @@ pub use stories::*; mod stories { use super::*; use crate::{Button, Story}; - use gpui::{Div, Render}; + use gpui::{Node, Render}; pub struct DetailsStory; impl Render for DetailsStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/components/elevated_surface.rs b/crates/ui2/src/components/elevated_surface.rs index 7a6f11978e4b0dcb6eccda4678c666677c2c2981..3a1699a64a9678687718eb14cd856b26370904f5 100644 --- a/crates/ui2/src/components/elevated_surface.rs +++ b/crates/ui2/src/components/elevated_surface.rs @@ -1,11 +1,11 @@ -use gpui::Div; +use gpui::Node; use crate::{prelude::*, v_stack}; /// Create an elevated surface. /// /// Must be used inside of a relative parent element -pub fn elevated_surface(level: ElevationIndex, cx: &mut ViewContext) -> Div { +pub fn elevated_surface(level: ElevationIndex, cx: &mut ViewContext) -> Node { let colors = cx.theme().colors(); // let shadow = BoxShadow { @@ -23,6 +23,6 @@ pub fn elevated_surface(level: ElevationIndex, cx: &mut ViewContext< .shadow(level.shadow()) } -pub fn modal(cx: &mut ViewContext) -> Div { +pub fn modal(cx: &mut ViewContext) -> Node { elevated_surface(ElevationIndex::ModalSurface, cx) } diff --git a/crates/ui2/src/components/facepile.rs b/crates/ui2/src/components/facepile.rs index efac4925f80a579bfc9deeca273fbf64aad10c5f..43fd233458fbb03d3faff2415e1ffeb48aef23f2 100644 --- a/crates/ui2/src/components/facepile.rs +++ b/crates/ui2/src/components/facepile.rs @@ -33,12 +33,12 @@ pub use stories::*; mod stories { use super::*; use crate::{static_players, Story}; - use gpui::{Div, Render}; + use gpui::{Node, Render}; pub struct FacepileStory; impl Render for FacepileStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let players = static_players(); diff --git a/crates/ui2/src/components/icon.rs b/crates/ui2/src/components/icon.rs index 907f3f91871b5c614944e821244d10228d2853bb..ce980a879bf26db0d1ed9da32656746d237b79a4 100644 --- a/crates/ui2/src/components/icon.rs +++ b/crates/ui2/src/components/icon.rs @@ -204,7 +204,7 @@ pub use stories::*; #[cfg(feature = "stories")] mod stories { - use gpui::{Div, Render}; + use gpui::{Node, Render}; use strum::IntoEnumIterator; use crate::Story; @@ -214,7 +214,7 @@ mod stories { pub struct IconStory; impl Render for IconStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let icons = Icon::iter(); diff --git a/crates/ui2/src/components/icon_button.rs b/crates/ui2/src/components/icon_button.rs index 91653ea8cdd0158d88294886b826c680b5cbf9b3..86803c584c9291e68684b36d9ab6a108eb7e6d1e 100644 --- a/crates/ui2/src/components/icon_button.rs +++ b/crates/ui2/src/components/icon_button.rs @@ -1,9 +1,7 @@ -use std::sync::Arc; - -use gpui::{rems, MouseButton}; - use crate::{h_stack, prelude::*}; use crate::{ClickHandler, Icon, IconColor, IconElement}; +use gpui::{prelude::*, rems, MouseButton}; +use std::sync::Arc; struct IconButtonHandlers { click: Option>, diff --git a/crates/ui2/src/components/input.rs b/crates/ui2/src/components/input.rs index 1a44827fe8d308f2f73dd3609bf9a4a5ab7625cb..d873d6a5cbf86f343febb820e817985ee98dbe3f 100644 --- a/crates/ui2/src/components/input.rs +++ b/crates/ui2/src/components/input.rs @@ -1,6 +1,5 @@ -use crate::prelude::*; -use crate::Label; -use crate::LabelColor; +use crate::{prelude::*, Label, LabelColor}; +use gpui::prelude::*; #[derive(Default, PartialEq)] pub enum InputVariant { @@ -111,12 +110,12 @@ pub use stories::*; mod stories { use super::*; use crate::Story; - use gpui::{Div, Render}; + use gpui::{Node, Render}; pub struct InputStory; impl Render for InputStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/components/keybinding.rs b/crates/ui2/src/components/keybinding.rs index bd02e694edd45561373f39e2673d7e290dcf30cb..86e876d24502624438f683abe242eac7d25144cf 100644 --- a/crates/ui2/src/components/keybinding.rs +++ b/crates/ui2/src/components/keybinding.rs @@ -158,13 +158,13 @@ pub use stories::*; mod stories { use super::*; use crate::Story; - use gpui::{Div, Render}; + use gpui::{Node, Render}; use itertools::Itertools; pub struct KeybindingStory; impl Render for KeybindingStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let all_modifier_permutations = ModifierKey::iter().permutations(2); diff --git a/crates/ui2/src/components/label.rs b/crates/ui2/src/components/label.rs index 827ba87918a0cd4dd3f3255c8b7852436ea06a79..497ebe677312703d49ed32ed2339d12a191ab938 100644 --- a/crates/ui2/src/components/label.rs +++ b/crates/ui2/src/components/label.rs @@ -196,12 +196,12 @@ pub use stories::*; mod stories { use super::*; use crate::Story; - use gpui::{Div, Render}; + use gpui::{Node, Render}; pub struct LabelStory; impl Render for LabelStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/components/modal.rs b/crates/ui2/src/components/modal.rs index 75528b5c3460defeb139f7a16d8d311d87a5093b..c3d71a78d8dd873d1d898da43edb69fadca66188 100644 --- a/crates/ui2/src/components/modal.rs +++ b/crates/ui2/src/components/modal.rs @@ -74,7 +74,7 @@ impl Modal { } } -impl ParentElement for Modal { +impl ParentComponent for Modal { fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { &mut self.children } diff --git a/crates/ui2/src/components/palette.rs b/crates/ui2/src/components/palette.rs index 7f736433fcd4d376534e265d3bf412aaa068888c..4a753215f0940c063e6737ded9d9c2bcf854eff3 100644 --- a/crates/ui2/src/components/palette.rs +++ b/crates/ui2/src/components/palette.rs @@ -1,5 +1,5 @@ -use crate::prelude::*; -use crate::{h_stack, v_stack, Keybinding, Label, LabelColor}; +use crate::{h_stack, prelude::*, v_stack, Keybinding, Label, LabelColor}; +use gpui::prelude::*; #[derive(Component)] pub struct Palette { @@ -159,7 +159,7 @@ pub use stories::*; #[cfg(feature = "stories")] mod stories { - use gpui::{Div, Render}; + use gpui::{Node, Render}; use crate::{ModifierKeys, Story}; @@ -168,7 +168,7 @@ mod stories { pub struct PaletteStory; impl Render for PaletteStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { { diff --git a/crates/ui2/src/components/panel.rs b/crates/ui2/src/components/panel.rs index 1762003a2c2f8b6a8569a5ffd99770d90aef130d..2b317b0bc1d02773d6bcc0be20241e464ebb3299 100644 --- a/crates/ui2/src/components/panel.rs +++ b/crates/ui2/src/components/panel.rs @@ -1,4 +1,4 @@ -use gpui::{AbsoluteLength, AnyElement}; +use gpui::{prelude::*, AbsoluteLength, AnyElement}; use smallvec::SmallVec; use crate::prelude::*; @@ -113,7 +113,7 @@ impl Panel { } } -impl ParentElement for Panel { +impl ParentComponent for Panel { fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { &mut self.children } @@ -126,12 +126,12 @@ pub use stories::*; mod stories { use super::*; use crate::{Label, Story}; - use gpui::{Div, Render}; + use gpui::{InteractiveComponent, Node, Render}; pub struct PanelStory; impl Render for PanelStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/components/stack.rs b/crates/ui2/src/components/stack.rs index d3d7a75aa76b8765a97b3dcc0c92c498cbbb7d24..d705863ad40a4cd9368f5e07be030ffda53be593 100644 --- a/crates/ui2/src/components/stack.rs +++ b/crates/ui2/src/components/stack.rs @@ -1,17 +1,17 @@ -use gpui::{div, Div}; +use gpui::{div, Node}; use crate::StyledExt; /// Horizontally stacks elements. /// /// Sets `flex()`, `flex_row()`, `items_center()` -pub fn h_stack() -> Div { +pub fn h_stack() -> Node { div().h_flex() } /// Vertically stacks elements. /// /// Sets `flex()`, `flex_col()` -pub fn v_stack() -> Div { +pub fn v_stack() -> Node { div().v_flex() } diff --git a/crates/ui2/src/components/tab.rs b/crates/ui2/src/components/tab.rs index e936dc924a5fcba43e7d0905d5fac455d9ebd5c8..fe993555b91094e289181bdc3b1976153dc88e49 100644 --- a/crates/ui2/src/components/tab.rs +++ b/crates/ui2/src/components/tab.rs @@ -1,6 +1,6 @@ use crate::prelude::*; use crate::{Icon, IconColor, IconElement, Label, LabelColor}; -use gpui::{red, Div, ElementId, Render, View, VisualContext}; +use gpui::{prelude::*, red, ElementId, Node, Render, View}; #[derive(Component, Clone)] pub struct Tab { @@ -21,7 +21,7 @@ struct TabDragState { } impl Render for TabDragState { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { div().w_8().h_4().bg(red()) @@ -178,7 +178,7 @@ mod stories { pub struct TabStory; impl Render for TabStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let git_statuses = GitStatus::iter(); diff --git a/crates/ui2/src/components/toast.rs b/crates/ui2/src/components/toast.rs index 4164be2c3e71fdf22b0b9a852588b796d0d1de21..2f07bbc3e09d939d3c94b0d9c41f8a1361ea4b86 100644 --- a/crates/ui2/src/components/toast.rs +++ b/crates/ui2/src/components/toast.rs @@ -1,7 +1,6 @@ -use gpui::AnyElement; -use smallvec::SmallVec; - use crate::prelude::*; +use gpui::{prelude::*, AnyElement}; +use smallvec::SmallVec; #[derive(Default, Debug, PartialEq, Eq, Clone, Copy)] pub enum ToastOrigin { @@ -59,7 +58,7 @@ impl Toast { } } -impl ParentElement for Toast { +impl ParentComponent for Toast { fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { &mut self.children } @@ -70,7 +69,7 @@ pub use stories::*; #[cfg(feature = "stories")] mod stories { - use gpui::{Div, Render}; + use gpui::{Node, Render}; use crate::{Label, Story}; @@ -79,7 +78,7 @@ mod stories { pub struct ToastStory; impl Render for ToastStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/components/toggle.rs b/crates/ui2/src/components/toggle.rs index 368c95662fa51ed804c3d73f0d456d4f071a76d1..f34f08e09e689650f502c40630f97435dfe14d4b 100644 --- a/crates/ui2/src/components/toggle.rs +++ b/crates/ui2/src/components/toggle.rs @@ -1,4 +1,4 @@ -use gpui::{div, Component, ParentElement}; +use gpui::{div, Component, ParentComponent}; use crate::{Icon, IconColor, IconElement, IconSize}; diff --git a/crates/ui2/src/components/tooltip.rs b/crates/ui2/src/components/tooltip.rs index 87860ce943135997c8a0a816d81d44d5a500fb25..6c5fa7bc2bb2ec85044fcc8a6be3d02ee7454611 100644 --- a/crates/ui2/src/components/tooltip.rs +++ b/crates/ui2/src/components/tooltip.rs @@ -1,4 +1,4 @@ -use gpui::{div, Div, ParentElement, Render, SharedString, Styled, ViewContext}; +use gpui::{div, Node, ParentComponent, Render, SharedString, Styled, ViewContext}; use theme2::ActiveTheme; #[derive(Clone, Debug)] @@ -13,7 +13,7 @@ impl TextTooltip { } impl Render for TextTooltip { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let theme = cx.theme(); diff --git a/crates/ui2/src/prelude.rs b/crates/ui2/src/prelude.rs index 545f437a9b4de2ee1deb14eada747e4315112557..f37b6123e3fadfd4536061c682c833e5a0ec2a0d 100644 --- a/crates/ui2/src/prelude.rs +++ b/crates/ui2/src/prelude.rs @@ -1,8 +1,8 @@ use gpui::rems; use gpui::Rems; pub use gpui::{ - div, Component, Element, ElementId, ParentElement, SharedString, StatefulInteractive, - StatelessInteractive, Styled, ViewContext, WindowContext, + div, Component, Element, ElementId, InteractiveComponent, ParentComponent, SharedString, Styled, + ViewContext, WindowContext, }; pub use crate::elevation::*; diff --git a/crates/ui2/src/story.rs b/crates/ui2/src/story.rs index 94e38267f4c5b160365317c4e597a76748c05d6f..cf5737a2454eff52bc64cc76338a64fbee09350a 100644 --- a/crates/ui2/src/story.rs +++ b/crates/ui2/src/story.rs @@ -1,11 +1,11 @@ -use gpui::Div; +use gpui::Node; use crate::prelude::*; pub struct Story {} impl Story { - pub fn container(cx: &mut ViewContext) -> Div { + pub fn container(cx: &mut ViewContext) -> Node { div() .size_full() .flex() diff --git a/crates/ui2/src/styled_ext.rs b/crates/ui2/src/styled_ext.rs index 0407d98f862abc37d319bb0ad61204a43ff3a451..d9911e683358dfd37a9110f71cf3899debe52904 100644 --- a/crates/ui2/src/styled_ext.rs +++ b/crates/ui2/src/styled_ext.rs @@ -1,4 +1,4 @@ -use gpui::{Div, ElementInteractivity, KeyDispatch, Styled, UniformList, ViewContext}; +use gpui::{Styled, ViewContext}; use theme2::ActiveTheme; use crate::{ElevationIndex, UITextSize}; @@ -93,11 +93,4 @@ pub trait StyledExt: Styled + Sized { } } -impl StyledExt for Div -where - I: ElementInteractivity, - F: KeyDispatch, -{ -} - -impl StyledExt for UniformList {} +impl StyledExt for E {} diff --git a/crates/ui2/src/to_extract/assistant_panel.rs b/crates/ui2/src/to_extract/assistant_panel.rs index 8a35757f5c484315daebea12c0af7186c418f96e..59d90591220118d15d4e67d5eb2ff35001d24748 100644 --- a/crates/ui2/src/to_extract/assistant_panel.rs +++ b/crates/ui2/src/to_extract/assistant_panel.rs @@ -1,6 +1,6 @@ use crate::prelude::*; use crate::{Icon, IconButton, Label, Panel, PanelSide}; -use gpui::{rems, AbsoluteLength}; +use gpui::{prelude::*, rems, AbsoluteLength}; #[derive(Component)] pub struct AssistantPanel { @@ -77,11 +77,11 @@ pub use stories::*; mod stories { use super::*; use crate::Story; - use gpui::{Div, Render}; + use gpui::{Node, Render}; pub struct AssistantPanelStory; impl Render for AssistantPanelStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/breadcrumb.rs b/crates/ui2/src/to_extract/breadcrumb.rs index 782f772fa1472fe6dd213da2d3e7346a03b84395..c113c641684b2f8289a55046e76fa5664f7b03f1 100644 --- a/crates/ui2/src/to_extract/breadcrumb.rs +++ b/crates/ui2/src/to_extract/breadcrumb.rs @@ -1,9 +1,7 @@ +use crate::{h_stack, prelude::*, HighlightedText}; +use gpui::{prelude::*, Node}; use std::path::PathBuf; -use crate::prelude::*; -use crate::{h_stack, HighlightedText}; -use gpui::Div; - #[derive(Clone)] pub struct Symbol(pub Vec); @@ -18,7 +16,7 @@ impl Breadcrumb { Self { path, symbols } } - fn render_separator(&self, cx: &WindowContext) -> Div { + fn render_separator(&self, cx: &WindowContext) -> Node { div() .child(" › ") .text_color(cx.theme().colors().text_muted) @@ -79,7 +77,7 @@ mod stories { pub struct BreadcrumbStory; impl Render for BreadcrumbStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/buffer.rs b/crates/ui2/src/to_extract/buffer.rs index aa4bebc9d5d5cdaa23f1429af7d64b71751c99c0..b04f2221d3158d658600f0650ab820abfd65a26b 100644 --- a/crates/ui2/src/to_extract/buffer.rs +++ b/crates/ui2/src/to_extract/buffer.rs @@ -235,12 +235,12 @@ mod stories { empty_buffer_example, hello_world_rust_buffer_example, hello_world_rust_buffer_with_status_example, Story, }; - use gpui::{rems, Div, Render}; + use gpui::{rems, Node, Render}; pub struct BufferStory; impl Render for BufferStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/buffer_search.rs b/crates/ui2/src/to_extract/buffer_search.rs index 9993cd361294067112c6b629ef9f5e2698e4e3cb..0e6fffa5a705ddc157a9f78e004c9c0eb6aa85be 100644 --- a/crates/ui2/src/to_extract/buffer_search.rs +++ b/crates/ui2/src/to_extract/buffer_search.rs @@ -1,4 +1,4 @@ -use gpui::{Div, Render, View, VisualContext}; +use gpui::{Node, Render, View, VisualContext}; use crate::prelude::*; use crate::{h_stack, Icon, IconButton, IconColor, Input}; @@ -27,9 +27,9 @@ impl BufferSearch { } impl Render for BufferSearch { - type Element = Div; + type Element = Node; - fn render(&mut self, cx: &mut ViewContext) -> Div { + fn render(&mut self, cx: &mut ViewContext) -> Node { h_stack() .bg(cx.theme().colors().toolbar_background) .p_2() diff --git a/crates/ui2/src/to_extract/chat_panel.rs b/crates/ui2/src/to_extract/chat_panel.rs index 538b5dfceba5bb753feb0504b1eb880140aef291..13f35468ff9a141f2474558712b59f04e8c92090 100644 --- a/crates/ui2/src/to_extract/chat_panel.rs +++ b/crates/ui2/src/to_extract/chat_panel.rs @@ -1,7 +1,6 @@ +use crate::{prelude::*, Icon, IconButton, Input, Label, LabelColor}; use chrono::NaiveDateTime; - -use crate::prelude::*; -use crate::{Icon, IconButton, Input, Label, LabelColor}; +use gpui::prelude::*; #[derive(Component)] pub struct ChatPanel { @@ -108,7 +107,7 @@ pub use stories::*; #[cfg(feature = "stories")] mod stories { use chrono::DateTime; - use gpui::{Div, Render}; + use gpui::{Node, Render}; use crate::{Panel, Story}; @@ -117,7 +116,7 @@ mod stories { pub struct ChatPanelStory; impl Render for ChatPanelStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/collab_panel.rs b/crates/ui2/src/to_extract/collab_panel.rs index d56166ad2e25303f1d0d8e01d50fe4e233437cf8..d2ac353e0530577ca85059e90013278486cbf37b 100644 --- a/crates/ui2/src/to_extract/collab_panel.rs +++ b/crates/ui2/src/to_extract/collab_panel.rs @@ -1,7 +1,8 @@ -use crate::{prelude::*, Toggle}; use crate::{ - static_collab_panel_channels, static_collab_panel_current_call, v_stack, Icon, List, ListHeader, + prelude::*, static_collab_panel_channels, static_collab_panel_current_call, v_stack, Icon, + List, ListHeader, Toggle, }; +use gpui::prelude::*; #[derive(Component)] pub struct CollabPanel { @@ -92,12 +93,12 @@ pub use stories::*; mod stories { use super::*; use crate::Story; - use gpui::{Div, Render}; + use gpui::{Node, Render}; pub struct CollabPanelStory; impl Render for CollabPanelStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/command_palette.rs b/crates/ui2/src/to_extract/command_palette.rs index 8a9461c796d053e45fb768f3db4c14f1364f0d27..8a9c61490cd525d91f70eef84ebaa8ffd5583baf 100644 --- a/crates/ui2/src/to_extract/command_palette.rs +++ b/crates/ui2/src/to_extract/command_palette.rs @@ -27,7 +27,7 @@ pub use stories::*; #[cfg(feature = "stories")] mod stories { - use gpui::{Div, Render}; + use gpui::{Node, Render}; use crate::Story; @@ -36,7 +36,7 @@ mod stories { pub struct CommandPaletteStory; impl Render for CommandPaletteStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/copilot.rs b/crates/ui2/src/to_extract/copilot.rs index 8750ab3c51a28cd1f91f67f09c4cd7d419a7b98b..2a2c2c4a2707be09567df13d6611d8f13c57d37a 100644 --- a/crates/ui2/src/to_extract/copilot.rs +++ b/crates/ui2/src/to_extract/copilot.rs @@ -25,7 +25,7 @@ pub use stories::*; #[cfg(feature = "stories")] mod stories { - use gpui::{Div, Render}; + use gpui::{Node, Render}; use crate::Story; @@ -34,7 +34,7 @@ mod stories { pub struct CopilotModalStory; impl Render for CopilotModalStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/editor_pane.rs b/crates/ui2/src/to_extract/editor_pane.rs index fd21e81242c34237f9d16fb63f66312ebc678fbf..4546c24794c961e79dd21b0fd620bef6df94e435 100644 --- a/crates/ui2/src/to_extract/editor_pane.rs +++ b/crates/ui2/src/to_extract/editor_pane.rs @@ -1,6 +1,6 @@ use std::path::PathBuf; -use gpui::{Div, Render, View, VisualContext}; +use gpui::{Node, Render, View, VisualContext}; use crate::prelude::*; use crate::{ @@ -48,9 +48,9 @@ impl EditorPane { } impl Render for EditorPane { - type Element = Div; + type Element = Node; - fn render(&mut self, cx: &mut ViewContext) -> Div { + fn render(&mut self, cx: &mut ViewContext) -> Node { v_stack() .w_full() .h_full() diff --git a/crates/ui2/src/to_extract/language_selector.rs b/crates/ui2/src/to_extract/language_selector.rs index 694ca78e9c92353a7097f33d7ec133278b063bb0..46a10d5c88c923c19380a30647a17b7e56b427dd 100644 --- a/crates/ui2/src/to_extract/language_selector.rs +++ b/crates/ui2/src/to_extract/language_selector.rs @@ -40,12 +40,12 @@ pub use stories::*; mod stories { use super::*; use crate::Story; - use gpui::{Div, Render}; + use gpui::{Node, Render}; pub struct LanguageSelectorStory; impl Render for LanguageSelectorStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/multi_buffer.rs b/crates/ui2/src/to_extract/multi_buffer.rs index 78a22d51d078bc6293e849f8898b53ee2c363109..0649bf12907aa51647a95e600304381abcf536fb 100644 --- a/crates/ui2/src/to_extract/multi_buffer.rs +++ b/crates/ui2/src/to_extract/multi_buffer.rs @@ -40,12 +40,12 @@ pub use stories::*; mod stories { use super::*; use crate::{hello_world_rust_buffer_example, Story}; - use gpui::{Div, Render}; + use gpui::{Node, Render}; pub struct MultiBufferStory; impl Render for MultiBufferStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/notifications_panel.rs b/crates/ui2/src/to_extract/notifications_panel.rs index b2cc4a7846c00acf32b4afb1d65d196f8caeda8a..0a85a15f34cd8bc1ec0725acae22452895f99b9c 100644 --- a/crates/ui2/src/to_extract/notifications_panel.rs +++ b/crates/ui2/src/to_extract/notifications_panel.rs @@ -1,10 +1,9 @@ -use crate::utils::naive_format_distance_from_now; use crate::{ - h_stack, prelude::*, static_new_notification_items_2, v_stack, Avatar, ButtonOrIconButton, - Icon, IconElement, Label, LabelColor, LineHeightStyle, ListHeaderMeta, ListSeparator, - PublicPlayer, UnreadIndicator, + h_stack, prelude::*, static_new_notification_items_2, utils::naive_format_distance_from_now, + v_stack, Avatar, ButtonOrIconButton, ClickHandler, Icon, IconElement, Label, LabelColor, + LineHeightStyle, ListHeader, ListHeaderMeta, ListSeparator, PublicPlayer, UnreadIndicator, }; -use crate::{ClickHandler, ListHeader}; +use gpui::prelude::*; #[derive(Component)] pub struct NotificationsPanel { @@ -353,12 +352,12 @@ pub use stories::*; mod stories { use super::*; use crate::{Panel, Story}; - use gpui::{Div, Render}; + use gpui::{Node, Render}; pub struct NotificationsPanelStory; impl Render for NotificationsPanelStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/panes.rs b/crates/ui2/src/to_extract/panes.rs index b57b77d5eeb8ec71dc4ab075d63269fcac158cbe..288419d8bf8ebdb1af71b668684ebf38619ce73b 100644 --- a/crates/ui2/src/to_extract/panes.rs +++ b/crates/ui2/src/to_extract/panes.rs @@ -59,7 +59,7 @@ impl Pane { } } -impl ParentElement for Pane { +impl ParentComponent for Pane { fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { &mut self.children } diff --git a/crates/ui2/src/to_extract/project_panel.rs b/crates/ui2/src/to_extract/project_panel.rs index d4f5c724265f549eaed54040364abf655c6a5bfd..c55056a7a90f0b3881075c7cf5fdb5b6ecd4a538 100644 --- a/crates/ui2/src/to_extract/project_panel.rs +++ b/crates/ui2/src/to_extract/project_panel.rs @@ -1,7 +1,8 @@ -use crate::prelude::*; use crate::{ - static_project_panel_project_items, static_project_panel_single_items, Input, List, ListHeader, + prelude::*, static_project_panel_project_items, static_project_panel_single_items, Input, List, + ListHeader, }; +use gpui::prelude::*; #[derive(Component)] pub struct ProjectPanel { @@ -54,12 +55,12 @@ pub use stories::*; mod stories { use super::*; use crate::{Panel, Story}; - use gpui::{Div, Render}; + use gpui::{Node, Render}; pub struct ProjectPanelStory; impl Render for ProjectPanelStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/recent_projects.rs b/crates/ui2/src/to_extract/recent_projects.rs index 3d4f551490a47ef5eab616ebf1e2b1f6f0a0a726..83b15a31288568da49ad183a885a62fa5353f5a9 100644 --- a/crates/ui2/src/to_extract/recent_projects.rs +++ b/crates/ui2/src/to_extract/recent_projects.rs @@ -36,12 +36,12 @@ pub use stories::*; mod stories { use super::*; use crate::Story; - use gpui::{Div, Render}; + use gpui::{Node, Render}; pub struct RecentProjectsStory; impl Render for RecentProjectsStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/tab_bar.rs b/crates/ui2/src/to_extract/tab_bar.rs index aff095c639ea48c560b35e738e18f60ea38e8264..e8de2e9e58e3c0a29b97aba559c989e23684061f 100644 --- a/crates/ui2/src/to_extract/tab_bar.rs +++ b/crates/ui2/src/to_extract/tab_bar.rs @@ -1,5 +1,5 @@ -use crate::prelude::*; -use crate::{Icon, IconButton, Tab}; +use crate::{prelude::*, Icon, IconButton, Tab}; +use gpui::prelude::*; #[derive(Component)] pub struct TabBar { @@ -100,12 +100,12 @@ pub use stories::*; mod stories { use super::*; use crate::Story; - use gpui::{Div, Render}; + use gpui::{Node, Render}; pub struct TabBarStory; impl Render for TabBarStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/terminal.rs b/crates/ui2/src/to_extract/terminal.rs index 6c36f35152d8082a3da7fda855a5fc58084b3ae2..5bcbca4fde4ea1fc9d9a6184d0e01e14705594e8 100644 --- a/crates/ui2/src/to_extract/terminal.rs +++ b/crates/ui2/src/to_extract/terminal.rs @@ -83,11 +83,11 @@ pub use stories::*; mod stories { use super::*; use crate::Story; - use gpui::{Div, Render}; + use gpui::{Node, Render}; pub struct TerminalStory; impl Render for TerminalStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/theme_selector.rs b/crates/ui2/src/to_extract/theme_selector.rs index 7f911b50bfa8d9b6273126053a7e791e41754989..7dd169a2f7a6a72c45642f7be41254c7c5727cbe 100644 --- a/crates/ui2/src/to_extract/theme_selector.rs +++ b/crates/ui2/src/to_extract/theme_selector.rs @@ -39,7 +39,7 @@ pub use stories::*; #[cfg(feature = "stories")] mod stories { - use gpui::{Div, Render}; + use gpui::{Node, Render}; use crate::Story; @@ -48,7 +48,7 @@ mod stories { pub struct ThemeSelectorStory; impl Render for ThemeSelectorStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/title_bar.rs b/crates/ui2/src/to_extract/title_bar.rs index 87d7dd4146d051aa5c8e4b8ae6697f487bfb34fa..d805992023779e05c4c82d055bc59310c1dc0537 100644 --- a/crates/ui2/src/to_extract/title_bar.rs +++ b/crates/ui2/src/to_extract/title_bar.rs @@ -1,7 +1,7 @@ use std::sync::atomic::AtomicBool; use std::sync::Arc; -use gpui::{Div, Render, View, VisualContext}; +use gpui::{Node, Render, View, VisualContext}; use crate::prelude::*; use crate::settings::user_settings; @@ -86,9 +86,9 @@ impl TitleBar { } impl Render for TitleBar { - type Element = Div; + type Element = Node; - fn render(&mut self, cx: &mut ViewContext) -> Div { + fn render(&mut self, cx: &mut ViewContext) -> Node { let settings = user_settings(cx); // let has_focus = cx.window_is_active(); @@ -202,9 +202,9 @@ mod stories { } impl Render for TitleBarStory { - type Element = Div; + type Element = Node; - fn render(&mut self, cx: &mut ViewContext) -> Div { + fn render(&mut self, cx: &mut ViewContext) -> Node { Story::container(cx) .child(Story::title_for::<_, TitleBar>(cx)) .child(Story::label(cx, "Default")) diff --git a/crates/ui2/src/to_extract/toolbar.rs b/crates/ui2/src/to_extract/toolbar.rs index 81918f34a790b1ec91aa4ac33cad210972b191cf..1c1795437b5fabba09978af2524fce7ba2f9fa06 100644 --- a/crates/ui2/src/to_extract/toolbar.rs +++ b/crates/ui2/src/to_extract/toolbar.rs @@ -73,7 +73,7 @@ mod stories { use std::path::PathBuf; use std::str::FromStr; - use gpui::{Div, Render}; + use gpui::{Node, Render}; use crate::{Breadcrumb, HighlightedText, Icon, IconButton, Story, Symbol}; @@ -82,7 +82,7 @@ mod stories { pub struct ToolbarStory; impl Render for ToolbarStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/traffic_lights.rs b/crates/ui2/src/to_extract/traffic_lights.rs index 245ff377f2146579f5532123a456f2f1ae498cfc..76898eb19a08f58f195c1efa38fd36c33f7e1cff 100644 --- a/crates/ui2/src/to_extract/traffic_lights.rs +++ b/crates/ui2/src/to_extract/traffic_lights.rs @@ -77,7 +77,7 @@ pub use stories::*; #[cfg(feature = "stories")] mod stories { - use gpui::{Div, Render}; + use gpui::{Node, Render}; use crate::Story; @@ -86,7 +86,7 @@ mod stories { pub struct TrafficLightsStory; impl Render for TrafficLightsStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/workspace.rs b/crates/ui2/src/to_extract/workspace.rs index d6de8a828807606a6d55086af724983ca1a93df0..2ab6b4b3efd2f0d803ff6713f0d3787ec64c9de6 100644 --- a/crates/ui2/src/to_extract/workspace.rs +++ b/crates/ui2/src/to_extract/workspace.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use chrono::DateTime; -use gpui::{px, relative, Div, Render, Size, View, VisualContext}; +use gpui::{px, relative, Node, Render, Size, View, VisualContext}; use settings2::Settings; use theme2::ThemeSettings; @@ -192,9 +192,9 @@ impl Workspace { } impl Render for Workspace { - type Element = Div; + type Element = Node; - fn render(&mut self, cx: &mut ViewContext) -> Div { + fn render(&mut self, cx: &mut ViewContext) -> Node { let root_group = PaneGroup::new_panes( vec![Pane::new( "pane-0", @@ -388,7 +388,7 @@ mod stories { } impl Render for WorkspaceStory { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { div().child(self.workspace.clone()) diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index f21eb84ae21eb59873f63110f2ffeb9696614d13..0e507c0f7c214c80e83119feb93e40d251a01624 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -1,7 +1,7 @@ use crate::{status_bar::StatusItemView, Axis, Workspace}; use gpui::{ - div, Action, AnyView, AppContext, Div, Entity, EntityId, EventEmitter, ParentElement, Render, - Subscription, View, ViewContext, WeakView, WindowContext, + div, Action, AnyView, AppContext, Entity, EntityId, EventEmitter, Node, ParentComponent, + Render, Subscription, View, ViewContext, WeakView, WindowContext, }; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -419,7 +419,7 @@ impl Dock { } impl Render for Dock { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { todo!() @@ -621,7 +621,7 @@ impl PanelButtons { // } impl Render for PanelButtons { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { // todo!() @@ -647,7 +647,7 @@ impl StatusItemView for PanelButtons { #[cfg(any(test, feature = "test-support"))] pub mod test { use super::*; - use gpui::{div, Div, ViewContext, WindowContext}; + use gpui::{div, Node, ViewContext, WindowContext}; pub struct TestPanel { pub position: DockPosition, @@ -672,7 +672,7 @@ pub mod test { } impl Render for TestPanel { - type Element = Div; + type Element = Node; fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { div() diff --git a/crates/workspace2/src/modal_layer.rs b/crates/workspace2/src/modal_layer.rs index 09ffa6c13f92b892ad1717f200a8c1ced84c0361..8beaaed3c35c2f41bc8c1fd7513444259952f34f 100644 --- a/crates/workspace2/src/modal_layer.rs +++ b/crates/workspace2/src/modal_layer.rs @@ -1,6 +1,6 @@ use gpui::{ - div, px, AnyView, Div, EventEmitter, FocusHandle, ParentElement, Render, StatelessInteractive, - Styled, Subscription, View, ViewContext, VisualContext, WindowContext, + div, prelude::*, px, AnyView, EventEmitter, FocusHandle, InteractiveComponent, Node, + ParentComponent, Render, Styled, Subscription, View, ViewContext, VisualContext, WindowContext, }; use ui::v_stack; @@ -76,7 +76,7 @@ impl ModalLayer { } impl Render for ModalLayer { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let Some(active_modal) = &self.active_modal else { diff --git a/crates/workspace2/src/notifications.rs b/crates/workspace2/src/notifications.rs index 7277cc6fc47b33bb93ada4d37c0a2a5c68550f57..8673645b1e5abd1349f6cf4b81ae14a654190d87 100644 --- a/crates/workspace2/src/notifications.rs +++ b/crates/workspace2/src/notifications.rs @@ -165,7 +165,7 @@ impl Workspace { pub mod simple_message_notification { use super::{Notification, NotificationEvent}; - use gpui::{AnyElement, AppContext, Div, EventEmitter, Render, TextStyle, ViewContext}; + use gpui::{AnyElement, AppContext, EventEmitter, Node, Render, TextStyle, ViewContext}; use serde::Deserialize; use std::{borrow::Cow, sync::Arc}; @@ -252,7 +252,7 @@ pub mod simple_message_notification { } impl Render for MessageNotification { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { todo!() diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 2bba684d12c67c2477299ed5915b80a65e7de2d4..ff16ebdc6d7cb965483e77a8cd4bd10efad96c04 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -1,5 +1,3 @@ -// mod dragged_item_receiver; - use crate::{ item::{Item, ItemHandle, ItemSettings, WeakItemHandle}, toolbar::Toolbar, @@ -9,9 +7,9 @@ use crate::{ use anyhow::Result; use collections::{HashMap, HashSet, VecDeque}; use gpui::{ - actions, register_action, AppContext, AsyncWindowContext, Component, Div, EntityId, - EventEmitter, FocusHandle, Model, PromptLevel, Render, Task, View, ViewContext, VisualContext, - WeakView, WindowContext, + actions, prelude::*, register_action, AppContext, AsyncWindowContext, Component, EntityId, + EventEmitter, FocusHandle, Model, Node, PromptLevel, Render, Task, View, ViewContext, + VisualContext, WeakView, WindowContext, }; use parking_lot::Mutex; use project2::{Project, ProjectEntryId, ProjectPath}; @@ -1903,7 +1901,7 @@ impl Pane { // } impl Render for Pane { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { v_stack() @@ -2928,7 +2926,7 @@ struct DraggedTab { } impl Render for DraggedTab { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { div().w_8().h_4().bg(gpui::red()) diff --git a/crates/workspace2/src/status_bar.rs b/crates/workspace2/src/status_bar.rs index fcf6ac3b613219aaf8fa7556de101fb0df5554a5..6ac524f8241e531726ead25db9d54a3dc03fdefd 100644 --- a/crates/workspace2/src/status_bar.rs +++ b/crates/workspace2/src/status_bar.rs @@ -2,8 +2,8 @@ use std::any::TypeId; use crate::{ItemHandle, Pane}; use gpui::{ - div, AnyView, Component, Div, ParentElement, Render, Styled, Subscription, View, ViewContext, - WindowContext, + div, AnyView, Component, Node, ParentComponent, Render, Styled, Subscription, View, + ViewContext, WindowContext, }; use theme2::ActiveTheme; use util::ResultExt; @@ -34,7 +34,7 @@ pub struct StatusBar { } impl Render for StatusBar { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { div() diff --git a/crates/workspace2/src/toolbar.rs b/crates/workspace2/src/toolbar.rs index 1d67da06b223155d076c39e53492ce370391aa06..dfe661d5b01b937bf11a6932f9c1c50887f6f7a4 100644 --- a/crates/workspace2/src/toolbar.rs +++ b/crates/workspace2/src/toolbar.rs @@ -1,6 +1,6 @@ use crate::ItemHandle; use gpui::{ - AnyView, Div, Entity, EntityId, EventEmitter, Render, View, ViewContext, WindowContext, + AnyView, Entity, EntityId, EventEmitter, Node, Render, View, ViewContext, WindowContext, }; pub enum ToolbarItemEvent { @@ -52,7 +52,7 @@ pub struct Toolbar { } impl Render for Toolbar { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { todo!() diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 14a7685a9bff1f91d2171a807bddb83f42cff9b9..df2b1d8f30e4ca95b7786b572efa24c21b7becb6 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -36,12 +36,11 @@ use futures::{ Future, FutureExt, StreamExt, }; use gpui::{ - actions, div, point, rems, size, Action, AnyModel, AnyView, AnyWeakView, AppContext, - AsyncAppContext, AsyncWindowContext, Bounds, Component, Div, Entity, EntityId, EventEmitter, - FocusHandle, GlobalPixels, KeyContext, Model, ModelContext, ParentElement, Point, Render, Size, - StatefulInteractive, StatelessInteractive, StatelessInteractivity, Styled, Subscription, Task, - View, ViewContext, VisualContext, WeakView, WindowBounds, WindowContext, WindowHandle, - WindowOptions, + actions, div, point, prelude::*, rems, size, Action, AnyModel, AnyView, AnyWeakView, + AppContext, AsyncAppContext, AsyncWindowContext, Bounds, Component, Entity, EntityId, + EventEmitter, FocusHandle, GlobalPixels, KeyContext, Model, ModelContext, Node, + ParentComponent, Point, Render, Size, Styled, Subscription, Task, View, ViewContext, WeakView, + WindowBounds, WindowContext, WindowHandle, WindowOptions, }; use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem}; use itertools::Itertools; @@ -443,7 +442,6 @@ struct Follower { impl AppState { #[cfg(any(test, feature = "test-support"))] pub fn test(cx: &mut AppContext) -> Arc { - use gpui::Context; use node_runtime::FakeNodeRuntime; use settings2::SettingsStore; @@ -531,13 +529,7 @@ pub enum Event { pub struct Workspace { weak_self: WeakView, focus_handle: FocusHandle, - workspace_actions: Vec< - Box< - dyn Fn( - Div>, - ) -> Div>, - >, - >, + workspace_actions: Vec) -> Node>>, zoomed: Option, zoomed_position: Option, center: PaneGroup, @@ -3450,7 +3442,6 @@ impl Workspace { #[cfg(any(test, feature = "test-support"))] pub fn test_new(project: Model, cx: &mut ViewContext) -> Self { - use gpui::Context; use node_runtime::FakeNodeRuntime; let client = project.read(cx).client(); @@ -3512,10 +3503,7 @@ impl Workspace { })); } - fn add_workspace_actions_listeners( - &self, - mut div: Div>, - ) -> Div> { + fn add_workspace_actions_listeners(&self, mut div: Node) -> Node { for action in self.workspace_actions.iter() { div = (action)(div) } @@ -3740,14 +3728,14 @@ fn notify_if_database_failed(workspace: WindowHandle, cx: &mut AsyncA impl EventEmitter for Workspace {} impl Render for Workspace { - type Element = Div; + type Element = Node; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let mut context = KeyContext::default(); context.add("Workspace"); self.add_workspace_actions_listeners(div()) - .context(context) + .key_context(context) .relative() .size_full() .flex() From 80014a28ea1f675fb5c5dc4b8f96221d37abf338 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 14 Nov 2023 01:23:09 -0700 Subject: [PATCH 14/23] No compile errors or warnings --- crates/gpui2/src/elements/img.rs | 8 +- crates/gpui2/src/elements/svg.rs | 6 +- crates/gpui2/src/interactive.rs | 47 +------- crates/gpui2/src/key_dispatch.rs | 153 +-------------------------- crates/gpui2/src/styled.rs | 3 +- crates/workspace2/src/modal_layer.rs | 4 +- 6 files changed, 15 insertions(+), 206 deletions(-) diff --git a/crates/gpui2/src/elements/img.rs b/crates/gpui2/src/elements/img.rs index bfa3c6cfae26f71b50d329c9f64628fab7950ed5..c5c5fb628e31989f6a575a9b26f11f4336d7857d 100644 --- a/crates/gpui2/src/elements/img.rs +++ b/crates/gpui2/src/elements/img.rs @@ -50,7 +50,7 @@ impl Element for Img { fn initialize( &mut self, - view_state: &mut V, + _view_state: &mut V, element_state: Option, cx: &mut ViewContext, ) -> Self::ElementState { @@ -59,7 +59,7 @@ impl Element for Img { fn layout( &mut self, - view_state: &mut V, + _view_state: &mut V, element_state: &mut Self::ElementState, cx: &mut ViewContext, ) -> LayoutId { @@ -71,7 +71,7 @@ impl Element for Img { fn paint( &mut self, bounds: Bounds, - view: &mut V, + _view_state: &mut V, element_state: &mut Self::ElementState, cx: &mut ViewContext, ) { @@ -80,7 +80,7 @@ impl Element for Img { bounds.size, element_state, cx, - |style, scroll_offset, cx| { + |style, _scroll_offset, cx| { let corner_radii = style.corner_radii; if let Some(uri) = self.uri.clone() { diff --git a/crates/gpui2/src/elements/svg.rs b/crates/gpui2/src/elements/svg.rs index d0b321c0e2619deb31c04efbff63954712037f53..4b441ad425ee1bc4fe9b860635d8214ace1c21c3 100644 --- a/crates/gpui2/src/elements/svg.rs +++ b/crates/gpui2/src/elements/svg.rs @@ -39,7 +39,7 @@ impl Element for Svg { fn initialize( &mut self, - view_state: &mut V, + _view_state: &mut V, element_state: Option, cx: &mut ViewContext, ) -> Self::ElementState { @@ -48,7 +48,7 @@ impl Element for Svg { fn layout( &mut self, - view_state: &mut V, + _view_state: &mut V, element_state: &mut Self::ElementState, cx: &mut ViewContext, ) -> LayoutId { @@ -60,7 +60,7 @@ impl Element for Svg { fn paint( &mut self, bounds: Bounds, - view: &mut V, + _view_state: &mut V, element_state: &mut Self::ElementState, cx: &mut ViewContext, ) where diff --git a/crates/gpui2/src/interactive.rs b/crates/gpui2/src/interactive.rs index 702a7ca5dbfacf0849e5496f991e8effa3183815..cb8be7c2962db30df0c29409245ad6882dd9360a 100644 --- a/crates/gpui2/src/interactive.rs +++ b/crates/gpui2/src/interactive.rs @@ -1,16 +1,9 @@ use crate::{ - div, point, px, AnyDrag, AnyTooltip, AnyView, AppContext, Bounds, Component, DispatchPhase, - FocusHandle, Keystroke, Modifiers, Node, Pixels, Point, Render, SharedString, StyleRefinement, - Task, ViewContext, + div, point, Component, FocusHandle, Keystroke, Modifiers, Node, Pixels, Point, Render, + ViewContext, }; use smallvec::SmallVec; -use std::{ - any::Any, fmt::Debug, marker::PhantomData, ops::Deref, path::PathBuf, sync::Arc, time::Duration, -}; - -const DRAG_THRESHOLD: f64 = 2.; -const TOOLTIP_DELAY: Duration = Duration::from_millis(500); -const TOOLTIP_OFFSET: Point = Point::new(px(10.0), px(8.0)); +use std::{any::Any, fmt::Debug, marker::PhantomData, ops::Deref, path::PathBuf}; #[derive(Clone, Debug, Eq, PartialEq)] pub struct KeyDownEvent { @@ -290,40 +283,6 @@ pub struct FocusEvent { pub focused: Option, } -pub type MouseDownListener = Box< - dyn Fn(&mut V, &MouseDownEvent, &Bounds, DispatchPhase, &mut ViewContext) + 'static, ->; -pub type MouseUpListener = Box< - dyn Fn(&mut V, &MouseUpEvent, &Bounds, DispatchPhase, &mut ViewContext) + 'static, ->; - -pub type MouseMoveListener = Box< - dyn Fn(&mut V, &MouseMoveEvent, &Bounds, DispatchPhase, &mut ViewContext) + 'static, ->; - -pub type ScrollWheelListener = Box< - dyn Fn(&mut V, &ScrollWheelEvent, &Bounds, DispatchPhase, &mut ViewContext) - + 'static, ->; - -pub type ClickListener = Box) + 'static>; - -pub(crate) type DragListener = - Box, &mut ViewContext) -> AnyDrag + 'static>; - -pub(crate) type HoverListener = Box) + 'static>; - -pub(crate) type TooltipBuilder = Arc) -> AnyView + 'static>; - -pub(crate) type KeyDownListener = - Box) + 'static>; - -pub(crate) type KeyUpListener = - Box) + 'static>; - -pub type ActionListener = - Box) + 'static>; - #[cfg(test)] mod test { use crate::{ diff --git a/crates/gpui2/src/key_dispatch.rs b/crates/gpui2/src/key_dispatch.rs index afe0b0f3e22e44e34476cb990d1a38e640f9a221..b06acae43d86f196d2d50d16d120afc26a7313b1 100644 --- a/crates/gpui2/src/key_dispatch.rs +++ b/crates/gpui2/src/key_dispatch.rs @@ -1,11 +1,9 @@ use crate::{ - build_action_from_type, Action, Bounds, DispatchPhase, FocusEvent, FocusHandle, FocusId, - KeyContext, KeyMatch, Keymap, Keystroke, KeystrokeMatcher, MouseDownEvent, Pixels, Style, - StyleRefinement, ViewContext, WindowContext, + build_action_from_type, Action, DispatchPhase, FocusId, KeyContext, KeyMatch, Keymap, + Keystroke, KeystrokeMatcher, WindowContext, }; use collections::HashMap; use parking_lot::Mutex; -use refineable::Refineable; use smallvec::SmallVec; use std::{ any::{Any, TypeId}, @@ -14,10 +12,6 @@ use std::{ }; use util::ResultExt; -pub type FocusListeners = SmallVec<[FocusListener; 2]>; -pub type FocusListener = - Box) + 'static>; - #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] pub struct DispatchNodeId(usize); @@ -199,146 +193,3 @@ impl DispatchTree { *self.node_stack.last().unwrap() } } - -pub trait KeyDispatch: 'static { - fn as_focusable(&self) -> Option<&FocusableKeyDispatch>; - fn as_focusable_mut(&mut self) -> Option<&mut FocusableKeyDispatch>; - fn key_context(&self) -> &KeyContext; - fn key_context_mut(&mut self) -> &mut KeyContext; - - fn initialize( - &mut self, - focus_handle: Option, - cx: &mut ViewContext, - f: impl FnOnce(Option, &mut ViewContext) -> R, - ) -> R { - let focus_handle = if let Some(focusable) = self.as_focusable_mut() { - let focus_handle = focusable - .focus_handle - .get_or_insert_with(|| focus_handle.unwrap_or_else(|| cx.focus_handle())) - .clone(); - for listener in focusable.focus_listeners.drain(..) { - let focus_handle = focus_handle.clone(); - cx.on_focus_changed(move |view, event, cx| { - listener(view, &focus_handle, event, cx) - }); - } - Some(focus_handle) - } else { - None - }; - - cx.with_key_dispatch(self.key_context().clone(), focus_handle, f) - } - - fn refine_style(&self, style: &mut Style, cx: &WindowContext) { - if let Some(focusable) = self.as_focusable() { - let focus_handle = focusable - .focus_handle - .as_ref() - .expect("must call initialize before refine_style"); - if focus_handle.contains_focused(cx) { - style.refine(&focusable.focus_in_style); - } - - if focus_handle.within_focused(cx) { - style.refine(&focusable.in_focus_style); - } - - if focus_handle.is_focused(cx) { - style.refine(&focusable.focus_style); - } - } - } - - fn paint(&self, bounds: Bounds, cx: &mut WindowContext) { - if let Some(focusable) = self.as_focusable() { - let focus_handle = focusable - .focus_handle - .clone() - .expect("must call initialize before paint"); - cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| { - if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { - if !cx.default_prevented() { - cx.focus(&focus_handle); - cx.prevent_default(); - } - } - }) - } - } -} - -pub struct FocusableKeyDispatch { - pub non_focusable: NonFocusableKeyDispatch, - pub focus_handle: Option, - pub focus_listeners: FocusListeners, - pub focus_style: StyleRefinement, - pub focus_in_style: StyleRefinement, - pub in_focus_style: StyleRefinement, -} - -impl FocusableKeyDispatch { - pub fn new(non_focusable: NonFocusableKeyDispatch) -> Self { - Self { - non_focusable, - focus_handle: None, - focus_listeners: FocusListeners::default(), - focus_style: StyleRefinement::default(), - focus_in_style: StyleRefinement::default(), - in_focus_style: StyleRefinement::default(), - } - } - - pub fn tracked(non_focusable: NonFocusableKeyDispatch, handle: &FocusHandle) -> Self { - Self { - non_focusable, - focus_handle: Some(handle.clone()), - focus_listeners: FocusListeners::default(), - focus_style: StyleRefinement::default(), - focus_in_style: StyleRefinement::default(), - in_focus_style: StyleRefinement::default(), - } - } -} - -impl KeyDispatch for FocusableKeyDispatch { - fn as_focusable(&self) -> Option<&FocusableKeyDispatch> { - Some(self) - } - - fn as_focusable_mut(&mut self) -> Option<&mut FocusableKeyDispatch> { - Some(self) - } - - fn key_context(&self) -> &KeyContext { - &self.non_focusable.key_context - } - - fn key_context_mut(&mut self) -> &mut KeyContext { - &mut self.non_focusable.key_context - } -} - -#[derive(Default)] -pub struct NonFocusableKeyDispatch { - pub(crate) key_context: KeyContext, -} - -impl KeyDispatch for NonFocusableKeyDispatch { - fn as_focusable(&self) -> Option<&FocusableKeyDispatch> { - None - } - - fn as_focusable_mut(&mut self) -> Option<&mut FocusableKeyDispatch> { - None - } - - fn key_context(&self) -> &KeyContext { - &self.key_context - } - - fn key_context_mut(&mut self) -> &mut KeyContext { - &mut self.key_context - } -} diff --git a/crates/gpui2/src/styled.rs b/crates/gpui2/src/styled.rs index 71e38efd9b74e7a4cdf5731c28e15a3311dd2378..beaf664dd8a51fcd58eba73feb247992945f0217 100644 --- a/crates/gpui2/src/styled.rs +++ b/crates/gpui2/src/styled.rs @@ -1,10 +1,9 @@ use crate::{ self as gpui, hsla, point, px, relative, rems, AbsoluteLength, AlignItems, CursorStyle, DefiniteLength, Display, Fill, FlexDirection, Hsla, JustifyContent, Length, Position, - SharedString, Style, StyleRefinement, Visibility, + SharedString, StyleRefinement, Visibility, }; use crate::{BoxShadow, TextStyleRefinement}; -use refineable::Refineable; use smallvec::{smallvec, SmallVec}; use taffy::style::Overflow; diff --git a/crates/workspace2/src/modal_layer.rs b/crates/workspace2/src/modal_layer.rs index 8beaaed3c35c2f41bc8c1fd7513444259952f34f..6cc08d56a63ca776edda240a7ef611ea65f9a4ac 100644 --- a/crates/workspace2/src/modal_layer.rs +++ b/crates/workspace2/src/modal_layer.rs @@ -1,6 +1,6 @@ use gpui::{ - div, prelude::*, px, AnyView, EventEmitter, FocusHandle, InteractiveComponent, Node, - ParentComponent, Render, Styled, Subscription, View, ViewContext, VisualContext, WindowContext, + div, prelude::*, px, AnyView, EventEmitter, FocusHandle, Node, Render, Subscription, View, + ViewContext, WindowContext, }; use ui::v_stack; From a5306c23122de470e7483ddc9b20ebc2c7b0f7f3 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 14 Nov 2023 01:25:10 -0700 Subject: [PATCH 15/23] Remove div module --- crates/gpui2/src/elements/div.rs | 334 ------------------------------- 1 file changed, 334 deletions(-) delete mode 100644 crates/gpui2/src/elements/div.rs diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs deleted file mode 100644 index 537c14633948d4077becf489ce1095403f7945c5..0000000000000000000000000000000000000000 --- a/crates/gpui2/src/elements/div.rs +++ /dev/null @@ -1,334 +0,0 @@ -use std::fmt::Debug; - -use crate::{ - point, AnyElement, BorrowWindow, Bounds, Component, Element, ElementId, ElementInteractivity, - FocusHandle, FocusListeners, Focusable, FocusableKeyDispatch, GroupBounds, - InteractiveElementState, KeyContext, KeyDispatch, LayoutId, NonFocusableKeyDispatch, Overflow, - ParentElement, Pixels, Point, SharedString, StatefulInteractive, StatefulInteractivity, - StatelessInteractive, StatelessInteractivity, Style, StyleRefinement, Styled, ViewContext, - Visibility, -}; -use refineable::Refineable; -use smallvec::SmallVec; -use util::ResultExt; - -pub struct Div< - V: 'static, - I: ElementInteractivity = StatelessInteractivity, - K: KeyDispatch = NonFocusableKeyDispatch, -> { - interactivity: I, - key_dispatch: K, - children: SmallVec<[AnyElement; 2]>, - group: Option, - base_style: StyleRefinement, -} - -pub fn div() -> Div, NonFocusableKeyDispatch> { - Div { - interactivity: StatelessInteractivity::default(), - key_dispatch: NonFocusableKeyDispatch::default(), - children: SmallVec::new(), - group: None, - base_style: StyleRefinement::default(), - } -} - -impl Div, F> -where - V: 'static, - F: KeyDispatch, -{ - pub fn id(self, id: impl Into) -> Div, F> { - Div { - interactivity: StatefulInteractivity::new(id.into(), self.interactivity), - key_dispatch: self.key_dispatch, - children: self.children, - group: self.group, - base_style: self.base_style, - } - } -} - -impl Div -where - I: ElementInteractivity, - F: KeyDispatch, -{ - pub fn context(mut self, context: C) -> Self - where - Self: Sized, - C: TryInto, - C::Error: Debug, - { - if let Some(context) = context.try_into().log_err() { - *self.key_dispatch.key_context_mut() = context; - } - self - } - - pub fn compute_style( - &self, - bounds: Bounds, - element_state: &DivState, - cx: &mut ViewContext, - ) -> Style { - let mut computed_style = Style::default(); - computed_style.refine(&self.base_style); - self.key_dispatch.refine_style(&mut computed_style, cx); - self.interactivity.refine_style( - &mut computed_style, - bounds, - &element_state.interactive, - cx, - ); - computed_style - } -} - -impl Div, NonFocusableKeyDispatch> { - pub fn focusable(self) -> Div, FocusableKeyDispatch> { - Div { - interactivity: self.interactivity, - key_dispatch: FocusableKeyDispatch::new(self.key_dispatch), - children: self.children, - group: self.group, - base_style: self.base_style, - } - } - - pub fn track_focus( - self, - handle: &FocusHandle, - ) -> Div, FocusableKeyDispatch> { - Div { - interactivity: self.interactivity, - key_dispatch: FocusableKeyDispatch::tracked(self.key_dispatch, handle), - children: self.children, - group: self.group, - base_style: self.base_style, - } - } -} - -impl Div, NonFocusableKeyDispatch> { - pub fn track_focus( - self, - handle: &FocusHandle, - ) -> Div, FocusableKeyDispatch> { - Div { - interactivity: self.interactivity.into_stateful(handle), - key_dispatch: FocusableKeyDispatch::tracked(self.key_dispatch, handle), - children: self.children, - group: self.group, - base_style: self.base_style, - } - } -} - -impl Focusable for Div> -where - V: 'static, - I: ElementInteractivity, -{ - fn focus_listeners(&mut self) -> &mut FocusListeners { - &mut self.key_dispatch.focus_listeners - } - - fn set_focus_style(&mut self, style: StyleRefinement) { - self.key_dispatch.focus_style = style; - } - - fn set_focus_in_style(&mut self, style: StyleRefinement) { - self.key_dispatch.focus_in_style = style; - } - - fn set_in_focus_style(&mut self, style: StyleRefinement) { - self.key_dispatch.in_focus_style = style; - } -} - -#[derive(Default)] -pub struct DivState { - interactive: InteractiveElementState, - focus_handle: Option, - child_layout_ids: SmallVec<[LayoutId; 4]>, -} - -impl Element for Div -where - I: ElementInteractivity, - F: KeyDispatch, -{ - type ElementState = DivState; - - fn id(&self) -> Option { - self.interactivity - .as_stateful() - .map(|identified| identified.id.clone()) - } - - fn initialize( - &mut self, - view_state: &mut V, - element_state: Option, - cx: &mut ViewContext, - ) -> Self::ElementState { - let mut element_state = element_state.unwrap_or_default(); - cx.with_element_id(self.id(), |cx| { - self.key_dispatch.initialize( - element_state.focus_handle.take(), - cx, - |focus_handle, cx| { - self.interactivity.initialize(cx); - element_state.focus_handle = focus_handle; - for child in &mut self.children { - child.initialize(view_state, cx); - } - }, - ); - }); - element_state - } - - fn layout( - &mut self, - view_state: &mut V, - element_state: &mut Self::ElementState, - cx: &mut ViewContext, - ) -> LayoutId { - let style = self.compute_style(Bounds::default(), element_state, cx); - style.apply_text_style(cx, |cx| { - cx.with_element_id(self.id(), |cx| { - let layout_ids = self - .children - .iter_mut() - .map(|child| child.layout(view_state, cx)) - .collect::>(); - element_state.child_layout_ids = layout_ids.clone(); - cx.request_layout(&style, layout_ids) - }) - }) - } - - fn paint( - &mut self, - bounds: Bounds, - view_state: &mut V, - element_state: &mut Self::ElementState, - cx: &mut ViewContext, - ) { - cx.with_element_id(self.id(), |cx| { - let style = self.compute_style(bounds, element_state, cx); - if style.visibility == Visibility::Hidden { - return; - } - - if let Some(mouse_cursor) = style.mouse_cursor { - let hovered = bounds.contains_point(&cx.mouse_position()); - if hovered { - cx.set_cursor_style(mouse_cursor); - } - } - - if let Some(group) = self.group.clone() { - GroupBounds::push(group, bounds, cx); - } - - let z_index = style.z_index.unwrap_or(0); - - let mut child_min = point(Pixels::MAX, Pixels::MAX); - let mut child_max = Point::default(); - - let content_size = if element_state.child_layout_ids.is_empty() { - bounds.size - } else { - for child_layout_id in &element_state.child_layout_ids { - let child_bounds = cx.layout_bounds(*child_layout_id); - child_min = child_min.min(&child_bounds.origin); - child_max = child_max.max(&child_bounds.lower_right()); - } - (child_max - child_min).into() - }; - - cx.with_z_index(z_index, |cx| { - cx.with_z_index(0, |cx| { - style.paint(bounds, cx); - self.key_dispatch.paint(bounds, cx); - self.interactivity.handle_events( - bounds, - content_size, - style.overflow, - &mut element_state.interactive, - cx, - ); - }); - cx.with_z_index(1, |cx| { - style.apply_text_style(cx, |cx| { - style.apply_overflow(bounds, cx, |cx| { - let scroll_offset = element_state.interactive.scroll_offset(); - cx.with_element_offset(scroll_offset.unwrap_or_default(), |cx| { - for child in &mut self.children { - child.paint(view_state, cx); - } - }); - }) - }) - }); - }); - - if let Some(group) = self.group.as_ref() { - GroupBounds::pop(group, cx); - } - }) - } -} - -impl Component for Div -where - I: ElementInteractivity, - F: KeyDispatch, -{ - fn render(self) -> AnyElement { - AnyElement::new(self) - } -} - -impl ParentElement for Div -where - I: ElementInteractivity, - F: KeyDispatch, -{ - fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { - &mut self.children - } -} - -impl Styled for Div -where - I: ElementInteractivity, - F: KeyDispatch, -{ - fn style(&mut self) -> &mut StyleRefinement { - &mut self.base_style - } -} - -impl StatelessInteractive for Div -where - I: ElementInteractivity, - F: KeyDispatch, -{ - fn stateless_interactivity(&mut self) -> &mut StatelessInteractivity { - self.interactivity.as_stateless_mut() - } -} - -impl StatefulInteractive for Div, F> -where - F: KeyDispatch, -{ - fn stateful_interactivity(&mut self) -> &mut StatefulInteractivity { - &mut self.interactivity - } -} From be18c47912ca6baea99d6da11aa38b4d5008f183 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 14 Nov 2023 01:38:13 -0700 Subject: [PATCH 16/23] Remove unnecessary with_element_id calls --- crates/gpui2/src/elements/node.rs | 68 +++++++++++++++---------------- 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/crates/gpui2/src/elements/node.rs b/crates/gpui2/src/elements/node.rs index 49c447254e62f0a72a4880beec2700e3e7a67442..7e61c8fbb496853a906a801eddbe57c5c794580f 100644 --- a/crates/gpui2/src/elements/node.rs +++ b/crates/gpui2/src/elements/node.rs @@ -746,13 +746,11 @@ where f: impl FnOnce(Style, &mut ViewContext) -> LayoutId, ) -> LayoutId { let style = self.compute_style(None, element_state, cx); - cx.with_element_id(self.element_id.clone(), |cx| { - cx.with_key_dispatch( - self.key_context.clone(), - self.tracked_focus_handle.clone(), - |_, cx| f(style, cx), - ) - }) + cx.with_key_dispatch( + self.key_context.clone(), + self.tracked_focus_handle.clone(), + |_, cx| f(style, cx), + ) } pub fn paint( @@ -1037,40 +1035,38 @@ where .as_ref() .map(|scroll_offset| *scroll_offset.lock()); - cx.with_element_id(self.element_id.clone(), |cx| { - cx.with_key_dispatch( - self.key_context.clone(), - element_state.focus_handle.clone(), - |_, cx| { - for listener in self.key_down_listeners.drain(..) { - cx.on_key_event(move |state, event: &KeyDownEvent, phase, cx| { - listener(state, event, phase, cx); - }) - } + cx.with_key_dispatch( + self.key_context.clone(), + element_state.focus_handle.clone(), + |_, cx| { + for listener in self.key_down_listeners.drain(..) { + cx.on_key_event(move |state, event: &KeyDownEvent, phase, cx| { + listener(state, event, phase, cx); + }) + } - for listener in self.key_up_listeners.drain(..) { - cx.on_key_event(move |state, event: &KeyUpEvent, phase, cx| { - listener(state, event, phase, cx); - }) - } + for listener in self.key_up_listeners.drain(..) { + cx.on_key_event(move |state, event: &KeyUpEvent, phase, cx| { + listener(state, event, phase, cx); + }) + } - for (action_type, listener) in self.action_listeners.drain(..) { - cx.on_action(action_type, listener) - } + for (action_type, listener) in self.action_listeners.drain(..) { + cx.on_action(action_type, listener) + } - if let Some(focus_handle) = element_state.focus_handle.as_ref() { - for listener in self.focus_listeners.drain(..) { - let focus_handle = focus_handle.clone(); - cx.on_focus_changed(move |view, event, cx| { - listener(view, &focus_handle, event, cx) - }); - } + if let Some(focus_handle) = element_state.focus_handle.as_ref() { + for listener in self.focus_listeners.drain(..) { + let focus_handle = focus_handle.clone(); + cx.on_focus_changed(move |view, event, cx| { + listener(view, &focus_handle, event, cx) + }); } + } - f(style, scroll_offset.unwrap_or_default(), cx) - }, - ); - }); + f(style, scroll_offset.unwrap_or_default(), cx) + }, + ); if let Some(group) = self.group.as_ref() { GroupBounds::pop(group, cx); From c6e8a097a37bef59bc5a5e5a25e6edf831907a98 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 14 Nov 2023 01:41:55 -0700 Subject: [PATCH 17/23] Rename back to div --- crates/command_palette2/src/command_palette.rs | 8 ++++---- crates/go_to_line2/src/go_to_line.rs | 6 +++--- crates/gpui2/src/elements/{node.rs => div.rs} | 16 ++++++++-------- .../gpui2/src/{elements.rs => elements/mod.rs} | 6 ++---- crates/gpui2/src/interactive.rs | 8 ++++---- crates/picker2/src/picker2.rs | 4 ++-- crates/storybook2/src/stories/colors.rs | 4 ++-- crates/storybook2/src/stories/focus.rs | 4 ++-- crates/storybook2/src/stories/kitchen_sink.rs | 4 ++-- crates/storybook2/src/stories/picker.rs | 6 +++--- crates/storybook2/src/stories/scroll.rs | 4 ++-- crates/storybook2/src/stories/text.rs | 4 ++-- crates/storybook2/src/stories/z_index.rs | 6 +++--- crates/storybook2/src/storybook2.rs | 4 ++-- crates/theme2/src/players.rs | 4 ++-- crates/theme2/src/story.rs | 4 ++-- crates/ui2/src/components/avatar.rs | 4 ++-- crates/ui2/src/components/button.rs | 4 ++-- crates/ui2/src/components/checkbox.rs | 4 ++-- crates/ui2/src/components/context_menu.rs | 4 ++-- crates/ui2/src/components/details.rs | 4 ++-- crates/ui2/src/components/elevated_surface.rs | 6 +++--- crates/ui2/src/components/facepile.rs | 4 ++-- crates/ui2/src/components/icon.rs | 4 ++-- crates/ui2/src/components/input.rs | 4 ++-- crates/ui2/src/components/keybinding.rs | 4 ++-- crates/ui2/src/components/label.rs | 4 ++-- crates/ui2/src/components/palette.rs | 4 ++-- crates/ui2/src/components/panel.rs | 4 ++-- crates/ui2/src/components/stack.rs | 6 +++--- crates/ui2/src/components/tab.rs | 6 +++--- crates/ui2/src/components/toast.rs | 4 ++-- crates/ui2/src/components/tooltip.rs | 4 ++-- crates/ui2/src/story.rs | 4 ++-- crates/ui2/src/to_extract/assistant_panel.rs | 4 ++-- crates/ui2/src/to_extract/breadcrumb.rs | 6 +++--- crates/ui2/src/to_extract/buffer.rs | 4 ++-- crates/ui2/src/to_extract/buffer_search.rs | 6 +++--- crates/ui2/src/to_extract/chat_panel.rs | 4 ++-- crates/ui2/src/to_extract/collab_panel.rs | 4 ++-- crates/ui2/src/to_extract/command_palette.rs | 4 ++-- crates/ui2/src/to_extract/copilot.rs | 4 ++-- crates/ui2/src/to_extract/editor_pane.rs | 6 +++--- crates/ui2/src/to_extract/language_selector.rs | 4 ++-- crates/ui2/src/to_extract/multi_buffer.rs | 4 ++-- crates/ui2/src/to_extract/notifications_panel.rs | 4 ++-- crates/ui2/src/to_extract/project_panel.rs | 4 ++-- crates/ui2/src/to_extract/recent_projects.rs | 4 ++-- crates/ui2/src/to_extract/tab_bar.rs | 4 ++-- crates/ui2/src/to_extract/terminal.rs | 4 ++-- crates/ui2/src/to_extract/theme_selector.rs | 4 ++-- crates/ui2/src/to_extract/title_bar.rs | 10 +++++----- crates/ui2/src/to_extract/toolbar.rs | 4 ++-- crates/ui2/src/to_extract/traffic_lights.rs | 4 ++-- crates/ui2/src/to_extract/workspace.rs | 8 ++++---- crates/workspace2/src/dock.rs | 10 +++++----- crates/workspace2/src/modal_layer.rs | 4 ++-- crates/workspace2/src/notifications.rs | 4 ++-- crates/workspace2/src/pane.rs | 6 +++--- crates/workspace2/src/status_bar.rs | 4 ++-- crates/workspace2/src/toolbar.rs | 4 ++-- crates/workspace2/src/workspace2.rs | 8 ++++---- 62 files changed, 154 insertions(+), 156 deletions(-) rename crates/gpui2/src/elements/{node.rs => div.rs} (99%) rename crates/gpui2/src/{elements.rs => elements/mod.rs} (67%) diff --git a/crates/command_palette2/src/command_palette.rs b/crates/command_palette2/src/command_palette.rs index 139d8a16c76602c0f9e8aee4a93e802e5273aeb4..cb0f2c20d41f5f48b016f5cf74395343e9e4e0b6 100644 --- a/crates/command_palette2/src/command_palette.rs +++ b/crates/command_palette2/src/command_palette.rs @@ -1,8 +1,8 @@ use collections::{CommandPaletteFilter, HashMap}; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{ - actions, div, prelude::*, Action, AppContext, Component, EventEmitter, FocusHandle, Keystroke, - Node, ParentComponent, Render, Styled, View, ViewContext, VisualContext, WeakView, + actions, div, prelude::*, Action, AppContext, Component, Div, EventEmitter, FocusHandle, + Keystroke, ParentComponent, Render, Styled, View, ViewContext, VisualContext, WeakView, WindowContext, }; use picker::{Picker, PickerDelegate}; @@ -77,7 +77,7 @@ impl Modal for CommandPalette { } impl Render for CommandPalette { - type Element = Node; + type Element = Div; fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { v_stack().w_96().child(self.picker.clone()) @@ -148,7 +148,7 @@ impl CommandPaletteDelegate { } impl PickerDelegate for CommandPaletteDelegate { - type ListItem = Node>; + type ListItem = Div>; fn placeholder_text(&self) -> Arc { "Execute a command...".into() diff --git a/crates/go_to_line2/src/go_to_line.rs b/crates/go_to_line2/src/go_to_line.rs index 9f2ba6db219e899d4cf6df1f91575943cf9427aa..abafe93cdd28947ba6e4b7cde2fa5bdd20393e53 100644 --- a/crates/go_to_line2/src/go_to_line.rs +++ b/crates/go_to_line2/src/go_to_line.rs @@ -1,7 +1,7 @@ use editor::{display_map::ToDisplayPoint, scroll::autoscroll::Autoscroll, Editor}; use gpui::{ - actions, div, prelude::*, AppContext, EventEmitter, Node, ParentComponent, Render, - SharedString, Styled, Subscription, View, ViewContext, VisualContext, WindowContext, + actions, div, prelude::*, AppContext, Div, EventEmitter, ParentComponent, Render, SharedString, + Styled, Subscription, View, ViewContext, VisualContext, WindowContext, }; use text::{Bias, Point}; use theme::ActiveTheme; @@ -145,7 +145,7 @@ impl GoToLine { } impl Render for GoToLine { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { modal(cx) diff --git a/crates/gpui2/src/elements/node.rs b/crates/gpui2/src/elements/div.rs similarity index 99% rename from crates/gpui2/src/elements/node.rs rename to crates/gpui2/src/elements/div.rs index 7e61c8fbb496853a906a801eddbe57c5c794580f..c0f916ae966033749cd78207bd42f14597906c11 100644 --- a/crates/gpui2/src/elements/node.rs +++ b/crates/gpui2/src/elements/div.rs @@ -538,37 +538,37 @@ pub type KeyUpListener = pub type ActionListener = Box) + 'static>; -pub fn div() -> Node { - Node { +pub fn div() -> Div { + Div { interactivity: Interactivity::default(), children: SmallVec::default(), } } -pub struct Node { +pub struct Div { interactivity: Interactivity, children: SmallVec<[AnyElement; 2]>, } -impl Styled for Node { +impl Styled for Div { fn style(&mut self) -> &mut StyleRefinement { &mut self.interactivity.base_style } } -impl InteractiveComponent for Node { +impl InteractiveComponent for Div { fn interactivity(&mut self) -> &mut Interactivity { &mut self.interactivity } } -impl ParentComponent for Node { +impl ParentComponent for Div { fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { &mut self.children } } -impl Element for Node { +impl Element for Div { type ElementState = NodeState; fn element_id(&self) -> Option { @@ -671,7 +671,7 @@ impl Element for Node { } } -impl Component for Node { +impl Component for Div { fn render(self) -> AnyElement { AnyElement::new(self) } diff --git a/crates/gpui2/src/elements.rs b/crates/gpui2/src/elements/mod.rs similarity index 67% rename from crates/gpui2/src/elements.rs rename to crates/gpui2/src/elements/mod.rs index 5bf9e6202b1a81374592bb1e03b9b277ce3365fa..eb061f7d34c8e77c1a366123818b253d33620c7a 100644 --- a/crates/gpui2/src/elements.rs +++ b/crates/gpui2/src/elements/mod.rs @@ -1,13 +1,11 @@ -// mod div; +mod div; mod img; -mod node; mod svg; mod text; mod uniform_list; -// pub use div::*; +pub use div::*; pub use img::*; -pub use node::*; pub use svg::*; pub use text::*; pub use uniform_list::*; diff --git a/crates/gpui2/src/interactive.rs b/crates/gpui2/src/interactive.rs index cb8be7c2962db30df0c29409245ad6882dd9360a..5ce78553fd60b59fcb5e531453d96116afa756be 100644 --- a/crates/gpui2/src/interactive.rs +++ b/crates/gpui2/src/interactive.rs @@ -1,5 +1,5 @@ use crate::{ - div, point, Component, FocusHandle, Keystroke, Modifiers, Node, Pixels, Point, Render, + div, point, Component, FocusHandle, Keystroke, Modifiers, Div, Pixels, Point, Render, ViewContext, }; use smallvec::SmallVec; @@ -194,7 +194,7 @@ impl Deref for MouseExitEvent { pub struct ExternalPaths(pub(crate) SmallVec<[PathBuf; 2]>); impl Render for ExternalPaths { - type Element = Node; + type Element = Div; fn render(&mut self, _: &mut ViewContext) -> Self::Element { div() // Intentionally left empty because the platform will render icons for the dragged files @@ -286,7 +286,7 @@ pub struct FocusEvent { #[cfg(test)] mod test { use crate::{ - self as gpui, div, FocusHandle, InteractiveComponent, KeyBinding, Keystroke, Node, + self as gpui, div, FocusHandle, InteractiveComponent, KeyBinding, Keystroke, Div, ParentComponent, Render, Stateful, TestAppContext, VisualContext, }; @@ -299,7 +299,7 @@ mod test { actions!(TestAction); impl Render for TestView { - type Element = Stateful>; + type Element = Stateful>; fn render(&mut self, _: &mut gpui::ViewContext) -> Self::Element { div().id("testview").child( diff --git a/crates/picker2/src/picker2.rs b/crates/picker2/src/picker2.rs index 189c07b49afde5c06fe327aa1de10422d35a878b..0a2a50deb6a1610011c893b843d5daa01ad748cb 100644 --- a/crates/picker2/src/picker2.rs +++ b/crates/picker2/src/picker2.rs @@ -1,6 +1,6 @@ use editor::Editor; use gpui::{ - div, uniform_list, Component, Node, ParentComponent, Render, Styled, Task, + div, uniform_list, Component, Div, ParentComponent, Render, Styled, Task, UniformListScrollHandle, View, ViewContext, VisualContext, WindowContext, }; use std::{cmp, sync::Arc}; @@ -139,7 +139,7 @@ impl Picker { } impl Render for Picker { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { div() diff --git a/crates/storybook2/src/stories/colors.rs b/crates/storybook2/src/stories/colors.rs index a5e9efc0da505973f2d5106352a9108d40d3c085..4f8c54fa6fa67404453737f33a79113e018e346f 100644 --- a/crates/storybook2/src/stories/colors.rs +++ b/crates/storybook2/src/stories/colors.rs @@ -1,12 +1,12 @@ use crate::story::Story; -use gpui::{prelude::*, px, Node, Render}; +use gpui::{prelude::*, px, Div, Render}; use theme2::{default_color_scales, ColorScaleStep}; use ui::prelude::*; pub struct ColorsStory; impl Render for ColorsStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let color_scales = default_color_scales(); diff --git a/crates/storybook2/src/stories/focus.rs b/crates/storybook2/src/stories/focus.rs index a6b27c460df399e14a42a43561ac4cb79bd33769..ff9a4da876a021a79b7ccb9a69c89d604122182d 100644 --- a/crates/storybook2/src/stories/focus.rs +++ b/crates/storybook2/src/stories/focus.rs @@ -1,5 +1,5 @@ use gpui::{ - actions, div, prelude::*, FocusHandle, Focusable, KeyBinding, Node, Render, Stateful, View, + actions, div, prelude::*, FocusHandle, Focusable, KeyBinding, Div, Render, Stateful, View, WindowContext, }; use theme2::ActiveTheme; @@ -27,7 +27,7 @@ impl FocusStory { } impl Render for FocusStory { - type Element = Focusable>>; + type Element = Focusable>>; fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { let theme = cx.theme(); diff --git a/crates/storybook2/src/stories/kitchen_sink.rs b/crates/storybook2/src/stories/kitchen_sink.rs index 0a165eff7496fb6a536a7d69a8f813080bb294b1..507aa8db2d5db7f0d24fd33aaacc34f04a700170 100644 --- a/crates/storybook2/src/stories/kitchen_sink.rs +++ b/crates/storybook2/src/stories/kitchen_sink.rs @@ -1,5 +1,5 @@ use crate::{story::Story, story_selector::ComponentStory}; -use gpui::{prelude::*, Node, Render, Stateful, View}; +use gpui::{prelude::*, Div, Render, Stateful, View}; use strum::IntoEnumIterator; use ui::prelude::*; @@ -12,7 +12,7 @@ impl KitchenSinkStory { } impl Render for KitchenSinkStory { - type Element = Stateful>; + type Element = Stateful>; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let component_stories = ComponentStory::iter() diff --git a/crates/storybook2/src/stories/picker.rs b/crates/storybook2/src/stories/picker.rs index bba8ae9990c36ea6c6d3d312f77bacaf9a05f059..eb4a3b88ea5759db2fe007390923c6a7f5184f59 100644 --- a/crates/storybook2/src/stories/picker.rs +++ b/crates/storybook2/src/stories/picker.rs @@ -1,5 +1,5 @@ use fuzzy::StringMatchCandidate; -use gpui::{div, prelude::*, KeyBinding, Node, Render, Styled, Task, View, WindowContext}; +use gpui::{div, prelude::*, KeyBinding, Div, Render, Styled, Task, View, WindowContext}; use picker::{Picker, PickerDelegate}; use std::sync::Arc; use theme2::ActiveTheme; @@ -34,7 +34,7 @@ impl Delegate { } impl PickerDelegate for Delegate { - type ListItem = Node>; + type ListItem = Div>; fn match_count(&self) -> usize { self.candidates.len() @@ -203,7 +203,7 @@ impl PickerStory { } impl Render for PickerStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { div() diff --git a/crates/storybook2/src/stories/scroll.rs b/crates/storybook2/src/stories/scroll.rs index c5675b5681ca1af1208be4fbaa67a8d44fd6c561..c5549e56d0e21c1c4fd6cd9c682cc60b209651a2 100644 --- a/crates/storybook2/src/stories/scroll.rs +++ b/crates/storybook2/src/stories/scroll.rs @@ -1,5 +1,5 @@ use gpui::{ - div, prelude::*, px, Node, Render, SharedString, Stateful, Styled, View, WindowContext, + div, prelude::*, px, Div, Render, SharedString, Stateful, Styled, View, WindowContext, }; use theme2::ActiveTheme; @@ -12,7 +12,7 @@ impl ScrollStory { } impl Render for ScrollStory { - type Element = Stateful>; + type Element = Stateful>; fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { let theme = cx.theme(); diff --git a/crates/storybook2/src/stories/text.rs b/crates/storybook2/src/stories/text.rs index 86ab2fce9998cdd4edbbb2fb07800b0e2a3eea6b..6fc76ab9073c770dba90626611c83313c7b6445a 100644 --- a/crates/storybook2/src/stories/text.rs +++ b/crates/storybook2/src/stories/text.rs @@ -1,4 +1,4 @@ -use gpui::{div, white, Node, ParentComponent, Render, Styled, View, VisualContext, WindowContext}; +use gpui::{div, white, Div, ParentComponent, Render, Styled, View, VisualContext, WindowContext}; pub struct TextStory; @@ -9,7 +9,7 @@ impl TextStory { } impl Render for TextStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { div().size_full().bg(white()).child(concat!( diff --git a/crates/storybook2/src/stories/z_index.rs b/crates/storybook2/src/stories/z_index.rs index 259685b9fa7f402a3b2eec3b8b9c1e4d8e165cf2..46ec0f4a3511ea2b3a3cc7999e203a62d35a01d6 100644 --- a/crates/storybook2/src/stories/z_index.rs +++ b/crates/storybook2/src/stories/z_index.rs @@ -1,4 +1,4 @@ -use gpui::{px, rgb, Hsla, Node, Render}; +use gpui::{px, rgb, Div, Hsla, Render}; use ui::prelude::*; use crate::story::Story; @@ -8,7 +8,7 @@ use crate::story::Story; pub struct ZIndexStory; impl Render for ZIndexStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) @@ -77,7 +77,7 @@ trait Styles: Styled + Sized { } } -impl Styles for Node {} +impl Styles for Div {} #[derive(Component)] struct ZIndexExample { diff --git a/crates/storybook2/src/storybook2.rs b/crates/storybook2/src/storybook2.rs index f20aa5909554761b47d40d8a4a11115dbd8f11c8..f0ba124162d546bcdbdc1fce12e986364f950dad 100644 --- a/crates/storybook2/src/storybook2.rs +++ b/crates/storybook2/src/storybook2.rs @@ -9,7 +9,7 @@ use std::sync::Arc; use clap::Parser; use gpui::{ - div, px, size, AnyView, AppContext, Bounds, Node, Render, ViewContext, VisualContext, + div, px, size, AnyView, AppContext, Bounds, Div, Render, ViewContext, VisualContext, WindowBounds, WindowOptions, }; use log::LevelFilter; @@ -107,7 +107,7 @@ impl StoryWrapper { } impl Render for StoryWrapper { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { div() diff --git a/crates/theme2/src/players.rs b/crates/theme2/src/players.rs index 32b3504b65f9004e1d6555170cb4bfdd5a406506..28489285a7602e99ff21c847269b9f8669aefc5a 100644 --- a/crates/theme2/src/players.rs +++ b/crates/theme2/src/players.rs @@ -40,12 +40,12 @@ pub use stories::*; mod stories { use super::*; use crate::{ActiveTheme, Story}; - use gpui::{div, img, px, Node, ParentComponent, Render, Styled, ViewContext}; + use gpui::{div, img, px, Div, ParentComponent, Render, Styled, ViewContext}; pub struct PlayerStory; impl Render for PlayerStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx).child( diff --git a/crates/theme2/src/story.rs b/crates/theme2/src/story.rs index 00cb20df9268c36d1235a7c3c4b88ba796ba133a..4296d4f99c4e2f4dfad0cbf1b60eef90efa3d0d0 100644 --- a/crates/theme2/src/story.rs +++ b/crates/theme2/src/story.rs @@ -1,11 +1,11 @@ -use gpui::{div, Component, Node, ParentComponent, Styled, ViewContext}; +use gpui::{div, Component, Div, ParentComponent, Styled, ViewContext}; use crate::ActiveTheme; pub struct Story {} impl Story { - pub fn container(cx: &mut ViewContext) -> Node { + pub fn container(cx: &mut ViewContext) -> Div { div() .size_full() .flex() diff --git a/crates/ui2/src/components/avatar.rs b/crates/ui2/src/components/avatar.rs index d270f2fd323c69ee3e9fffbee12ae9117c1f6473..d083d8fd463e144e236e5c625caa92f237f3fce4 100644 --- a/crates/ui2/src/components/avatar.rs +++ b/crates/ui2/src/components/avatar.rs @@ -44,12 +44,12 @@ pub use stories::*; mod stories { use super::*; use crate::Story; - use gpui::{Node, Render}; + use gpui::{Div, Render}; pub struct AvatarStory; impl Render for AvatarStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/components/button.rs b/crates/ui2/src/components/button.rs index eeb8ddb90687766f67277ff01f340b91b25a91a7..1c36eab44f1972bdb65066a849cf85642db57706 100644 --- a/crates/ui2/src/components/button.rs +++ b/crates/ui2/src/components/button.rs @@ -236,13 +236,13 @@ pub use stories::*; mod stories { use super::*; use crate::{h_stack, v_stack, LabelColor, Story}; - use gpui::{rems, Node, Render}; + use gpui::{rems, Div, Render}; use strum::IntoEnumIterator; pub struct ButtonStory; impl Render for ButtonStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let states = InteractionState::iter(); diff --git a/crates/ui2/src/components/checkbox.rs b/crates/ui2/src/components/checkbox.rs index c2a0cfdc2f539f60846739793260e35c71156e69..971da8338b5d866b73baad53fa199dfc4cb90598 100644 --- a/crates/ui2/src/components/checkbox.rs +++ b/crates/ui2/src/components/checkbox.rs @@ -171,12 +171,12 @@ pub use stories::*; mod stories { use super::*; use crate::{h_stack, Story}; - use gpui::{Node, Render}; + use gpui::{Div, Render}; pub struct CheckboxStory; impl Render for CheckboxStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/components/context_menu.rs b/crates/ui2/src/components/context_menu.rs index a33f10c296f92e3ebd25123e0b1a3a8b160de816..117be127798bd56f9d0c3963f8119832aa170550 100644 --- a/crates/ui2/src/components/context_menu.rs +++ b/crates/ui2/src/components/context_menu.rs @@ -65,12 +65,12 @@ pub use stories::*; mod stories { use super::*; use crate::story::Story; - use gpui::{Node, Render}; + use gpui::{Div, Render}; pub struct ContextMenuStory; impl Render for ContextMenuStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/components/details.rs b/crates/ui2/src/components/details.rs index 44c433179a94b291145dcb363f4cc4d69c869180..f138290f17fd3b6fc325f0972f62f6aa6f996ed1 100644 --- a/crates/ui2/src/components/details.rs +++ b/crates/ui2/src/components/details.rs @@ -47,12 +47,12 @@ pub use stories::*; mod stories { use super::*; use crate::{Button, Story}; - use gpui::{Node, Render}; + use gpui::{Div, Render}; pub struct DetailsStory; impl Render for DetailsStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/components/elevated_surface.rs b/crates/ui2/src/components/elevated_surface.rs index 3a1699a64a9678687718eb14cd856b26370904f5..fff232d7ed6f19739f80f9a1913e4c1d0fa69628 100644 --- a/crates/ui2/src/components/elevated_surface.rs +++ b/crates/ui2/src/components/elevated_surface.rs @@ -1,11 +1,11 @@ -use gpui::Node; +use gpui::Div; use crate::{prelude::*, v_stack}; /// Create an elevated surface. /// /// Must be used inside of a relative parent element -pub fn elevated_surface(level: ElevationIndex, cx: &mut ViewContext) -> Node { +pub fn elevated_surface(level: ElevationIndex, cx: &mut ViewContext) -> Div { let colors = cx.theme().colors(); // let shadow = BoxShadow { @@ -23,6 +23,6 @@ pub fn elevated_surface(level: ElevationIndex, cx: &mut ViewContext< .shadow(level.shadow()) } -pub fn modal(cx: &mut ViewContext) -> Node { +pub fn modal(cx: &mut ViewContext) -> Div { elevated_surface(ElevationIndex::ModalSurface, cx) } diff --git a/crates/ui2/src/components/facepile.rs b/crates/ui2/src/components/facepile.rs index 43fd233458fbb03d3faff2415e1ffeb48aef23f2..efac4925f80a579bfc9deeca273fbf64aad10c5f 100644 --- a/crates/ui2/src/components/facepile.rs +++ b/crates/ui2/src/components/facepile.rs @@ -33,12 +33,12 @@ pub use stories::*; mod stories { use super::*; use crate::{static_players, Story}; - use gpui::{Node, Render}; + use gpui::{Div, Render}; pub struct FacepileStory; impl Render for FacepileStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let players = static_players(); diff --git a/crates/ui2/src/components/icon.rs b/crates/ui2/src/components/icon.rs index ce980a879bf26db0d1ed9da32656746d237b79a4..907f3f91871b5c614944e821244d10228d2853bb 100644 --- a/crates/ui2/src/components/icon.rs +++ b/crates/ui2/src/components/icon.rs @@ -204,7 +204,7 @@ pub use stories::*; #[cfg(feature = "stories")] mod stories { - use gpui::{Node, Render}; + use gpui::{Div, Render}; use strum::IntoEnumIterator; use crate::Story; @@ -214,7 +214,7 @@ mod stories { pub struct IconStory; impl Render for IconStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let icons = Icon::iter(); diff --git a/crates/ui2/src/components/input.rs b/crates/ui2/src/components/input.rs index d873d6a5cbf86f343febb820e817985ee98dbe3f..4db9222a0ec5bd70090afb0f41728d49c7d3e382 100644 --- a/crates/ui2/src/components/input.rs +++ b/crates/ui2/src/components/input.rs @@ -110,12 +110,12 @@ pub use stories::*; mod stories { use super::*; use crate::Story; - use gpui::{Node, Render}; + use gpui::{Div, Render}; pub struct InputStory; impl Render for InputStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/components/keybinding.rs b/crates/ui2/src/components/keybinding.rs index 86e876d24502624438f683abe242eac7d25144cf..bd02e694edd45561373f39e2673d7e290dcf30cb 100644 --- a/crates/ui2/src/components/keybinding.rs +++ b/crates/ui2/src/components/keybinding.rs @@ -158,13 +158,13 @@ pub use stories::*; mod stories { use super::*; use crate::Story; - use gpui::{Node, Render}; + use gpui::{Div, Render}; use itertools::Itertools; pub struct KeybindingStory; impl Render for KeybindingStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let all_modifier_permutations = ModifierKey::iter().permutations(2); diff --git a/crates/ui2/src/components/label.rs b/crates/ui2/src/components/label.rs index 497ebe677312703d49ed32ed2339d12a191ab938..827ba87918a0cd4dd3f3255c8b7852436ea06a79 100644 --- a/crates/ui2/src/components/label.rs +++ b/crates/ui2/src/components/label.rs @@ -196,12 +196,12 @@ pub use stories::*; mod stories { use super::*; use crate::Story; - use gpui::{Node, Render}; + use gpui::{Div, Render}; pub struct LabelStory; impl Render for LabelStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/components/palette.rs b/crates/ui2/src/components/palette.rs index 4a753215f0940c063e6737ded9d9c2bcf854eff3..249e577ff1048efd305b659a535ec04d6ebcc93d 100644 --- a/crates/ui2/src/components/palette.rs +++ b/crates/ui2/src/components/palette.rs @@ -159,7 +159,7 @@ pub use stories::*; #[cfg(feature = "stories")] mod stories { - use gpui::{Node, Render}; + use gpui::{Div, Render}; use crate::{ModifierKeys, Story}; @@ -168,7 +168,7 @@ mod stories { pub struct PaletteStory; impl Render for PaletteStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { { diff --git a/crates/ui2/src/components/panel.rs b/crates/ui2/src/components/panel.rs index 2b317b0bc1d02773d6bcc0be20241e464ebb3299..e16f203599c49519ebfb546cd2a61e06828db672 100644 --- a/crates/ui2/src/components/panel.rs +++ b/crates/ui2/src/components/panel.rs @@ -126,12 +126,12 @@ pub use stories::*; mod stories { use super::*; use crate::{Label, Story}; - use gpui::{InteractiveComponent, Node, Render}; + use gpui::{InteractiveComponent, Div, Render}; pub struct PanelStory; impl Render for PanelStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/components/stack.rs b/crates/ui2/src/components/stack.rs index d705863ad40a4cd9368f5e07be030ffda53be593..d3d7a75aa76b8765a97b3dcc0c92c498cbbb7d24 100644 --- a/crates/ui2/src/components/stack.rs +++ b/crates/ui2/src/components/stack.rs @@ -1,17 +1,17 @@ -use gpui::{div, Node}; +use gpui::{div, Div}; use crate::StyledExt; /// Horizontally stacks elements. /// /// Sets `flex()`, `flex_row()`, `items_center()` -pub fn h_stack() -> Node { +pub fn h_stack() -> Div { div().h_flex() } /// Vertically stacks elements. /// /// Sets `flex()`, `flex_col()` -pub fn v_stack() -> Node { +pub fn v_stack() -> Div { div().v_flex() } diff --git a/crates/ui2/src/components/tab.rs b/crates/ui2/src/components/tab.rs index fe993555b91094e289181bdc3b1976153dc88e49..268098a579f8c7f8a9faac77498b28f13bac11a9 100644 --- a/crates/ui2/src/components/tab.rs +++ b/crates/ui2/src/components/tab.rs @@ -1,6 +1,6 @@ use crate::prelude::*; use crate::{Icon, IconColor, IconElement, Label, LabelColor}; -use gpui::{prelude::*, red, ElementId, Node, Render, View}; +use gpui::{prelude::*, red, Div, ElementId, Render, View}; #[derive(Component, Clone)] pub struct Tab { @@ -21,7 +21,7 @@ struct TabDragState { } impl Render for TabDragState { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { div().w_8().h_4().bg(red()) @@ -178,7 +178,7 @@ mod stories { pub struct TabStory; impl Render for TabStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let git_statuses = GitStatus::iter(); diff --git a/crates/ui2/src/components/toast.rs b/crates/ui2/src/components/toast.rs index 2f07bbc3e09d939d3c94b0d9c41f8a1361ea4b86..0fcfe6038b97e3b6ba8cc3f88db8cd12f8b2bfc0 100644 --- a/crates/ui2/src/components/toast.rs +++ b/crates/ui2/src/components/toast.rs @@ -69,7 +69,7 @@ pub use stories::*; #[cfg(feature = "stories")] mod stories { - use gpui::{Node, Render}; + use gpui::{Div, Render}; use crate::{Label, Story}; @@ -78,7 +78,7 @@ mod stories { pub struct ToastStory; impl Render for ToastStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/components/tooltip.rs b/crates/ui2/src/components/tooltip.rs index 6c5fa7bc2bb2ec85044fcc8a6be3d02ee7454611..80c6863f6815cd97aa63b81f890ed337000ea3f8 100644 --- a/crates/ui2/src/components/tooltip.rs +++ b/crates/ui2/src/components/tooltip.rs @@ -1,4 +1,4 @@ -use gpui::{div, Node, ParentComponent, Render, SharedString, Styled, ViewContext}; +use gpui::{div, Div, ParentComponent, Render, SharedString, Styled, ViewContext}; use theme2::ActiveTheme; #[derive(Clone, Debug)] @@ -13,7 +13,7 @@ impl TextTooltip { } impl Render for TextTooltip { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let theme = cx.theme(); diff --git a/crates/ui2/src/story.rs b/crates/ui2/src/story.rs index cf5737a2454eff52bc64cc76338a64fbee09350a..94e38267f4c5b160365317c4e597a76748c05d6f 100644 --- a/crates/ui2/src/story.rs +++ b/crates/ui2/src/story.rs @@ -1,11 +1,11 @@ -use gpui::Node; +use gpui::Div; use crate::prelude::*; pub struct Story {} impl Story { - pub fn container(cx: &mut ViewContext) -> Node { + pub fn container(cx: &mut ViewContext) -> Div { div() .size_full() .flex() diff --git a/crates/ui2/src/to_extract/assistant_panel.rs b/crates/ui2/src/to_extract/assistant_panel.rs index 59d90591220118d15d4e67d5eb2ff35001d24748..f111dad83024f539d033701bfab66a7c10dbb446 100644 --- a/crates/ui2/src/to_extract/assistant_panel.rs +++ b/crates/ui2/src/to_extract/assistant_panel.rs @@ -77,11 +77,11 @@ pub use stories::*; mod stories { use super::*; use crate::Story; - use gpui::{Node, Render}; + use gpui::{Div, Render}; pub struct AssistantPanelStory; impl Render for AssistantPanelStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/breadcrumb.rs b/crates/ui2/src/to_extract/breadcrumb.rs index c113c641684b2f8289a55046e76fa5664f7b03f1..fd43a5b3bf58556ca003e00114b1f060f82ba453 100644 --- a/crates/ui2/src/to_extract/breadcrumb.rs +++ b/crates/ui2/src/to_extract/breadcrumb.rs @@ -1,5 +1,5 @@ use crate::{h_stack, prelude::*, HighlightedText}; -use gpui::{prelude::*, Node}; +use gpui::{prelude::*, Div}; use std::path::PathBuf; #[derive(Clone)] @@ -16,7 +16,7 @@ impl Breadcrumb { Self { path, symbols } } - fn render_separator(&self, cx: &WindowContext) -> Node { + fn render_separator(&self, cx: &WindowContext) -> Div { div() .child(" › ") .text_color(cx.theme().colors().text_muted) @@ -77,7 +77,7 @@ mod stories { pub struct BreadcrumbStory; impl Render for BreadcrumbStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/buffer.rs b/crates/ui2/src/to_extract/buffer.rs index b04f2221d3158d658600f0650ab820abfd65a26b..aa4bebc9d5d5cdaa23f1429af7d64b71751c99c0 100644 --- a/crates/ui2/src/to_extract/buffer.rs +++ b/crates/ui2/src/to_extract/buffer.rs @@ -235,12 +235,12 @@ mod stories { empty_buffer_example, hello_world_rust_buffer_example, hello_world_rust_buffer_with_status_example, Story, }; - use gpui::{rems, Node, Render}; + use gpui::{rems, Div, Render}; pub struct BufferStory; impl Render for BufferStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/buffer_search.rs b/crates/ui2/src/to_extract/buffer_search.rs index 0e6fffa5a705ddc157a9f78e004c9c0eb6aa85be..9993cd361294067112c6b629ef9f5e2698e4e3cb 100644 --- a/crates/ui2/src/to_extract/buffer_search.rs +++ b/crates/ui2/src/to_extract/buffer_search.rs @@ -1,4 +1,4 @@ -use gpui::{Node, Render, View, VisualContext}; +use gpui::{Div, Render, View, VisualContext}; use crate::prelude::*; use crate::{h_stack, Icon, IconButton, IconColor, Input}; @@ -27,9 +27,9 @@ impl BufferSearch { } impl Render for BufferSearch { - type Element = Node; + type Element = Div; - fn render(&mut self, cx: &mut ViewContext) -> Node { + fn render(&mut self, cx: &mut ViewContext) -> Div { h_stack() .bg(cx.theme().colors().toolbar_background) .p_2() diff --git a/crates/ui2/src/to_extract/chat_panel.rs b/crates/ui2/src/to_extract/chat_panel.rs index 13f35468ff9a141f2474558712b59f04e8c92090..fcc8e6a46e8b7d17e2b2496180da0ce11b2fe32c 100644 --- a/crates/ui2/src/to_extract/chat_panel.rs +++ b/crates/ui2/src/to_extract/chat_panel.rs @@ -107,7 +107,7 @@ pub use stories::*; #[cfg(feature = "stories")] mod stories { use chrono::DateTime; - use gpui::{Node, Render}; + use gpui::{Div, Render}; use crate::{Panel, Story}; @@ -116,7 +116,7 @@ mod stories { pub struct ChatPanelStory; impl Render for ChatPanelStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/collab_panel.rs b/crates/ui2/src/to_extract/collab_panel.rs index d2ac353e0530577ca85059e90013278486cbf37b..256a648c0d42e39cfaccc9c4115d0ff431df8c85 100644 --- a/crates/ui2/src/to_extract/collab_panel.rs +++ b/crates/ui2/src/to_extract/collab_panel.rs @@ -93,12 +93,12 @@ pub use stories::*; mod stories { use super::*; use crate::Story; - use gpui::{Node, Render}; + use gpui::{Div, Render}; pub struct CollabPanelStory; impl Render for CollabPanelStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/command_palette.rs b/crates/ui2/src/to_extract/command_palette.rs index 8a9c61490cd525d91f70eef84ebaa8ffd5583baf..8a9461c796d053e45fb768f3db4c14f1364f0d27 100644 --- a/crates/ui2/src/to_extract/command_palette.rs +++ b/crates/ui2/src/to_extract/command_palette.rs @@ -27,7 +27,7 @@ pub use stories::*; #[cfg(feature = "stories")] mod stories { - use gpui::{Node, Render}; + use gpui::{Div, Render}; use crate::Story; @@ -36,7 +36,7 @@ mod stories { pub struct CommandPaletteStory; impl Render for CommandPaletteStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/copilot.rs b/crates/ui2/src/to_extract/copilot.rs index 2a2c2c4a2707be09567df13d6611d8f13c57d37a..8750ab3c51a28cd1f91f67f09c4cd7d419a7b98b 100644 --- a/crates/ui2/src/to_extract/copilot.rs +++ b/crates/ui2/src/to_extract/copilot.rs @@ -25,7 +25,7 @@ pub use stories::*; #[cfg(feature = "stories")] mod stories { - use gpui::{Node, Render}; + use gpui::{Div, Render}; use crate::Story; @@ -34,7 +34,7 @@ mod stories { pub struct CopilotModalStory; impl Render for CopilotModalStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/editor_pane.rs b/crates/ui2/src/to_extract/editor_pane.rs index 4546c24794c961e79dd21b0fd620bef6df94e435..fd21e81242c34237f9d16fb63f66312ebc678fbf 100644 --- a/crates/ui2/src/to_extract/editor_pane.rs +++ b/crates/ui2/src/to_extract/editor_pane.rs @@ -1,6 +1,6 @@ use std::path::PathBuf; -use gpui::{Node, Render, View, VisualContext}; +use gpui::{Div, Render, View, VisualContext}; use crate::prelude::*; use crate::{ @@ -48,9 +48,9 @@ impl EditorPane { } impl Render for EditorPane { - type Element = Node; + type Element = Div; - fn render(&mut self, cx: &mut ViewContext) -> Node { + fn render(&mut self, cx: &mut ViewContext) -> Div { v_stack() .w_full() .h_full() diff --git a/crates/ui2/src/to_extract/language_selector.rs b/crates/ui2/src/to_extract/language_selector.rs index 46a10d5c88c923c19380a30647a17b7e56b427dd..694ca78e9c92353a7097f33d7ec133278b063bb0 100644 --- a/crates/ui2/src/to_extract/language_selector.rs +++ b/crates/ui2/src/to_extract/language_selector.rs @@ -40,12 +40,12 @@ pub use stories::*; mod stories { use super::*; use crate::Story; - use gpui::{Node, Render}; + use gpui::{Div, Render}; pub struct LanguageSelectorStory; impl Render for LanguageSelectorStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/multi_buffer.rs b/crates/ui2/src/to_extract/multi_buffer.rs index 0649bf12907aa51647a95e600304381abcf536fb..78a22d51d078bc6293e849f8898b53ee2c363109 100644 --- a/crates/ui2/src/to_extract/multi_buffer.rs +++ b/crates/ui2/src/to_extract/multi_buffer.rs @@ -40,12 +40,12 @@ pub use stories::*; mod stories { use super::*; use crate::{hello_world_rust_buffer_example, Story}; - use gpui::{Node, Render}; + use gpui::{Div, Render}; pub struct MultiBufferStory; impl Render for MultiBufferStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/notifications_panel.rs b/crates/ui2/src/to_extract/notifications_panel.rs index 0a85a15f34cd8bc1ec0725acae22452895f99b9c..a7854107b1c4f838f90a5042b50f065122a538f5 100644 --- a/crates/ui2/src/to_extract/notifications_panel.rs +++ b/crates/ui2/src/to_extract/notifications_panel.rs @@ -352,12 +352,12 @@ pub use stories::*; mod stories { use super::*; use crate::{Panel, Story}; - use gpui::{Node, Render}; + use gpui::{Div, Render}; pub struct NotificationsPanelStory; impl Render for NotificationsPanelStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/project_panel.rs b/crates/ui2/src/to_extract/project_panel.rs index c55056a7a90f0b3881075c7cf5fdb5b6ecd4a538..018f9a4bf10154504df580a1c95e31fe0a4a1016 100644 --- a/crates/ui2/src/to_extract/project_panel.rs +++ b/crates/ui2/src/to_extract/project_panel.rs @@ -55,12 +55,12 @@ pub use stories::*; mod stories { use super::*; use crate::{Panel, Story}; - use gpui::{Node, Render}; + use gpui::{Div, Render}; pub struct ProjectPanelStory; impl Render for ProjectPanelStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/recent_projects.rs b/crates/ui2/src/to_extract/recent_projects.rs index 83b15a31288568da49ad183a885a62fa5353f5a9..3d4f551490a47ef5eab616ebf1e2b1f6f0a0a726 100644 --- a/crates/ui2/src/to_extract/recent_projects.rs +++ b/crates/ui2/src/to_extract/recent_projects.rs @@ -36,12 +36,12 @@ pub use stories::*; mod stories { use super::*; use crate::Story; - use gpui::{Node, Render}; + use gpui::{Div, Render}; pub struct RecentProjectsStory; impl Render for RecentProjectsStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/tab_bar.rs b/crates/ui2/src/to_extract/tab_bar.rs index e8de2e9e58e3c0a29b97aba559c989e23684061f..3b4b5cc2205ebd015ba40b050d058384897be1e4 100644 --- a/crates/ui2/src/to_extract/tab_bar.rs +++ b/crates/ui2/src/to_extract/tab_bar.rs @@ -100,12 +100,12 @@ pub use stories::*; mod stories { use super::*; use crate::Story; - use gpui::{Node, Render}; + use gpui::{Div, Render}; pub struct TabBarStory; impl Render for TabBarStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/terminal.rs b/crates/ui2/src/to_extract/terminal.rs index 5bcbca4fde4ea1fc9d9a6184d0e01e14705594e8..6c36f35152d8082a3da7fda855a5fc58084b3ae2 100644 --- a/crates/ui2/src/to_extract/terminal.rs +++ b/crates/ui2/src/to_extract/terminal.rs @@ -83,11 +83,11 @@ pub use stories::*; mod stories { use super::*; use crate::Story; - use gpui::{Node, Render}; + use gpui::{Div, Render}; pub struct TerminalStory; impl Render for TerminalStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/theme_selector.rs b/crates/ui2/src/to_extract/theme_selector.rs index 7dd169a2f7a6a72c45642f7be41254c7c5727cbe..7f911b50bfa8d9b6273126053a7e791e41754989 100644 --- a/crates/ui2/src/to_extract/theme_selector.rs +++ b/crates/ui2/src/to_extract/theme_selector.rs @@ -39,7 +39,7 @@ pub use stories::*; #[cfg(feature = "stories")] mod stories { - use gpui::{Node, Render}; + use gpui::{Div, Render}; use crate::Story; @@ -48,7 +48,7 @@ mod stories { pub struct ThemeSelectorStory; impl Render for ThemeSelectorStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/title_bar.rs b/crates/ui2/src/to_extract/title_bar.rs index d805992023779e05c4c82d055bc59310c1dc0537..87d7dd4146d051aa5c8e4b8ae6697f487bfb34fa 100644 --- a/crates/ui2/src/to_extract/title_bar.rs +++ b/crates/ui2/src/to_extract/title_bar.rs @@ -1,7 +1,7 @@ use std::sync::atomic::AtomicBool; use std::sync::Arc; -use gpui::{Node, Render, View, VisualContext}; +use gpui::{Div, Render, View, VisualContext}; use crate::prelude::*; use crate::settings::user_settings; @@ -86,9 +86,9 @@ impl TitleBar { } impl Render for TitleBar { - type Element = Node; + type Element = Div; - fn render(&mut self, cx: &mut ViewContext) -> Node { + fn render(&mut self, cx: &mut ViewContext) -> Div { let settings = user_settings(cx); // let has_focus = cx.window_is_active(); @@ -202,9 +202,9 @@ mod stories { } impl Render for TitleBarStory { - type Element = Node; + type Element = Div; - fn render(&mut self, cx: &mut ViewContext) -> Node { + fn render(&mut self, cx: &mut ViewContext) -> Div { Story::container(cx) .child(Story::title_for::<_, TitleBar>(cx)) .child(Story::label(cx, "Default")) diff --git a/crates/ui2/src/to_extract/toolbar.rs b/crates/ui2/src/to_extract/toolbar.rs index 1c1795437b5fabba09978af2524fce7ba2f9fa06..81918f34a790b1ec91aa4ac33cad210972b191cf 100644 --- a/crates/ui2/src/to_extract/toolbar.rs +++ b/crates/ui2/src/to_extract/toolbar.rs @@ -73,7 +73,7 @@ mod stories { use std::path::PathBuf; use std::str::FromStr; - use gpui::{Node, Render}; + use gpui::{Div, Render}; use crate::{Breadcrumb, HighlightedText, Icon, IconButton, Story, Symbol}; @@ -82,7 +82,7 @@ mod stories { pub struct ToolbarStory; impl Render for ToolbarStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/traffic_lights.rs b/crates/ui2/src/to_extract/traffic_lights.rs index 76898eb19a08f58f195c1efa38fd36c33f7e1cff..245ff377f2146579f5532123a456f2f1ae498cfc 100644 --- a/crates/ui2/src/to_extract/traffic_lights.rs +++ b/crates/ui2/src/to_extract/traffic_lights.rs @@ -77,7 +77,7 @@ pub use stories::*; #[cfg(feature = "stories")] mod stories { - use gpui::{Node, Render}; + use gpui::{Div, Render}; use crate::Story; @@ -86,7 +86,7 @@ mod stories { pub struct TrafficLightsStory; impl Render for TrafficLightsStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { Story::container(cx) diff --git a/crates/ui2/src/to_extract/workspace.rs b/crates/ui2/src/to_extract/workspace.rs index 2ab6b4b3efd2f0d803ff6713f0d3787ec64c9de6..d6de8a828807606a6d55086af724983ca1a93df0 100644 --- a/crates/ui2/src/to_extract/workspace.rs +++ b/crates/ui2/src/to_extract/workspace.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use chrono::DateTime; -use gpui::{px, relative, Node, Render, Size, View, VisualContext}; +use gpui::{px, relative, Div, Render, Size, View, VisualContext}; use settings2::Settings; use theme2::ThemeSettings; @@ -192,9 +192,9 @@ impl Workspace { } impl Render for Workspace { - type Element = Node; + type Element = Div; - fn render(&mut self, cx: &mut ViewContext) -> Node { + fn render(&mut self, cx: &mut ViewContext) -> Div { let root_group = PaneGroup::new_panes( vec![Pane::new( "pane-0", @@ -388,7 +388,7 @@ mod stories { } impl Render for WorkspaceStory { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { div().child(self.workspace.clone()) diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index 0e507c0f7c214c80e83119feb93e40d251a01624..7695cffa882df33ae4ca37efcbaf98823dc7d962 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -1,6 +1,6 @@ use crate::{status_bar::StatusItemView, Axis, Workspace}; use gpui::{ - div, Action, AnyView, AppContext, Entity, EntityId, EventEmitter, Node, ParentComponent, + div, Action, AnyView, AppContext, Entity, EntityId, EventEmitter, Div, ParentComponent, Render, Subscription, View, ViewContext, WeakView, WindowContext, }; use schemars::JsonSchema; @@ -419,7 +419,7 @@ impl Dock { } impl Render for Dock { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { todo!() @@ -621,7 +621,7 @@ impl PanelButtons { // } impl Render for PanelButtons { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { // todo!() @@ -647,7 +647,7 @@ impl StatusItemView for PanelButtons { #[cfg(any(test, feature = "test-support"))] pub mod test { use super::*; - use gpui::{div, Node, ViewContext, WindowContext}; + use gpui::{div, Div, ViewContext, WindowContext}; pub struct TestPanel { pub position: DockPosition, @@ -672,7 +672,7 @@ pub mod test { } impl Render for TestPanel { - type Element = Node; + type Element = Div; fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { div() diff --git a/crates/workspace2/src/modal_layer.rs b/crates/workspace2/src/modal_layer.rs index 6cc08d56a63ca776edda240a7ef611ea65f9a4ac..3ebb2749692ccb5401b5af26320e8f976a55c69f 100644 --- a/crates/workspace2/src/modal_layer.rs +++ b/crates/workspace2/src/modal_layer.rs @@ -1,5 +1,5 @@ use gpui::{ - div, prelude::*, px, AnyView, EventEmitter, FocusHandle, Node, Render, Subscription, View, + div, prelude::*, px, AnyView, EventEmitter, FocusHandle, Div, Render, Subscription, View, ViewContext, WindowContext, }; use ui::v_stack; @@ -76,7 +76,7 @@ impl ModalLayer { } impl Render for ModalLayer { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let Some(active_modal) = &self.active_modal else { diff --git a/crates/workspace2/src/notifications.rs b/crates/workspace2/src/notifications.rs index 8673645b1e5abd1349f6cf4b81ae14a654190d87..a17399af5754c249db7967417b2b8d73c06255b9 100644 --- a/crates/workspace2/src/notifications.rs +++ b/crates/workspace2/src/notifications.rs @@ -165,7 +165,7 @@ impl Workspace { pub mod simple_message_notification { use super::{Notification, NotificationEvent}; - use gpui::{AnyElement, AppContext, EventEmitter, Node, Render, TextStyle, ViewContext}; + use gpui::{AnyElement, AppContext, EventEmitter, Div, Render, TextStyle, ViewContext}; use serde::Deserialize; use std::{borrow::Cow, sync::Arc}; @@ -252,7 +252,7 @@ pub mod simple_message_notification { } impl Render for MessageNotification { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { todo!() diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index ff16ebdc6d7cb965483e77a8cd4bd10efad96c04..c4935599a60167b138194b0f3386d61e0f017763 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -8,7 +8,7 @@ use anyhow::Result; use collections::{HashMap, HashSet, VecDeque}; use gpui::{ actions, prelude::*, register_action, AppContext, AsyncWindowContext, Component, EntityId, - EventEmitter, FocusHandle, Model, Node, PromptLevel, Render, Task, View, ViewContext, + EventEmitter, FocusHandle, Model, Div, PromptLevel, Render, Task, View, ViewContext, VisualContext, WeakView, WindowContext, }; use parking_lot::Mutex; @@ -1901,7 +1901,7 @@ impl Pane { // } impl Render for Pane { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { v_stack() @@ -2926,7 +2926,7 @@ struct DraggedTab { } impl Render for DraggedTab { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { div().w_8().h_4().bg(gpui::red()) diff --git a/crates/workspace2/src/status_bar.rs b/crates/workspace2/src/status_bar.rs index 6ac524f8241e531726ead25db9d54a3dc03fdefd..18c6bbf0798eb0af6159ecf7914737b5fc291769 100644 --- a/crates/workspace2/src/status_bar.rs +++ b/crates/workspace2/src/status_bar.rs @@ -2,7 +2,7 @@ use std::any::TypeId; use crate::{ItemHandle, Pane}; use gpui::{ - div, AnyView, Component, Node, ParentComponent, Render, Styled, Subscription, View, + div, AnyView, Component, Div, ParentComponent, Render, Styled, Subscription, View, ViewContext, WindowContext, }; use theme2::ActiveTheme; @@ -34,7 +34,7 @@ pub struct StatusBar { } impl Render for StatusBar { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { div() diff --git a/crates/workspace2/src/toolbar.rs b/crates/workspace2/src/toolbar.rs index dfe661d5b01b937bf11a6932f9c1c50887f6f7a4..1d67da06b223155d076c39e53492ce370391aa06 100644 --- a/crates/workspace2/src/toolbar.rs +++ b/crates/workspace2/src/toolbar.rs @@ -1,6 +1,6 @@ use crate::ItemHandle; use gpui::{ - AnyView, Entity, EntityId, EventEmitter, Node, Render, View, ViewContext, WindowContext, + AnyView, Div, Entity, EntityId, EventEmitter, Render, View, ViewContext, WindowContext, }; pub enum ToolbarItemEvent { @@ -52,7 +52,7 @@ pub struct Toolbar { } impl Render for Toolbar { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { todo!() diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index df2b1d8f30e4ca95b7786b572efa24c21b7becb6..10399624b58f180a57441f724a7e27e2e8383997 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -38,7 +38,7 @@ use futures::{ use gpui::{ actions, div, point, prelude::*, rems, size, Action, AnyModel, AnyView, AnyWeakView, AppContext, AsyncAppContext, AsyncWindowContext, Bounds, Component, Entity, EntityId, - EventEmitter, FocusHandle, GlobalPixels, KeyContext, Model, ModelContext, Node, + EventEmitter, FocusHandle, GlobalPixels, KeyContext, Model, ModelContext, Div, ParentComponent, Point, Render, Size, Styled, Subscription, Task, View, ViewContext, WeakView, WindowBounds, WindowContext, WindowHandle, WindowOptions, }; @@ -529,7 +529,7 @@ pub enum Event { pub struct Workspace { weak_self: WeakView, focus_handle: FocusHandle, - workspace_actions: Vec) -> Node>>, + workspace_actions: Vec) -> Div>>, zoomed: Option, zoomed_position: Option, center: PaneGroup, @@ -3503,7 +3503,7 @@ impl Workspace { })); } - fn add_workspace_actions_listeners(&self, mut div: Node) -> Node { + fn add_workspace_actions_listeners(&self, mut div: Div) -> Div { for action in self.workspace_actions.iter() { div = (action)(div) } @@ -3728,7 +3728,7 @@ fn notify_if_database_failed(workspace: WindowHandle, cx: &mut AsyncA impl EventEmitter for Workspace {} impl Render for Workspace { - type Element = Node; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let mut context = KeyContext::default(); From 6abaacc457ceae2b521e26bc1e5de33964a72cfa Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 14 Nov 2023 01:58:10 -0700 Subject: [PATCH 18/23] Fix formatting --- crates/storybook2/src/stories/focus.rs | 2 +- crates/storybook2/src/stories/picker.rs | 2 +- crates/storybook2/src/stories/scroll.rs | 4 +--- crates/ui2/src/components/panel.rs | 2 +- crates/ui2/src/prelude.rs | 4 ++-- crates/workspace2/src/dock.rs | 4 ++-- crates/workspace2/src/modal_layer.rs | 2 +- crates/workspace2/src/notifications.rs | 2 +- crates/workspace2/src/pane.rs | 6 +++--- crates/workspace2/src/status_bar.rs | 4 ++-- crates/workspace2/src/workspace2.rs | 8 ++++---- 11 files changed, 19 insertions(+), 21 deletions(-) diff --git a/crates/storybook2/src/stories/focus.rs b/crates/storybook2/src/stories/focus.rs index ff9a4da876a021a79b7ccb9a69c89d604122182d..a8794afdb86053c93d06c73f82cf0af7125deeeb 100644 --- a/crates/storybook2/src/stories/focus.rs +++ b/crates/storybook2/src/stories/focus.rs @@ -1,5 +1,5 @@ use gpui::{ - actions, div, prelude::*, FocusHandle, Focusable, KeyBinding, Div, Render, Stateful, View, + actions, div, prelude::*, Div, FocusHandle, Focusable, KeyBinding, Render, Stateful, View, WindowContext, }; use theme2::ActiveTheme; diff --git a/crates/storybook2/src/stories/picker.rs b/crates/storybook2/src/stories/picker.rs index eb4a3b88ea5759db2fe007390923c6a7f5184f59..a3f9ef5eb82a018619c52f314c00d2578d4e9b7b 100644 --- a/crates/storybook2/src/stories/picker.rs +++ b/crates/storybook2/src/stories/picker.rs @@ -1,5 +1,5 @@ use fuzzy::StringMatchCandidate; -use gpui::{div, prelude::*, KeyBinding, Div, Render, Styled, Task, View, WindowContext}; +use gpui::{div, prelude::*, Div, KeyBinding, Render, Styled, Task, View, WindowContext}; use picker::{Picker, PickerDelegate}; use std::sync::Arc; use theme2::ActiveTheme; diff --git a/crates/storybook2/src/stories/scroll.rs b/crates/storybook2/src/stories/scroll.rs index c5549e56d0e21c1c4fd6cd9c682cc60b209651a2..f9530269d5cdcdd73de522263003c88bd2500290 100644 --- a/crates/storybook2/src/stories/scroll.rs +++ b/crates/storybook2/src/stories/scroll.rs @@ -1,6 +1,4 @@ -use gpui::{ - div, prelude::*, px, Div, Render, SharedString, Stateful, Styled, View, WindowContext, -}; +use gpui::{div, prelude::*, px, Div, Render, SharedString, Stateful, Styled, View, WindowContext}; use theme2::ActiveTheme; pub struct ScrollStory; diff --git a/crates/ui2/src/components/panel.rs b/crates/ui2/src/components/panel.rs index e16f203599c49519ebfb546cd2a61e06828db672..d9fc50dd923cc00084f257387efcbb1705efa9f1 100644 --- a/crates/ui2/src/components/panel.rs +++ b/crates/ui2/src/components/panel.rs @@ -126,7 +126,7 @@ pub use stories::*; mod stories { use super::*; use crate::{Label, Story}; - use gpui::{InteractiveComponent, Div, Render}; + use gpui::{Div, InteractiveComponent, Render}; pub struct PanelStory; diff --git a/crates/ui2/src/prelude.rs b/crates/ui2/src/prelude.rs index f37b6123e3fadfd4536061c682c833e5a0ec2a0d..09ce43d91239a34f50990ddcb945ec74d2ce98b7 100644 --- a/crates/ui2/src/prelude.rs +++ b/crates/ui2/src/prelude.rs @@ -1,8 +1,8 @@ use gpui::rems; use gpui::Rems; pub use gpui::{ - div, Component, Element, ElementId, InteractiveComponent, ParentComponent, SharedString, Styled, - ViewContext, WindowContext, + div, Component, Element, ElementId, InteractiveComponent, ParentComponent, SharedString, + Styled, ViewContext, WindowContext, }; pub use crate::elevation::*; diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index 7695cffa882df33ae4ca37efcbaf98823dc7d962..499fb0d673b3bb38bcb99c7d22c568e5337dab15 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -1,7 +1,7 @@ use crate::{status_bar::StatusItemView, Axis, Workspace}; use gpui::{ - div, Action, AnyView, AppContext, Entity, EntityId, EventEmitter, Div, ParentComponent, - Render, Subscription, View, ViewContext, WeakView, WindowContext, + div, Action, AnyView, AppContext, Div, Entity, EntityId, EventEmitter, ParentComponent, Render, + Subscription, View, ViewContext, WeakView, WindowContext, }; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; diff --git a/crates/workspace2/src/modal_layer.rs b/crates/workspace2/src/modal_layer.rs index 0703d0dc563205dd9ee97c3ea9ab484a624fd198..c9dddfdace6bb2bbfd8d70075cccd02c975ab930 100644 --- a/crates/workspace2/src/modal_layer.rs +++ b/crates/workspace2/src/modal_layer.rs @@ -1,5 +1,5 @@ use gpui::{ - div, prelude::*, px, AnyView, EventEmitter, FocusHandle, Div, Render, Subscription, View, + div, prelude::*, px, AnyView, Div, EventEmitter, FocusHandle, Render, Subscription, View, ViewContext, WindowContext, }; use ui::{h_stack, v_stack}; diff --git a/crates/workspace2/src/notifications.rs b/crates/workspace2/src/notifications.rs index a17399af5754c249db7967417b2b8d73c06255b9..7277cc6fc47b33bb93ada4d37c0a2a5c68550f57 100644 --- a/crates/workspace2/src/notifications.rs +++ b/crates/workspace2/src/notifications.rs @@ -165,7 +165,7 @@ impl Workspace { pub mod simple_message_notification { use super::{Notification, NotificationEvent}; - use gpui::{AnyElement, AppContext, EventEmitter, Div, Render, TextStyle, ViewContext}; + use gpui::{AnyElement, AppContext, Div, EventEmitter, Render, TextStyle, ViewContext}; use serde::Deserialize; use std::{borrow::Cow, sync::Arc}; diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index aeca6173428dbedfeedac4f3437d82ab11b6010e..de0784758394ecf0564e75218e18d2ae210c7de2 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -7,9 +7,9 @@ use crate::{ use anyhow::Result; use collections::{HashMap, HashSet, VecDeque}; use gpui::{ - actions, prelude::*, register_action, AppContext, AsyncWindowContext, Component, EntityId, - EventEmitter, FocusHandle, Model, Div, PromptLevel, Render, Task, View, ViewContext, - VisualContext, WeakView, WindowContext, + actions, prelude::*, register_action, AppContext, AsyncWindowContext, Component, Div, EntityId, + EventEmitter, FocusHandle, Model, PromptLevel, Render, Task, View, ViewContext, VisualContext, + WeakView, WindowContext, }; use parking_lot::Mutex; use project2::{Project, ProjectEntryId, ProjectPath}; diff --git a/crates/workspace2/src/status_bar.rs b/crates/workspace2/src/status_bar.rs index 18c6bbf0798eb0af6159ecf7914737b5fc291769..5dccac243f47c0ec169c3bec9436d7c0a998b22f 100644 --- a/crates/workspace2/src/status_bar.rs +++ b/crates/workspace2/src/status_bar.rs @@ -2,8 +2,8 @@ use std::any::TypeId; use crate::{ItemHandle, Pane}; use gpui::{ - div, AnyView, Component, Div, ParentComponent, Render, Styled, Subscription, View, - ViewContext, WindowContext, + div, AnyView, Component, Div, ParentComponent, Render, Styled, Subscription, View, ViewContext, + WindowContext, }; use theme2::ActiveTheme; use util::ResultExt; diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index b48e4aa27855dc0e20b132ca5a2fb08fad1af641..3e3312ac3a6c3e44192169d33d72df1842dc3a6a 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -37,10 +37,10 @@ use futures::{ }; use gpui::{ actions, div, point, prelude::*, rems, size, Action, AnyModel, AnyView, AnyWeakView, - AppContext, AsyncAppContext, AsyncWindowContext, Bounds, Component, Entity, EntityId, - EventEmitter, FocusHandle, GlobalPixels, KeyContext, Model, ModelContext, Div, - ParentComponent, Point, Render, Size, Styled, Subscription, Task, View, ViewContext, WeakView, - WindowBounds, WindowContext, WindowHandle, WindowOptions, + AppContext, AsyncAppContext, AsyncWindowContext, Bounds, Component, Div, Entity, EntityId, + EventEmitter, FocusHandle, GlobalPixels, KeyContext, Model, ModelContext, ParentComponent, + Point, Render, Size, Styled, Subscription, Task, View, ViewContext, WeakView, WindowBounds, + WindowContext, WindowHandle, WindowOptions, }; use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem}; use itertools::Itertools; From e08f1690b378d43dfd57df4152777a8a431dd1d2 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 14 Nov 2023 09:33:28 -0700 Subject: [PATCH 19/23] Remove commented field --- crates/gpui2/src/elements/div.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index aeda28256a82775fa54a7751b0768bb951fa7014..aa4ef9bd36eb8160868f5dcdc2520e3137cb00ef 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -716,7 +716,6 @@ pub struct Interactivity { pub focusable: bool, pub tracked_focus_handle: Option, pub focus_listeners: FocusListeners, - // pub scroll_offset: Point, pub group: Option, pub base_style: StyleRefinement, pub focus_style: StyleRefinement, From bb584cc7c4e52a2864fc1a0e00891872c011abbe Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 14 Nov 2023 11:00:52 -0700 Subject: [PATCH 20/23] WIP --- .../command_palette2/src/command_palette.rs | 2 + crates/editor2/src/element.rs | 114 +++++++++--------- crates/gpui2/src/elements/div.rs | 11 +- crates/gpui2/src/interactive.rs | 17 ++- crates/gpui2/src/keymap/matcher.rs | 1 + crates/gpui2/src/window.rs | 7 +- 6 files changed, 82 insertions(+), 70 deletions(-) diff --git a/crates/command_palette2/src/command_palette.rs b/crates/command_palette2/src/command_palette.rs index 435a6446693e590f2af9c678df445c0f53b18428..5d428fba8e97ac306d2fe7ff54dea6e1ac0fdd37 100644 --- a/crates/command_palette2/src/command_palette.rs +++ b/crates/command_palette2/src/command_palette.rs @@ -32,7 +32,9 @@ pub struct CommandPalette { impl CommandPalette { fn register(workspace: &mut Workspace, _: &mut ViewContext) { + dbg!("registering command palette toggle"); workspace.register_action(|workspace, _: &Toggle, cx| { + dbg!("got cmd-shift-p"); let Some(previous_focus_handle) = cx.focused() else { return; }; diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index dd834b4cd89998211b7290b98db8d5323fe55878..3efd399a518875de852df7c55d14f099ecdd6d61 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -2446,7 +2446,7 @@ impl Element for EditorElement { type ElementState = (); fn element_id(&self) -> Option { - None + None // todo! can we change the element trait to return an id here from the view context? } fn initialize( @@ -2456,6 +2456,41 @@ impl Element for EditorElement { cx: &mut gpui::ViewContext, ) -> Self::ElementState { editor.style = Some(self.style.clone()); // Long-term, we'd like to eliminate this. + } + + fn layout( + &mut self, + editor: &mut Editor, + element_state: &mut Self::ElementState, + cx: &mut gpui::ViewContext, + ) -> gpui::LayoutId { + let rem_size = cx.rem_size(); + let mut style = Style::default(); + style.size.width = relative(1.).into(); + style.size.height = match editor.mode { + EditorMode::SingleLine => self.style.text.line_height_in_pixels(cx.rem_size()).into(), + EditorMode::AutoHeight { .. } => todo!(), + EditorMode::Full => relative(1.).into(), + }; + cx.request_layout(&style, None) + } + + fn paint( + &mut self, + bounds: Bounds, + editor: &mut Editor, + element_state: &mut Self::ElementState, + cx: &mut gpui::ViewContext, + ) { + let mut layout = self.compute_layout(editor, cx, bounds); + let gutter_bounds = Bounds { + origin: bounds.origin, + size: layout.gutter_size, + }; + let text_bounds = Bounds { + origin: gutter_bounds.upper_right(), + size: layout.text_size, + }; let dispatch_context = editor.dispatch_context(cx); cx.with_element_id(Some(cx.view().entity_id()), |cx| { @@ -2621,63 +2656,28 @@ impl Element for EditorElement { register_action(cx, Editor::context_menu_prev); register_action(cx, Editor::context_menu_next); register_action(cx, Editor::context_menu_last); - }, - ) - }); - } - - fn layout( - &mut self, - editor: &mut Editor, - element_state: &mut Self::ElementState, - cx: &mut gpui::ViewContext, - ) -> gpui::LayoutId { - let rem_size = cx.rem_size(); - let mut style = Style::default(); - style.size.width = relative(1.).into(); - style.size.height = match editor.mode { - EditorMode::SingleLine => self.style.text.line_height_in_pixels(cx.rem_size()).into(), - EditorMode::AutoHeight { .. } => todo!(), - EditorMode::Full => relative(1.).into(), - }; - cx.request_layout(&style, None) - } - fn paint( - &mut self, - bounds: Bounds, - editor: &mut Editor, - element_state: &mut Self::ElementState, - cx: &mut gpui::ViewContext, - ) { - let mut layout = self.compute_layout(editor, cx, bounds); - let gutter_bounds = Bounds { - origin: bounds.origin, - size: layout.gutter_size, - }; - let text_bounds = Bounds { - origin: gutter_bounds.upper_right(), - size: layout.text_size, - }; - - // We call with_z_index to establish a new stacking context. - cx.with_z_index(0, |cx| { - cx.with_content_mask(Some(ContentMask { bounds }), |cx| { - self.paint_mouse_listeners( - bounds, - gutter_bounds, - text_bounds, - &layout.position_map, - cx, - ); - self.paint_background(gutter_bounds, text_bounds, &layout, cx); - if layout.gutter_size.width > Pixels::ZERO { - self.paint_gutter(gutter_bounds, &mut layout, editor, cx); - } - self.paint_text(text_bounds, &mut layout, editor, cx); - let input_handler = ElementInputHandler::new(bounds, cx); - cx.handle_input(&editor.focus_handle, input_handler); - }); + // We call with_z_index to establish a new stacking context. + cx.with_z_index(0, |cx| { + cx.with_content_mask(Some(ContentMask { bounds }), |cx| { + self.paint_mouse_listeners( + bounds, + gutter_bounds, + text_bounds, + &layout.position_map, + cx, + ); + self.paint_background(gutter_bounds, text_bounds, &layout, cx); + if layout.gutter_size.width > Pixels::ZERO { + self.paint_gutter(gutter_bounds, &mut layout, editor, cx); + } + self.paint_text(text_bounds, &mut layout, editor, cx); + let input_handler = ElementInputHandler::new(bounds, cx); + cx.handle_input(&editor.focus_handle, input_handler); + }); + }); + }, + ); }); } } diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index aa4ef9bd36eb8160868f5dcdc2520e3137cb00ef..94f94241b219b74ac38c3322dfbccf63f6a77443 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -612,6 +612,7 @@ impl Element for Div { let interactive_state = self .interactivity .initialize(element_state.map(|s| s.interactive_state), cx); + for child in &mut self.children { child.initialize(view_state, cx); } @@ -763,6 +764,7 @@ where .unwrap_or_else(|| cx.focus_handle()) }); } + element_state } @@ -773,11 +775,7 @@ where f: impl FnOnce(Style, &mut ViewContext) -> LayoutId, ) -> LayoutId { let style = self.compute_style(None, element_state, cx); - cx.with_key_dispatch( - self.key_context.clone(), - self.tracked_focus_handle.clone(), - |_, cx| f(style, cx), - ) + f(style, cx) } pub fn paint( @@ -1078,6 +1076,9 @@ where }) } + if !self.key_context.is_empty() { + dbg!(&self.key_context, self.action_listeners.len()); + } for (action_type, listener) in self.action_listeners.drain(..) { cx.on_action(action_type, listener) } diff --git a/crates/gpui2/src/interactive.rs b/crates/gpui2/src/interactive.rs index 1896957ac80e799e1b72a8957ae56ac36dbabf1e..013ed2ea482a49cdf26f2411b09d8398d01dc506 100644 --- a/crates/gpui2/src/interactive.rs +++ b/crates/gpui2/src/interactive.rs @@ -286,8 +286,8 @@ pub struct FocusEvent { #[cfg(test)] mod test { use crate::{ - self as gpui, div, Div, FocusHandle, InteractiveComponent, KeyBinding, Keystroke, - ParentComponent, Render, Stateful, TestAppContext, VisualContext, + self as gpui, div, Component, Div, FocusHandle, InteractiveComponent, KeyBinding, + Keystroke, ParentComponent, Render, Stateful, TestAppContext, ViewContext, VisualContext, }; struct TestView { @@ -304,10 +304,15 @@ mod test { fn render(&mut self, _: &mut gpui::ViewContext) -> Self::Element { div().id("testview").child( div() - .key_context("test") - .track_focus(&self.focus_handle) + .key_context("parent") .on_key_down(|this: &mut TestView, _, _, _| this.saw_key_down = true) - .on_action(|this: &mut TestView, _: &TestAction, _| this.saw_action = true), + .on_action(|this: &mut TestView, _: &TestAction, _| this.saw_action = true) + .child(|this: &mut Self, _cx: &mut ViewContext| { + div() + .key_context("nested") + .track_focus(&this.focus_handle) + .render() + }), ) } } @@ -325,7 +330,7 @@ mod test { }); cx.update(|cx| { - cx.bind_keys(vec![KeyBinding::new("ctrl-g", TestAction, None)]); + cx.bind_keys(vec![KeyBinding::new("ctrl-g", TestAction, Some("parent"))]); }); window diff --git a/crates/gpui2/src/keymap/matcher.rs b/crates/gpui2/src/keymap/matcher.rs index bab9c0f5757354b933849ca7b324061df4812cec..a842913aef5969cf291b92c776fe866378a478b7 100644 --- a/crates/gpui2/src/keymap/matcher.rs +++ b/crates/gpui2/src/keymap/matcher.rs @@ -97,6 +97,7 @@ impl KeystrokeMatcher { } } +#[derive(Debug)] pub enum KeyMatch { None, Pending, diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 4ed7f89c7807665601f8bfe915eef56e412f6f74..3832605c3dd02c97d4f8e5b8c2895aafb2837ea3 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -1309,6 +1309,7 @@ impl<'a> WindowContext<'a> { .current_frame .dispatch_tree .dispatch_path(node_id); + dbg!(node_id, &dispatch_path, self.propagate_event); // Capture phase for node_id in &dispatch_path { @@ -1328,6 +1329,8 @@ impl<'a> WindowContext<'a> { } } + dbg!(node_id, &dispatch_path, self.propagate_event); + // Bubble phase for node_id in dispatch_path.iter().rev() { let node = self.window.current_frame.dispatch_tree.node(*node_id); @@ -1337,6 +1340,7 @@ impl<'a> WindowContext<'a> { } in node.action_listeners.clone() { let any_action = action.as_any(); + dbg!(action_type, any_action.type_id()); if action_type == any_action.type_id() { self.propagate_event = false; // Actions stop propagation by default during the bubble phase listener(any_action, DispatchPhase::Bubble, self); @@ -2082,11 +2086,10 @@ impl<'a, V: 'static> ViewContext<'a, V> { f: impl FnOnce(Option, &mut Self) -> R, ) -> R { let window = &mut self.window; - window .current_frame .dispatch_tree - .push_node(context, &mut window.previous_frame.dispatch_tree); + .push_node(context.clone(), &mut window.previous_frame.dispatch_tree); if let Some(focus_handle) = focus_handle.as_ref() { window .current_frame From b69b5742eda00fcef9693d0131ac3282bf36837a Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Tue, 14 Nov 2023 11:27:52 -0700 Subject: [PATCH 21/23] Fix panicking unwrap() --- crates/command_palette2/src/command_palette.rs | 2 -- crates/gpui2/src/elements/div.rs | 3 --- crates/gpui2/src/elements/uniform_list.rs | 6 +++++- crates/gpui2/src/window.rs | 4 ---- 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/crates/command_palette2/src/command_palette.rs b/crates/command_palette2/src/command_palette.rs index 5d428fba8e97ac306d2fe7ff54dea6e1ac0fdd37..435a6446693e590f2af9c678df445c0f53b18428 100644 --- a/crates/command_palette2/src/command_palette.rs +++ b/crates/command_palette2/src/command_palette.rs @@ -32,9 +32,7 @@ pub struct CommandPalette { impl CommandPalette { fn register(workspace: &mut Workspace, _: &mut ViewContext) { - dbg!("registering command palette toggle"); workspace.register_action(|workspace, _: &Toggle, cx| { - dbg!("got cmd-shift-p"); let Some(previous_focus_handle) = cx.focused() else { return; }; diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 94f94241b219b74ac38c3322dfbccf63f6a77443..f3f6385503466387cbd992778203301eee40ad82 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -1076,9 +1076,6 @@ where }) } - if !self.key_context.is_empty() { - dbg!(&self.key_context, self.action_listeners.len()); - } for (action_type, listener) in self.action_listeners.drain(..) { cx.on_action(action_type, listener) } diff --git a/crates/gpui2/src/elements/uniform_list.rs b/crates/gpui2/src/elements/uniform_list.rs index 2f6584cda5b25599f8b916fb271b490824f36a27..28292a3d005e29b8009afabe836b34337912a875 100644 --- a/crates/gpui2/src/elements/uniform_list.rs +++ b/crates/gpui2/src/elements/uniform_list.rs @@ -193,7 +193,11 @@ impl Element for UniformList { }; let mut interactivity = mem::take(&mut self.interactivity); - let shared_scroll_offset = element_state.interactive.scroll_offset.clone().unwrap(); + let shared_scroll_offset = element_state + .interactive + .scroll_offset + .get_or_insert_with(Arc::default) + .clone(); interactivity.paint( bounds, diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 3832605c3dd02c97d4f8e5b8c2895aafb2837ea3..00e050f2d85e8fa00146b16353da88baa550891c 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -1309,7 +1309,6 @@ impl<'a> WindowContext<'a> { .current_frame .dispatch_tree .dispatch_path(node_id); - dbg!(node_id, &dispatch_path, self.propagate_event); // Capture phase for node_id in &dispatch_path { @@ -1329,8 +1328,6 @@ impl<'a> WindowContext<'a> { } } - dbg!(node_id, &dispatch_path, self.propagate_event); - // Bubble phase for node_id in dispatch_path.iter().rev() { let node = self.window.current_frame.dispatch_tree.node(*node_id); @@ -1340,7 +1337,6 @@ impl<'a> WindowContext<'a> { } in node.action_listeners.clone() { let any_action = action.as_any(); - dbg!(action_type, any_action.type_id()); if action_type == any_action.type_id() { self.propagate_event = false; // Actions stop propagation by default during the bubble phase listener(any_action, DispatchPhase::Bubble, self); From bef4df5df98d6e715589a20c4cd92f3c67f70002 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 14 Nov 2023 16:05:28 -0700 Subject: [PATCH 22/23] Return an id from `Element::element_id` instead of calling `cx.with_element_id` Co-Authored-By: Julia --- crates/editor2/src/editor.rs | 19 +- crates/editor2/src/element.rs | 396 +++++++++++++++++----------------- 2 files changed, 210 insertions(+), 205 deletions(-) diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index 0f349ceda7927d3fbd23d7fd62239d6c84efccee..5cfd349dc9c4a43f82b47873ce3853a0737b8040 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -9409,14 +9409,17 @@ impl Render for Editor { EditorMode::Full => cx.theme().colors().editor_background, }; - EditorElement::new(EditorStyle { - background, - local_player: cx.theme().players().local(), - text: text_style, - scrollbar_width: px(12.), - syntax: cx.theme().syntax().clone(), - diagnostic_style: cx.theme().diagnostic_style(), - }) + EditorElement::new( + cx.view(), + EditorStyle { + background, + local_player: cx.theme().players().local(), + text: text_style, + scrollbar_width: px(12.), + syntax: cx.theme().syntax().clone(), + diagnostic_style: cx.theme().diagnostic_style(), + }, + ) } } diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index d06f73c92b4be4ea9f6dc6f2734160c15b3fbf85..844e6a645fcd249d7aea49d5185ddaec7ff8400c 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -20,9 +20,9 @@ use collections::{BTreeMap, HashMap}; use gpui::{ point, px, relative, size, transparent_black, Action, AnyElement, AvailableSpace, BorrowWindow, Bounds, Component, ContentMask, Corners, DispatchPhase, Edges, Element, ElementId, - ElementInputHandler, Entity, Hsla, Line, MouseButton, MouseDownEvent, MouseMoveEvent, + ElementInputHandler, Entity, EntityId, Hsla, Line, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentComponent, Pixels, ScrollWheelEvent, Size, Style, Styled, TextRun, - TextStyle, ViewContext, WindowContext, + TextStyle, View, ViewContext, WindowContext, }; use itertools::Itertools; use language::language_settings::ShowWhitespaceSetting; @@ -111,12 +111,16 @@ impl SelectionLayout { } pub struct EditorElement { + editor_id: EntityId, style: EditorStyle, } impl EditorElement { - pub fn new(style: EditorStyle) -> Self { - Self { style } + pub fn new(editor: &View, style: EditorStyle) -> Self { + Self { + editor_id: editor.entity_id(), + style, + } } fn mouse_down( @@ -2404,7 +2408,7 @@ impl Element for EditorElement { type ElementState = (); fn element_id(&self) -> Option { - None // todo! can we change the element trait to return an id here from the view context? + Some(self.editor_id.into()) } fn initialize( @@ -2451,201 +2455,199 @@ impl Element for EditorElement { }; let dispatch_context = editor.dispatch_context(cx); - cx.with_element_id(Some(cx.view().entity_id()), |cx| { - cx.with_key_dispatch( - dispatch_context, - Some(editor.focus_handle.clone()), - |_, cx| { - register_action(cx, Editor::move_left); - register_action(cx, Editor::move_right); - register_action(cx, Editor::move_down); - register_action(cx, Editor::move_up); - // on_action(cx, Editor::new_file); todo!() - // on_action(cx, Editor::new_file_in_direction); todo!() - register_action(cx, Editor::cancel); - register_action(cx, Editor::newline); - register_action(cx, Editor::newline_above); - register_action(cx, Editor::newline_below); - register_action(cx, Editor::backspace); - register_action(cx, Editor::delete); - register_action(cx, Editor::tab); - register_action(cx, Editor::tab_prev); - register_action(cx, Editor::indent); - register_action(cx, Editor::outdent); - register_action(cx, Editor::delete_line); - register_action(cx, Editor::join_lines); - register_action(cx, Editor::sort_lines_case_sensitive); - register_action(cx, Editor::sort_lines_case_insensitive); - register_action(cx, Editor::reverse_lines); - register_action(cx, Editor::shuffle_lines); - register_action(cx, Editor::convert_to_upper_case); - register_action(cx, Editor::convert_to_lower_case); - register_action(cx, Editor::convert_to_title_case); - register_action(cx, Editor::convert_to_snake_case); - register_action(cx, Editor::convert_to_kebab_case); - register_action(cx, Editor::convert_to_upper_camel_case); - register_action(cx, Editor::convert_to_lower_camel_case); - register_action(cx, Editor::delete_to_previous_word_start); - register_action(cx, Editor::delete_to_previous_subword_start); - register_action(cx, Editor::delete_to_next_word_end); - register_action(cx, Editor::delete_to_next_subword_end); - register_action(cx, Editor::delete_to_beginning_of_line); - register_action(cx, Editor::delete_to_end_of_line); - register_action(cx, Editor::cut_to_end_of_line); - register_action(cx, Editor::duplicate_line); - register_action(cx, Editor::move_line_up); - register_action(cx, Editor::move_line_down); - register_action(cx, Editor::transpose); - register_action(cx, Editor::cut); - register_action(cx, Editor::copy); - register_action(cx, Editor::paste); - register_action(cx, Editor::undo); - register_action(cx, Editor::redo); - register_action(cx, Editor::move_page_up); - register_action(cx, Editor::move_page_down); - register_action(cx, Editor::next_screen); - register_action(cx, Editor::scroll_cursor_top); - register_action(cx, Editor::scroll_cursor_center); - register_action(cx, Editor::scroll_cursor_bottom); - register_action(cx, |editor, _: &LineDown, cx| { - editor.scroll_screen(&ScrollAmount::Line(1.), cx) - }); - register_action(cx, |editor, _: &LineUp, cx| { - editor.scroll_screen(&ScrollAmount::Line(-1.), cx) - }); - register_action(cx, |editor, _: &HalfPageDown, cx| { - editor.scroll_screen(&ScrollAmount::Page(0.5), cx) - }); - register_action(cx, |editor, _: &HalfPageUp, cx| { - editor.scroll_screen(&ScrollAmount::Page(-0.5), cx) - }); - register_action(cx, |editor, _: &PageDown, cx| { - editor.scroll_screen(&ScrollAmount::Page(1.), cx) - }); - register_action(cx, |editor, _: &PageUp, cx| { - editor.scroll_screen(&ScrollAmount::Page(-1.), cx) - }); - register_action(cx, Editor::move_to_previous_word_start); - register_action(cx, Editor::move_to_previous_subword_start); - register_action(cx, Editor::move_to_next_word_end); - register_action(cx, Editor::move_to_next_subword_end); - register_action(cx, Editor::move_to_beginning_of_line); - register_action(cx, Editor::move_to_end_of_line); - register_action(cx, Editor::move_to_start_of_paragraph); - register_action(cx, Editor::move_to_end_of_paragraph); - register_action(cx, Editor::move_to_beginning); - register_action(cx, Editor::move_to_end); - register_action(cx, Editor::select_up); - register_action(cx, Editor::select_down); - register_action(cx, Editor::select_left); - register_action(cx, Editor::select_right); - register_action(cx, Editor::select_to_previous_word_start); - register_action(cx, Editor::select_to_previous_subword_start); - register_action(cx, Editor::select_to_next_word_end); - register_action(cx, Editor::select_to_next_subword_end); - register_action(cx, Editor::select_to_beginning_of_line); - register_action(cx, Editor::select_to_end_of_line); - register_action(cx, Editor::select_to_start_of_paragraph); - register_action(cx, Editor::select_to_end_of_paragraph); - register_action(cx, Editor::select_to_beginning); - register_action(cx, Editor::select_to_end); - register_action(cx, Editor::select_all); - register_action(cx, |editor, action, cx| { - editor.select_all_matches(action, cx).log_err(); - }); - register_action(cx, Editor::select_line); - register_action(cx, Editor::split_selection_into_lines); - register_action(cx, Editor::add_selection_above); - register_action(cx, Editor::add_selection_below); - register_action(cx, |editor, action, cx| { - editor.select_next(action, cx).log_err(); - }); - register_action(cx, |editor, action, cx| { - editor.select_previous(action, cx).log_err(); - }); - register_action(cx, Editor::toggle_comments); - register_action(cx, Editor::select_larger_syntax_node); - register_action(cx, Editor::select_smaller_syntax_node); - register_action(cx, Editor::move_to_enclosing_bracket); - register_action(cx, Editor::undo_selection); - register_action(cx, Editor::redo_selection); - register_action(cx, Editor::go_to_diagnostic); - register_action(cx, Editor::go_to_prev_diagnostic); - register_action(cx, Editor::go_to_hunk); - register_action(cx, Editor::go_to_prev_hunk); - register_action(cx, Editor::go_to_definition); - register_action(cx, Editor::go_to_definition_split); - register_action(cx, Editor::go_to_type_definition); - register_action(cx, Editor::go_to_type_definition_split); - register_action(cx, Editor::fold); - register_action(cx, Editor::fold_at); - register_action(cx, Editor::unfold_lines); - register_action(cx, Editor::unfold_at); - register_action(cx, Editor::fold_selected_ranges); - register_action(cx, Editor::show_completions); - register_action(cx, Editor::toggle_code_actions); - // on_action(cx, Editor::open_excerpts); todo!() - register_action(cx, Editor::toggle_soft_wrap); - register_action(cx, Editor::toggle_inlay_hints); - register_action(cx, Editor::reveal_in_finder); - register_action(cx, Editor::copy_path); - register_action(cx, Editor::copy_relative_path); - register_action(cx, Editor::copy_highlight_json); - register_action(cx, |editor, action, cx| { - editor - .format(action, cx) - .map(|task| task.detach_and_log_err(cx)); - }); - register_action(cx, Editor::restart_language_server); - register_action(cx, Editor::show_character_palette); - // on_action(cx, Editor::confirm_completion); todo!() - register_action(cx, |editor, action, cx| { - editor - .confirm_code_action(action, cx) - .map(|task| task.detach_and_log_err(cx)); - }); - // on_action(cx, Editor::rename); todo!() - // on_action(cx, Editor::confirm_rename); todo!() - register_action(cx, |editor, action, cx| { - editor - .find_all_references(action, cx) - .map(|task| task.detach_and_log_err(cx)); - }); - register_action(cx, Editor::next_copilot_suggestion); - register_action(cx, Editor::previous_copilot_suggestion); - register_action(cx, Editor::copilot_suggest); - register_action(cx, Editor::context_menu_first); - register_action(cx, Editor::context_menu_prev); - register_action(cx, Editor::context_menu_next); - register_action(cx, Editor::context_menu_last); - - // We call with_z_index to establish a new stacking context. - cx.with_z_index(0, |cx| { - cx.with_content_mask(Some(ContentMask { bounds }), |cx| { - self.paint_mouse_listeners( - bounds, - gutter_bounds, - text_bounds, - &layout.position_map, - cx, - ); - self.paint_background(gutter_bounds, text_bounds, &layout, cx); - if layout.gutter_size.width > Pixels::ZERO { - self.paint_gutter(gutter_bounds, &mut layout, editor, cx); - } - self.paint_text(text_bounds, &mut layout, editor, cx); + cx.with_key_dispatch( + dispatch_context, + Some(editor.focus_handle.clone()), + |_, cx| { + register_action(cx, Editor::move_left); + register_action(cx, Editor::move_right); + register_action(cx, Editor::move_down); + register_action(cx, Editor::move_up); + // on_action(cx, Editor::new_file); todo!() + // on_action(cx, Editor::new_file_in_direction); todo!() + register_action(cx, Editor::cancel); + register_action(cx, Editor::newline); + register_action(cx, Editor::newline_above); + register_action(cx, Editor::newline_below); + register_action(cx, Editor::backspace); + register_action(cx, Editor::delete); + register_action(cx, Editor::tab); + register_action(cx, Editor::tab_prev); + register_action(cx, Editor::indent); + register_action(cx, Editor::outdent); + register_action(cx, Editor::delete_line); + register_action(cx, Editor::join_lines); + register_action(cx, Editor::sort_lines_case_sensitive); + register_action(cx, Editor::sort_lines_case_insensitive); + register_action(cx, Editor::reverse_lines); + register_action(cx, Editor::shuffle_lines); + register_action(cx, Editor::convert_to_upper_case); + register_action(cx, Editor::convert_to_lower_case); + register_action(cx, Editor::convert_to_title_case); + register_action(cx, Editor::convert_to_snake_case); + register_action(cx, Editor::convert_to_kebab_case); + register_action(cx, Editor::convert_to_upper_camel_case); + register_action(cx, Editor::convert_to_lower_camel_case); + register_action(cx, Editor::delete_to_previous_word_start); + register_action(cx, Editor::delete_to_previous_subword_start); + register_action(cx, Editor::delete_to_next_word_end); + register_action(cx, Editor::delete_to_next_subword_end); + register_action(cx, Editor::delete_to_beginning_of_line); + register_action(cx, Editor::delete_to_end_of_line); + register_action(cx, Editor::cut_to_end_of_line); + register_action(cx, Editor::duplicate_line); + register_action(cx, Editor::move_line_up); + register_action(cx, Editor::move_line_down); + register_action(cx, Editor::transpose); + register_action(cx, Editor::cut); + register_action(cx, Editor::copy); + register_action(cx, Editor::paste); + register_action(cx, Editor::undo); + register_action(cx, Editor::redo); + register_action(cx, Editor::move_page_up); + register_action(cx, Editor::move_page_down); + register_action(cx, Editor::next_screen); + register_action(cx, Editor::scroll_cursor_top); + register_action(cx, Editor::scroll_cursor_center); + register_action(cx, Editor::scroll_cursor_bottom); + register_action(cx, |editor, _: &LineDown, cx| { + editor.scroll_screen(&ScrollAmount::Line(1.), cx) + }); + register_action(cx, |editor, _: &LineUp, cx| { + editor.scroll_screen(&ScrollAmount::Line(-1.), cx) + }); + register_action(cx, |editor, _: &HalfPageDown, cx| { + editor.scroll_screen(&ScrollAmount::Page(0.5), cx) + }); + register_action(cx, |editor, _: &HalfPageUp, cx| { + editor.scroll_screen(&ScrollAmount::Page(-0.5), cx) + }); + register_action(cx, |editor, _: &PageDown, cx| { + editor.scroll_screen(&ScrollAmount::Page(1.), cx) + }); + register_action(cx, |editor, _: &PageUp, cx| { + editor.scroll_screen(&ScrollAmount::Page(-1.), cx) + }); + register_action(cx, Editor::move_to_previous_word_start); + register_action(cx, Editor::move_to_previous_subword_start); + register_action(cx, Editor::move_to_next_word_end); + register_action(cx, Editor::move_to_next_subword_end); + register_action(cx, Editor::move_to_beginning_of_line); + register_action(cx, Editor::move_to_end_of_line); + register_action(cx, Editor::move_to_start_of_paragraph); + register_action(cx, Editor::move_to_end_of_paragraph); + register_action(cx, Editor::move_to_beginning); + register_action(cx, Editor::move_to_end); + register_action(cx, Editor::select_up); + register_action(cx, Editor::select_down); + register_action(cx, Editor::select_left); + register_action(cx, Editor::select_right); + register_action(cx, Editor::select_to_previous_word_start); + register_action(cx, Editor::select_to_previous_subword_start); + register_action(cx, Editor::select_to_next_word_end); + register_action(cx, Editor::select_to_next_subword_end); + register_action(cx, Editor::select_to_beginning_of_line); + register_action(cx, Editor::select_to_end_of_line); + register_action(cx, Editor::select_to_start_of_paragraph); + register_action(cx, Editor::select_to_end_of_paragraph); + register_action(cx, Editor::select_to_beginning); + register_action(cx, Editor::select_to_end); + register_action(cx, Editor::select_all); + register_action(cx, |editor, action, cx| { + editor.select_all_matches(action, cx).log_err(); + }); + register_action(cx, Editor::select_line); + register_action(cx, Editor::split_selection_into_lines); + register_action(cx, Editor::add_selection_above); + register_action(cx, Editor::add_selection_below); + register_action(cx, |editor, action, cx| { + editor.select_next(action, cx).log_err(); + }); + register_action(cx, |editor, action, cx| { + editor.select_previous(action, cx).log_err(); + }); + register_action(cx, Editor::toggle_comments); + register_action(cx, Editor::select_larger_syntax_node); + register_action(cx, Editor::select_smaller_syntax_node); + register_action(cx, Editor::move_to_enclosing_bracket); + register_action(cx, Editor::undo_selection); + register_action(cx, Editor::redo_selection); + register_action(cx, Editor::go_to_diagnostic); + register_action(cx, Editor::go_to_prev_diagnostic); + register_action(cx, Editor::go_to_hunk); + register_action(cx, Editor::go_to_prev_hunk); + register_action(cx, Editor::go_to_definition); + register_action(cx, Editor::go_to_definition_split); + register_action(cx, Editor::go_to_type_definition); + register_action(cx, Editor::go_to_type_definition_split); + register_action(cx, Editor::fold); + register_action(cx, Editor::fold_at); + register_action(cx, Editor::unfold_lines); + register_action(cx, Editor::unfold_at); + register_action(cx, Editor::fold_selected_ranges); + register_action(cx, Editor::show_completions); + register_action(cx, Editor::toggle_code_actions); + // on_action(cx, Editor::open_excerpts); todo!() + register_action(cx, Editor::toggle_soft_wrap); + register_action(cx, Editor::toggle_inlay_hints); + register_action(cx, Editor::reveal_in_finder); + register_action(cx, Editor::copy_path); + register_action(cx, Editor::copy_relative_path); + register_action(cx, Editor::copy_highlight_json); + register_action(cx, |editor, action, cx| { + editor + .format(action, cx) + .map(|task| task.detach_and_log_err(cx)); + }); + register_action(cx, Editor::restart_language_server); + register_action(cx, Editor::show_character_palette); + // on_action(cx, Editor::confirm_completion); todo!() + register_action(cx, |editor, action, cx| { + editor + .confirm_code_action(action, cx) + .map(|task| task.detach_and_log_err(cx)); + }); + // on_action(cx, Editor::rename); todo!() + // on_action(cx, Editor::confirm_rename); todo!() + register_action(cx, |editor, action, cx| { + editor + .find_all_references(action, cx) + .map(|task| task.detach_and_log_err(cx)); + }); + register_action(cx, Editor::next_copilot_suggestion); + register_action(cx, Editor::previous_copilot_suggestion); + register_action(cx, Editor::copilot_suggest); + register_action(cx, Editor::context_menu_first); + register_action(cx, Editor::context_menu_prev); + register_action(cx, Editor::context_menu_next); + register_action(cx, Editor::context_menu_last); + + // We call with_z_index to establish a new stacking context. + cx.with_z_index(0, |cx| { + cx.with_content_mask(Some(ContentMask { bounds }), |cx| { + self.paint_mouse_listeners( + bounds, + gutter_bounds, + text_bounds, + &layout.position_map, + cx, + ); + self.paint_background(gutter_bounds, text_bounds, &layout, cx); + if layout.gutter_size.width > Pixels::ZERO { + self.paint_gutter(gutter_bounds, &mut layout, editor, cx); + } + self.paint_text(text_bounds, &mut layout, editor, cx); - if !layout.blocks.is_empty() { - self.paint_blocks(bounds, &mut layout, editor, cx); - } + if !layout.blocks.is_empty() { + self.paint_blocks(bounds, &mut layout, editor, cx); + } - let input_handler = ElementInputHandler::new(bounds, cx); - cx.handle_input(&editor.focus_handle, input_handler); - }); + let input_handler = ElementInputHandler::new(bounds, cx); + cx.handle_input(&editor.focus_handle, input_handler); }); - }, - ) - }); + }); + }, + ) } } From 817c6dd49cb141990a3508fe6c07331c404b4f80 Mon Sep 17 00:00:00 2001 From: Mikayla Date: Tue, 14 Nov 2023 15:57:23 -0800 Subject: [PATCH 23/23] remove dbg --- crates/file_finder2/src/file_finder.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/file_finder2/src/file_finder.rs b/crates/file_finder2/src/file_finder.rs index 39bbb91465bf5c2f678442cce4af053b39e25fd6..aae3bca160da8d9db514e2e566ff7d4a1dbeeb09 100644 --- a/crates/file_finder2/src/file_finder.rs +++ b/crates/file_finder2/src/file_finder.rs @@ -33,9 +33,7 @@ pub fn init(cx: &mut AppContext) { impl FileFinder { fn register(workspace: &mut Workspace, _: &mut ViewContext) { - dbg!("REGISTERING"); workspace.register_action(|workspace, _: &Toggle, cx| { - dbg!("CALLING ACTION"); let Some(file_finder) = workspace.current_modal::(cx) else { Self::open(workspace, cx); return; @@ -594,7 +592,6 @@ impl PickerDelegate for FileFinderDelegate { } fn confirm(&mut self, secondary: bool, cx: &mut ViewContext>) { - dbg!("CONFIRMING???"); if let Some(m) = self.matches.get(self.selected_index()) { if let Some(workspace) = self.workspace.upgrade() { let open_task = workspace.update(cx, move |workspace, cx| { @@ -692,7 +689,6 @@ impl PickerDelegate for FileFinderDelegate { .log_err(); } } - dbg!("DISMISSING"); finder .update(&mut cx, |_, cx| cx.emit(ModalEvent::Dismissed)) .ok()?;