diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 3de5389b1f..2de9182901 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -488,8 +488,8 @@ impl EditorElement { } } - for (ix, fold_indicator) in layout.fold_indicators.iter_mut().enumerate() { - if let Some(fold_indicator) = fold_indicator.as_mut() { + for (ix, fold_indicator) in layout.fold_indicators.drain(..).enumerate() { + if let Some(mut fold_indicator) = fold_indicator { let available_space = size( AvailableSpace::MinContent, AvailableSpace::Definite(line_height * 0.55), @@ -509,7 +509,7 @@ impl EditorElement { } } - if let Some(indicator) = layout.code_actions_indicator.as_mut() { + if let Some(mut indicator) = layout.code_actions_indicator.take() { let available_space = size( AvailableSpace::MinContent, AvailableSpace::Definite(line_height), @@ -840,7 +840,7 @@ impl EditorElement { } }); - if let Some((position, context_menu)) = layout.context_menu.as_mut() { + if let Some((position, mut context_menu)) = layout.context_menu.take() { cx.with_z_index(1, |cx| { let line_height = self.style.text.line_height_in_pixels(cx.rem_size()); let available_space = size( @@ -1224,7 +1224,7 @@ impl EditorElement { let scroll_left = scroll_position.x * layout.position_map.em_width; let scroll_top = scroll_position.y * layout.position_map.line_height; - for block in &mut layout.blocks { + for block in layout.blocks.drain(..) { let mut origin = bounds.origin + point( Pixels::ZERO, @@ -2389,7 +2389,7 @@ enum Invisible { } impl Element for EditorElement { - type ElementState = (); + type State = (); fn element_id(&self) -> Option { Some(self.editor_id.into()) @@ -2398,9 +2398,9 @@ impl Element for EditorElement { fn layout( &mut self, editor: &mut Editor, - element_state: Option, + element_state: Option, cx: &mut gpui::ViewContext, - ) -> (gpui::LayoutId, Self::ElementState) { + ) -> (gpui::LayoutId, Self::State) { editor.style = Some(self.style.clone()); // Long-term, we'd like to eliminate this. let rem_size = cx.rem_size(); @@ -2416,10 +2416,10 @@ impl Element for EditorElement { } fn paint( - &mut self, + mut self, bounds: Bounds, editor: &mut Editor, - element_state: &mut Self::ElementState, + element_state: &mut Self::State, cx: &mut gpui::ViewContext, ) { let mut layout = self.compute_layout(editor, cx, bounds); diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index b5083b97c2..397b770c2b 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -14,7 +14,7 @@ use smallvec::SmallVec; pub use test_context::*; use crate::{ - current_platform, image_cache::ImageCache, Action, ActionRegistry, AnyBox, AnyView, + current_platform, image_cache::ImageCache, Action, ActionRegistry, Any, AnyView, AnyWindowHandle, AppMetadata, AssetSource, BackgroundExecutor, ClipboardItem, Context, DispatchPhase, DisplayId, Entity, EventEmitter, FocusEvent, FocusHandle, FocusId, ForegroundExecutor, KeyBinding, Keymap, LayoutId, PathPromptOptions, Pixels, Platform, @@ -28,7 +28,7 @@ use futures::{channel::oneshot, future::LocalBoxFuture, Future}; use parking_lot::Mutex; use slotmap::SlotMap; use std::{ - any::{type_name, Any, TypeId}, + any::{type_name, TypeId}, cell::{Ref, RefCell, RefMut}, marker::PhantomData, mem, @@ -194,7 +194,7 @@ pub struct AppContext { asset_source: Arc, pub(crate) image_cache: ImageCache, pub(crate) text_style_stack: Vec, - pub(crate) globals_by_type: HashMap, + pub(crate) globals_by_type: HashMap>, pub(crate) entities: EntityMap, pub(crate) new_view_observers: SubscriberSet, pub(crate) windows: SlotMap>, @@ -1100,12 +1100,12 @@ pub(crate) enum Effect { /// Wraps a global variable value during `update_global` while the value has been moved to the stack. pub(crate) struct GlobalLease { - global: AnyBox, + global: Box, global_type: PhantomData, } impl GlobalLease { - fn new(global: AnyBox) -> Self { + fn new(global: Box) -> Self { GlobalLease { global, global_type: PhantomData, diff --git a/crates/gpui2/src/app/entity_map.rs b/crates/gpui2/src/app/entity_map.rs index 4a3cca040b..e909e50b10 100644 --- a/crates/gpui2/src/app/entity_map.rs +++ b/crates/gpui2/src/app/entity_map.rs @@ -1,10 +1,10 @@ -use crate::{private::Sealed, AnyBox, AppContext, Context, Entity, ModelContext}; +use crate::{private::Sealed, AppContext, Context, Entity, ModelContext}; use anyhow::{anyhow, Result}; use derive_more::{Deref, DerefMut}; use parking_lot::{RwLock, RwLockUpgradableReadGuard}; use slotmap::{SecondaryMap, SlotMap}; use std::{ - any::{type_name, TypeId}, + any::{type_name, Any, TypeId}, fmt::{self, Display}, hash::{Hash, Hasher}, marker::PhantomData, @@ -31,7 +31,7 @@ impl Display for EntityId { } pub(crate) struct EntityMap { - entities: SecondaryMap, + entities: SecondaryMap>, ref_counts: Arc>, } @@ -101,7 +101,7 @@ impl EntityMap { ); } - pub fn take_dropped(&mut self) -> Vec<(EntityId, AnyBox)> { + pub fn take_dropped(&mut self) -> Vec<(EntityId, Box)> { let mut ref_counts = self.ref_counts.write(); let dropped_entity_ids = mem::take(&mut ref_counts.dropped_entity_ids); @@ -121,7 +121,7 @@ impl EntityMap { } pub struct Lease<'a, T> { - entity: Option, + entity: Option>, pub model: &'a Model, entity_type: PhantomData, } diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index 26232620d9..b9d312755a 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -3,25 +3,25 @@ use crate::{ }; use derive_more::{Deref, DerefMut}; pub(crate) use smallvec::SmallVec; -use std::{any::Any, fmt::Debug, mem}; +use std::{any::Any, fmt::Debug}; pub trait Element: 'static + Sized { - type ElementState: 'static; + type State: 'static; fn element_id(&self) -> Option; fn layout( &mut self, view_state: &mut V, - element_state: Option, + element_state: Option, cx: &mut ViewContext, - ) -> (LayoutId, Self::ElementState); + ) -> (LayoutId, Self::State); fn paint( - &mut self, + self, bounds: Bounds, view_state: &mut V, - element_state: &mut Self::ElementState, + element_state: &mut Self::State, cx: &mut ViewContext, ); @@ -35,32 +35,26 @@ pub trait Element: 'static + Sized { available_space: Size, view_state: &mut V, cx: &mut ViewContext, - f: impl FnOnce(&Self::ElementState, &mut ViewContext) -> R, + f: impl FnOnce(&mut Self::State, &mut ViewContext) -> R, ) -> R where T: Clone + Default + Debug + Into, { - let mut element = RenderedElement { - element: self, - phase: ElementRenderPhase::Start, + let element_id = self.element_id(); + let element = DrawableElement { + element: Some(self), + phase: ElementDrawPhase::Start, }; - element.draw(origin, available_space.map(Into::into), view_state, cx); - if let ElementRenderPhase::Painted { frame_state } = &element.phase { - if let Some(frame_state) = frame_state.as_ref() { - f(&frame_state, cx) - } else { - let element_id = element - .element - .element_id() - .expect("we either have some frame_state or some element_id"); - cx.with_element_state(element_id, |element_state, cx| { - let element_state = element_state.unwrap(); - let result = f(&element_state, cx); - (result, element_state) - }) - } + let frame_state = element.draw(origin, available_space.map(Into::into), view_state, cx); + + if let Some(mut frame_state) = frame_state { + f(&mut frame_state, cx) } else { - unreachable!() + cx.with_element_state(element_id.unwrap(), |element_state, cx| { + let mut element_state = element_state.unwrap(); + let result = f(&mut element_state, cx); + (result, element_state) + }) } } } @@ -107,13 +101,13 @@ trait ElementObject { ); } -struct RenderedElement> { - element: E, - phase: ElementRenderPhase, +pub struct DrawableElement> { + element: Option, + phase: ElementDrawPhase, } #[derive(Default)] -enum ElementRenderPhase { +enum ElementDrawPhase { #[default] Start, LayoutRequested { @@ -125,83 +119,83 @@ enum ElementRenderPhase { available_space: Size, frame_state: Option, }, - Painted { - frame_state: Option, - }, } /// Internal struct that wraps an element to store Layout and ElementState after the element is rendered. /// It's allocated as a trait object to erase the element type and wrapped in AnyElement for /// improved usability. -impl> RenderedElement { +impl> DrawableElement { fn new(element: E) -> Self { - RenderedElement { - element, - phase: ElementRenderPhase::Start, + DrawableElement { + element: Some(element), + phase: ElementDrawPhase::Start, } } -} -impl ElementObject for RenderedElement -where - E: Element, - E::ElementState: 'static, -{ fn layout(&mut self, state: &mut V, cx: &mut ViewContext) -> LayoutId { - let (layout_id, frame_state) = match mem::take(&mut self.phase) { - ElementRenderPhase::Start => { - if let Some(id) = self.element.element_id() { - let layout_id = cx.with_element_state(id, |element_state, cx| { - self.element.layout(state, element_state, cx) - }); - (layout_id, None) - } else { - let (layout_id, frame_state) = self.element.layout(state, None, cx); - (layout_id, Some(frame_state)) - } - } - ElementRenderPhase::LayoutRequested { .. } - | ElementRenderPhase::LayoutComputed { .. } - | ElementRenderPhase::Painted { .. } => { - panic!("element rendered twice") - } + let (layout_id, frame_state) = if let Some(id) = self.element.as_ref().unwrap().element_id() + { + let layout_id = cx.with_element_state(id, |element_state, cx| { + self.element + .as_mut() + .unwrap() + .layout(state, element_state, cx) + }); + (layout_id, None) + } else { + let (layout_id, frame_state) = self.element.as_mut().unwrap().layout(state, None, cx); + (layout_id, Some(frame_state)) }; - self.phase = ElementRenderPhase::LayoutRequested { + self.phase = ElementDrawPhase::LayoutRequested { layout_id, frame_state, }; layout_id } - fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext) { - self.phase = match mem::take(&mut self.phase) { - ElementRenderPhase::LayoutRequested { + fn paint(mut self, view_state: &mut V, cx: &mut ViewContext) -> Option { + match self.phase { + ElementDrawPhase::LayoutRequested { layout_id, - mut frame_state, + frame_state, } - | ElementRenderPhase::LayoutComputed { + | ElementDrawPhase::LayoutComputed { layout_id, - mut frame_state, + frame_state, .. } => { let bounds = cx.layout_bounds(layout_id); - if let Some(id) = self.element.element_id() { - cx.with_element_state(id, |element_state, cx| { + + if let Some(mut frame_state) = frame_state { + self.element + .take() + .unwrap() + .paint(bounds, view_state, &mut frame_state, cx); + Some(frame_state) + } else { + let element_id = self + .element + .as_ref() + .unwrap() + .element_id() + .expect("if we don't have frame state, we should have element state"); + cx.with_element_state(element_id, |element_state, cx| { let mut element_state = element_state.unwrap(); - self.element - .paint(bounds, view_state, &mut element_state, cx); + self.element.take().unwrap().paint( + bounds, + view_state, + &mut element_state, + cx, + ); ((), element_state) }); - } else { - self.element - .paint(bounds, view_state, frame_state.as_mut().unwrap(), cx); + None } - ElementRenderPhase::Painted { frame_state } } _ => panic!("must call layout before paint"), - }; + } } fn measure( @@ -210,25 +204,25 @@ where view_state: &mut V, cx: &mut ViewContext, ) -> Size { - if matches!(&self.phase, ElementRenderPhase::Start) { + if matches!(&self.phase, ElementDrawPhase::Start) { self.layout(view_state, cx); } let layout_id = match &mut self.phase { - ElementRenderPhase::LayoutRequested { + ElementDrawPhase::LayoutRequested { layout_id, frame_state, } => { cx.compute_layout(*layout_id, available_space); let layout_id = *layout_id; - self.phase = ElementRenderPhase::LayoutComputed { + self.phase = ElementDrawPhase::LayoutComputed { layout_id, available_space, frame_state: frame_state.take(), }; layout_id } - ElementRenderPhase::LayoutComputed { + ElementDrawPhase::LayoutComputed { layout_id, available_space: prev_available_space, .. @@ -245,6 +239,40 @@ where cx.layout_bounds(layout_id).size } + fn draw( + mut self, + origin: Point, + available_space: Size, + view_state: &mut V, + cx: &mut ViewContext, + ) -> Option { + self.measure(available_space, view_state, cx); + cx.with_absolute_element_offset(origin, |cx| self.paint(view_state, cx)) + } +} + +impl ElementObject for Option> +where + E: Element, + E::State: 'static, +{ + fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext) -> LayoutId { + DrawableElement::layout(self.as_mut().unwrap(), view_state, cx) + } + + fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext) { + DrawableElement::paint(self.take().unwrap(), view_state, cx); + } + + fn measure( + &mut self, + available_space: Size, + view_state: &mut V, + cx: &mut ViewContext, + ) -> Size { + DrawableElement::measure(self.as_mut().unwrap(), available_space, view_state, cx) + } + fn draw( &mut self, origin: Point, @@ -252,8 +280,13 @@ where view_state: &mut V, cx: &mut ViewContext, ) { - self.measure(available_space, view_state, cx); - cx.with_absolute_element_offset(origin, |cx| self.paint(view_state, cx)) + DrawableElement::draw( + self.take().unwrap(), + origin, + available_space, + view_state, + cx, + ); } } @@ -264,16 +297,16 @@ impl AnyElement { where V: 'static, E: 'static + Element, - E::ElementState: Any, + E::State: Any, { - AnyElement(Box::new(RenderedElement::new(element))) + AnyElement(Box::new(Some(DrawableElement::new(element))) as Box>) } pub fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext) -> LayoutId { self.0.layout(view_state, cx) } - pub fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext) { + pub fn paint(mut self, view_state: &mut V, cx: &mut ViewContext) { self.0.paint(view_state, cx) } @@ -289,7 +322,7 @@ impl AnyElement { /// Initializes this element and performs layout in the available space, then paints it at the given origin. pub fn draw( - &mut self, + mut self, origin: Point, available_space: Size, view_state: &mut V, @@ -343,7 +376,7 @@ where E: 'static + Component, F: FnOnce(&mut V, &mut ViewContext<'_, V>) -> E + 'static, { - type ElementState = AnyElement; + type State = Option>; fn element_id(&self) -> Option { None @@ -352,23 +385,23 @@ where fn layout( &mut self, view_state: &mut V, - _: Option, + _: Option, cx: &mut ViewContext, - ) -> (LayoutId, Self::ElementState) { + ) -> (LayoutId, Self::State) { let render = self.take().unwrap(); let mut rendered_element = (render)(view_state, cx).render(); let layout_id = rendered_element.layout(view_state, cx); - (layout_id, rendered_element) + (layout_id, Some(rendered_element)) } fn paint( - &mut self, + self, _bounds: Bounds, view_state: &mut V, - rendered_element: &mut Self::ElementState, + rendered_element: &mut Self::State, cx: &mut ViewContext, ) { - rendered_element.paint(view_state, cx) + rendered_element.take().unwrap().paint(view_state, cx); } } diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index f9560f2c53..1a70a9bab2 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -600,7 +600,7 @@ impl ParentComponent for Div { } impl Element for Div { - type ElementState = DivState; + type State = DivState; fn element_id(&self) -> Option { self.interactivity.element_id.clone() @@ -609,9 +609,9 @@ impl Element for Div { fn layout( &mut self, view_state: &mut V, - element_state: Option, + element_state: Option, cx: &mut ViewContext, - ) -> (LayoutId, Self::ElementState) { + ) -> (LayoutId, Self::State) { let mut child_layout_ids = SmallVec::new(); let mut interactivity = mem::take(&mut self.interactivity); let (layout_id, interactive_state) = interactivity.layout( @@ -639,10 +639,10 @@ impl Element for Div { } fn paint( - &mut self, + self, bounds: Bounds, view_state: &mut V, - element_state: &mut Self::ElementState, + element_state: &mut Self::State, cx: &mut ViewContext, ) { let mut child_min = point(Pixels::MAX, Pixels::MAX); @@ -658,8 +658,7 @@ impl Element for Div { (child_max - child_min).into() }; - let mut interactivity = mem::take(&mut self.interactivity); - interactivity.paint( + self.interactivity.paint( bounds, content_size, &mut element_state.interactive_state, @@ -679,7 +678,7 @@ impl Element for Div { 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 { + for child in self.children { child.paint(view_state, cx); } }) @@ -689,7 +688,6 @@ impl Element for Div { }) }, ); - self.interactivity = interactivity; } } @@ -770,7 +768,7 @@ where } pub fn paint( - &mut self, + mut self, bounds: Bounds, content_size: Size, element_state: &mut InteractiveElementState, @@ -786,25 +784,25 @@ where } } - for listener in self.mouse_down_listeners.drain(..) { + for listener in self.mouse_down_listeners { cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| { listener(state, event, &bounds, phase, cx); }) } - for listener in self.mouse_up_listeners.drain(..) { + for listener in self.mouse_up_listeners { cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| { listener(state, event, &bounds, phase, cx); }) } - for listener in self.mouse_move_listeners.drain(..) { + for listener in self.mouse_move_listeners { cx.on_mouse_event(move |state, event: &MouseMoveEvent, phase, cx| { listener(state, event, &bounds, phase, cx); }) } - for listener in self.scroll_wheel_listeners.drain(..) { + for listener in self.scroll_wheel_listeners { cx.on_mouse_event(move |state, event: &ScrollWheelEvent, phase, cx| { listener(state, event, &bounds, phase, cx); }) @@ -840,7 +838,7 @@ where } if cx.active_drag.is_some() { - let drop_listeners = mem::take(&mut self.drop_listeners); + let drop_listeners = 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) = @@ -1062,24 +1060,24 @@ where self.key_context.clone(), element_state.focus_handle.clone(), |_, cx| { - for listener in self.key_down_listeners.drain(..) { + for listener in self.key_down_listeners { cx.on_key_event(move |state, event: &KeyDownEvent, phase, cx| { listener(state, event, phase, cx); }) } - for listener in self.key_up_listeners.drain(..) { + for listener in self.key_up_listeners { cx.on_key_event(move |state, event: &KeyUpEvent, phase, cx| { listener(state, event, phase, cx); }) } - for (action_type, listener) in self.action_listeners.drain(..) { + for (action_type, listener) in self.action_listeners { cx.on_action(action_type, listener) } if let Some(focus_handle) = element_state.focus_handle.as_ref() { - for listener in self.focus_listeners.drain(..) { + for listener in self.focus_listeners { let focus_handle = focus_handle.clone(); cx.on_focus_changed(move |view, event, cx| { listener(view, &focus_handle, event, cx) @@ -1291,7 +1289,7 @@ where V: 'static, E: Element, { - type ElementState = E::ElementState; + type State = E::State; fn element_id(&self) -> Option { self.element.element_id() @@ -1300,20 +1298,20 @@ where fn layout( &mut self, view_state: &mut V, - element_state: Option, + element_state: Option, cx: &mut ViewContext, - ) -> (LayoutId, Self::ElementState) { + ) -> (LayoutId, Self::State) { self.element.layout(view_state, element_state, cx) } fn paint( - &mut self, + self, bounds: Bounds, view_state: &mut V, - element_state: &mut Self::ElementState, + element_state: &mut Self::State, cx: &mut ViewContext, ) { - self.element.paint(bounds, view_state, element_state, cx); + self.element.paint(bounds, view_state, element_state, cx) } } @@ -1377,7 +1375,7 @@ where V: 'static, E: Element, { - type ElementState = E::ElementState; + type State = E::State; fn element_id(&self) -> Option { self.element.element_id() @@ -1386,17 +1384,17 @@ where fn layout( &mut self, view_state: &mut V, - element_state: Option, + element_state: Option, cx: &mut ViewContext, - ) -> (LayoutId, Self::ElementState) { + ) -> (LayoutId, Self::State) { self.element.layout(view_state, element_state, cx) } fn paint( - &mut self, + self, bounds: Bounds, view_state: &mut V, - element_state: &mut Self::ElementState, + element_state: &mut Self::State, cx: &mut ViewContext, ) { self.element.paint(bounds, view_state, element_state, cx) diff --git a/crates/gpui2/src/elements/img.rs b/crates/gpui2/src/elements/img.rs index 1080135fe1..db55bd0dc6 100644 --- a/crates/gpui2/src/elements/img.rs +++ b/crates/gpui2/src/elements/img.rs @@ -42,7 +42,7 @@ impl Component for Img { } impl Element for Img { - type ElementState = InteractiveElementState; + type State = InteractiveElementState; fn element_id(&self) -> Option { self.interactivity.element_id.clone() @@ -51,19 +51,19 @@ impl Element for Img { fn layout( &mut self, _view_state: &mut V, - element_state: Option, + element_state: Option, cx: &mut ViewContext, - ) -> (LayoutId, Self::ElementState) { + ) -> (LayoutId, Self::State) { self.interactivity.layout(element_state, cx, |style, cx| { cx.request_layout(&style, None) }) } fn paint( - &mut self, + self, bounds: Bounds, _view_state: &mut V, - element_state: &mut Self::ElementState, + element_state: &mut Self::State, cx: &mut ViewContext, ) { self.interactivity.paint( diff --git a/crates/gpui2/src/elements/overlay.rs b/crates/gpui2/src/elements/overlay.rs index 14a8048d39..394030f3d7 100644 --- a/crates/gpui2/src/elements/overlay.rs +++ b/crates/gpui2/src/elements/overlay.rs @@ -64,7 +64,7 @@ impl Component for Overlay { } impl Element for Overlay { - type ElementState = OverlayState; + type State = OverlayState; fn element_id(&self) -> Option { None @@ -73,9 +73,9 @@ impl Element for Overlay { fn layout( &mut self, view_state: &mut V, - _: Option, + _: Option, cx: &mut crate::ViewContext, - ) -> (crate::LayoutId, Self::ElementState) { + ) -> (crate::LayoutId, Self::State) { let child_layout_ids = self .children .iter_mut() @@ -92,10 +92,10 @@ impl Element for Overlay { } fn paint( - &mut self, + self, bounds: crate::Bounds, view_state: &mut V, - element_state: &mut Self::ElementState, + element_state: &mut Self::State, cx: &mut crate::ViewContext, ) { if element_state.child_layout_ids.is_empty() { @@ -156,7 +156,7 @@ impl Element for Overlay { } cx.with_element_offset(desired.origin - bounds.origin, |cx| { - for child in &mut self.children { + for child in self.children { child.paint(view_state, cx); } }) diff --git a/crates/gpui2/src/elements/svg.rs b/crates/gpui2/src/elements/svg.rs index c1c7691fbf..7d9c04b729 100644 --- a/crates/gpui2/src/elements/svg.rs +++ b/crates/gpui2/src/elements/svg.rs @@ -31,7 +31,7 @@ impl Component for Svg { } impl Element for Svg { - type ElementState = InteractiveElementState; + type State = InteractiveElementState; fn element_id(&self) -> Option { self.interactivity.element_id.clone() @@ -40,19 +40,19 @@ impl Element for Svg { fn layout( &mut self, _view_state: &mut V, - element_state: Option, + element_state: Option, cx: &mut ViewContext, - ) -> (LayoutId, Self::ElementState) { + ) -> (LayoutId, Self::State) { self.interactivity.layout(element_state, cx, |style, cx| { cx.request_layout(&style, None) }) } fn paint( - &mut self, + self, bounds: Bounds, _view_state: &mut V, - element_state: &mut Self::ElementState, + element_state: &mut Self::State, cx: &mut ViewContext, ) where Self: Sized, diff --git a/crates/gpui2/src/elements/text.rs b/crates/gpui2/src/elements/text.rs index 9e8256014e..c6090fdfb4 100644 --- a/crates/gpui2/src/elements/text.rs +++ b/crates/gpui2/src/elements/text.rs @@ -9,7 +9,7 @@ use std::{cell::Cell, rc::Rc, sync::Arc}; use util::ResultExt; impl Element for &'static str { - type ElementState = TextState; + type State = TextState; fn element_id(&self) -> Option { None @@ -18,16 +18,16 @@ impl Element for &'static str { fn layout( &mut self, _: &mut V, - _: Option, + _: Option, cx: &mut ViewContext, - ) -> (LayoutId, Self::ElementState) { + ) -> (LayoutId, Self::State) { let mut state = TextState::default(); let layout_id = state.layout(SharedString::from(*self), None, cx); (layout_id, state) } fn paint( - &mut self, + self, bounds: Bounds, _: &mut V, state: &mut TextState, @@ -38,7 +38,7 @@ impl Element for &'static str { } impl Element for SharedString { - type ElementState = TextState; + type State = TextState; fn element_id(&self) -> Option { Some(self.clone().into()) @@ -47,16 +47,16 @@ impl Element for SharedString { fn layout( &mut self, _: &mut V, - _: Option, + _: Option, cx: &mut ViewContext, - ) -> (LayoutId, Self::ElementState) { + ) -> (LayoutId, Self::State) { let mut state = TextState::default(); let layout_id = state.layout(self.clone(), None, cx); (layout_id, state) } fn paint( - &mut self, + self, bounds: Bounds, _: &mut V, state: &mut TextState, @@ -93,7 +93,7 @@ impl Component for Text { } impl Element for Text { - type ElementState = TextState; + type State = TextState; fn element_id(&self) -> Option { None @@ -102,9 +102,9 @@ impl Element for Text { fn layout( &mut self, _view: &mut V, - element_state: Option, + element_state: Option, cx: &mut ViewContext, - ) -> (LayoutId, Self::ElementState) { + ) -> (LayoutId, Self::State) { let element_state = element_state.unwrap_or_default(); let text_system = cx.text_system().clone(); let text_style = cx.text_style(); @@ -160,10 +160,10 @@ impl Element for Text { } fn paint( - &mut self, + self, bounds: Bounds, _: &mut V, - element_state: &mut Self::ElementState, + element_state: &mut Self::State, cx: &mut ViewContext, ) { let element_state = element_state.lock(); @@ -280,7 +280,7 @@ struct InteractiveTextState { } impl Element for InteractiveText { - type ElementState = InteractiveTextState; + type State = InteractiveTextState; fn element_id(&self) -> Option { Some(self.id.clone()) @@ -289,9 +289,9 @@ impl Element for InteractiveText { fn layout( &mut self, view_state: &mut V, - element_state: Option, + element_state: Option, cx: &mut ViewContext, - ) -> (LayoutId, Self::ElementState) { + ) -> (LayoutId, Self::State) { if let Some(InteractiveTextState { text_state, clicked_range_ixs, @@ -314,10 +314,10 @@ impl Element for InteractiveText { } fn paint( - &mut self, + self, bounds: Bounds, view_state: &mut V, - element_state: &mut Self::ElementState, + element_state: &mut Self::State, cx: &mut ViewContext, ) { self.text diff --git a/crates/gpui2/src/elements/uniform_list.rs b/crates/gpui2/src/elements/uniform_list.rs index 773f9ec8aa..d7339d00ab 100644 --- a/crates/gpui2/src/elements/uniform_list.rs +++ b/crates/gpui2/src/elements/uniform_list.rs @@ -4,7 +4,7 @@ use crate::{ Point, Size, StyleRefinement, Styled, ViewContext, }; use smallvec::SmallVec; -use std::{cell::RefCell, cmp, mem, ops::Range, rc::Rc}; +use std::{cell::RefCell, cmp, ops::Range, rc::Rc}; use taffy::style::Overflow; /// uniform_list provides lazy rendering for a set of items that are of uniform height. @@ -102,7 +102,7 @@ pub struct UniformListState { } impl Element for UniformList { - type ElementState = UniformListState; + type State = UniformListState; fn element_id(&self) -> Option { Some(self.id.clone()) @@ -111,9 +111,9 @@ impl Element for UniformList { fn layout( &mut self, view_state: &mut V, - element_state: Option, + element_state: Option, cx: &mut ViewContext, - ) -> (LayoutId, Self::ElementState) { + ) -> (LayoutId, Self::State) { let max_items = self.item_count; let rem_size = cx.rem_size(); let item_size = element_state @@ -159,10 +159,10 @@ impl Element for UniformList { } fn paint( - &mut self, + self, bounds: Bounds, view_state: &mut V, - element_state: &mut Self::ElementState, + element_state: &mut Self::State, cx: &mut ViewContext, ) { let style = @@ -183,14 +183,17 @@ impl Element for UniformList { height: item_size.height * self.item_count, }; - let mut interactivity = mem::take(&mut self.interactivity); let shared_scroll_offset = element_state .interactive .scroll_offset .get_or_insert_with(Rc::default) .clone(); - interactivity.paint( + let item_height = self + .measure_item(view_state, Some(padded_bounds.size.width), cx) + .height; + + self.interactivity.paint( bounds, content_size, &mut element_state.interactive, @@ -209,9 +212,6 @@ impl Element for UniformList { style.paint(bounds, cx); 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.borrow_mut().replace(ScrollHandleState { item_height, @@ -233,9 +233,9 @@ impl Element for UniformList { self.item_count, ); - let mut items = (self.render_items)(view_state, visible_range.clone(), cx); + let 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) { + for (item, ix) in items.into_iter().zip(visible_range) { let item_origin = padded_bounds.origin + point(px(0.), item_height * ix + scroll_offset.y); let available_space = size( @@ -249,7 +249,6 @@ impl Element for UniformList { }) }, ); - self.interactivity = interactivity; } } diff --git a/crates/gpui2/src/gpui2.rs b/crates/gpui2/src/gpui2.rs index 88ecd52c03..4423986e3d 100644 --- a/crates/gpui2/src/gpui2.rs +++ b/crates/gpui2/src/gpui2.rs @@ -78,8 +78,6 @@ use std::{ }; use taffy::TaffyLayoutEngine; -type AnyBox = Box; - pub trait Context { type Result; diff --git a/crates/gpui2/src/view.rs b/crates/gpui2/src/view.rs index 6b8c8a3eef..51675e814c 100644 --- a/crates/gpui2/src/view.rs +++ b/crates/gpui2/src/view.rs @@ -1,8 +1,7 @@ use crate::{ - private::Sealed, AnyBox, AnyElement, AnyModel, AnyWeakModel, AppContext, AvailableSpace, - BorrowWindow, Bounds, Component, Element, ElementId, Entity, EntityId, Flatten, FocusHandle, - FocusableView, LayoutId, Model, Pixels, Point, Size, ViewContext, VisualContext, WeakModel, - WindowContext, + private::Sealed, AnyElement, AnyModel, AnyWeakModel, AppContext, AvailableSpace, BorrowWindow, + Bounds, Component, Element, ElementId, Entity, EntityId, Flatten, FocusHandle, FocusableView, + LayoutId, Model, Pixels, Point, Size, ViewContext, VisualContext, WeakModel, WindowContext, }; use anyhow::{Context, Result}; use std::{ @@ -164,7 +163,7 @@ impl Eq for WeakView {} pub struct AnyView { model: AnyModel, layout: fn(&AnyView, &mut WindowContext) -> (LayoutId, Box), - paint: fn(&AnyView, &mut AnyBox, &mut WindowContext), + paint: fn(&AnyView, Box, &mut WindowContext), } impl AnyView { @@ -198,11 +197,11 @@ impl AnyView { cx: &mut WindowContext, ) { cx.with_absolute_element_offset(origin, |cx| { - let (layout_id, mut rendered_element) = (self.layout)(self, cx); + let (layout_id, rendered_element) = (self.layout)(self, cx); cx.window .layout_engine .compute_layout(layout_id, available_space); - (self.paint)(self, &mut rendered_element, cx); + (self.paint)(self, rendered_element, cx); }) } } @@ -224,7 +223,7 @@ impl From> for AnyView { } impl Element for AnyView { - type ElementState = Box; + type State = Option>; fn element_id(&self) -> Option { Some(self.model.entity_id.into()) @@ -233,27 +232,28 @@ impl Element for AnyView { fn layout( &mut self, _view_state: &mut ParentViewState, - _element_state: Option, + _element_state: Option, cx: &mut ViewContext, - ) -> (LayoutId, Self::ElementState) { - (self.layout)(self, cx) + ) -> (LayoutId, Self::State) { + let (layout_id, rendered_element) = (self.layout)(self, cx); + (layout_id, Some(rendered_element)) } fn paint( - &mut self, + mut self, _bounds: Bounds, _view_state: &mut ParentViewState, - rendered_element: &mut Self::ElementState, + rendered_element: &mut Self::State, cx: &mut ViewContext, ) { - (self.paint)(self, rendered_element, cx) + (self.paint)(&mut self, rendered_element.take().unwrap(), cx) } } pub struct AnyWeakView { model: AnyWeakModel, layout: fn(&AnyView, &mut WindowContext) -> (LayoutId, Box), - paint: fn(&AnyView, &mut AnyBox, &mut WindowContext), + paint: fn(&AnyView, Box, &mut WindowContext), } impl AnyWeakView { @@ -311,7 +311,7 @@ where ParentViewState: 'static, ViewState: 'static, { - type ElementState = AnyElement; + type State = Option>; fn element_id(&self) -> Option { Some(self.view.entity_id().into()) @@ -320,24 +320,25 @@ where fn layout( &mut self, _: &mut ParentViewState, - _: Option, + _: Option, cx: &mut ViewContext, - ) -> (LayoutId, Self::ElementState) { + ) -> (LayoutId, Self::State) { self.view.update(cx, |view, cx| { let mut element = self.component.take().unwrap().render(); let layout_id = element.layout(view, cx); - (layout_id, element) + (layout_id, Some(element)) }) } fn paint( - &mut self, + self, _: Bounds, _: &mut ParentViewState, - element: &mut Self::ElementState, + element: &mut Self::State, cx: &mut ViewContext, ) { - self.view.update(cx, |view, cx| element.paint(view, cx)) + self.view + .update(cx, |view, cx| element.take().unwrap().paint(view, cx)) } } @@ -359,14 +360,10 @@ mod any_view { }) } - pub(crate) fn paint( - view: &AnyView, - element: &mut Box, - cx: &mut WindowContext, - ) { + pub(crate) fn paint(view: &AnyView, element: Box, cx: &mut WindowContext) { cx.with_element_id(Some(view.model.entity_id), |cx| { let view = view.clone().downcast::().unwrap(); - let element = element.downcast_mut::>().unwrap(); + let element = element.downcast::>().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 6d07f06d94..a9a2c60acb 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -1,5 +1,5 @@ use crate::{ - key_dispatch::DispatchActionListener, px, size, Action, AnyBox, AnyDrag, AnyView, AppContext, + key_dispatch::DispatchActionListener, px, size, Action, AnyDrag, AnyView, AppContext, AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, Context, Corners, CursorStyle, DevicePixels, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, FocusEvent, FontId, GlobalElementId, GlyphId, Hsla, ImageData, @@ -237,7 +237,7 @@ pub struct Window { // #[derive(Default)] pub(crate) struct Frame { - pub(crate) element_states: HashMap, + pub(crate) element_states: HashMap>, mouse_listeners: HashMap>, pub(crate) dispatch_tree: DispatchTree, pub(crate) focus_listeners: Vec, diff --git a/crates/gpui2_macros/src/gpui2_macros.rs b/crates/gpui2_macros/src/gpui2_macros.rs index 3ce8373689..02c9629d01 100644 --- a/crates/gpui2_macros/src/gpui2_macros.rs +++ b/crates/gpui2_macros/src/gpui2_macros.rs @@ -1,5 +1,6 @@ mod action; mod derive_component; +mod derive_element; mod register_action; mod style_helpers; mod test; @@ -26,6 +27,11 @@ pub fn derive_component(input: TokenStream) -> TokenStream { derive_component::derive_component(input) } +// #[proc_macro_derive(Element)] +// pub fn derive_element(input: TokenStream) -> TokenStream { +// derive_element::derive_element(input) +// } + #[proc_macro_attribute] pub fn test(args: TokenStream, function: TokenStream) -> TokenStream { test::test(args, function) diff --git a/crates/ui2/src/components/context_menu.rs b/crates/ui2/src/components/context_menu.rs index d3214cbff1..c6d2382f56 100644 --- a/crates/ui2/src/components/context_menu.rs +++ b/crates/ui2/src/components/context_menu.rs @@ -133,7 +133,7 @@ pub struct MenuHandleState { menu_element: Option>, } impl Element for MenuHandle { - type ElementState = MenuHandleState; + type State = MenuHandleState; fn element_id(&self) -> Option { Some(self.id.clone().expect("menu_handle must have an id()")) @@ -142,9 +142,9 @@ impl Element for MenuHandle { fn layout( &mut self, view_state: &mut V, - element_state: Option, + element_state: Option, cx: &mut crate::ViewContext, - ) -> (gpui::LayoutId, Self::ElementState) { + ) -> (gpui::LayoutId, Self::State) { let (menu, position) = if let Some(element_state) = element_state { (element_state.menu, element_state.position) } else { @@ -192,22 +192,22 @@ impl Element for MenuHandle { } fn paint( - &mut self, + self, bounds: Bounds, view_state: &mut V, - element_state: &mut Self::ElementState, + element_state: &mut Self::State, cx: &mut crate::ViewContext, ) { - if let Some(child) = element_state.child_element.as_mut() { + if let Some(child) = element_state.child_element.take() { child.paint(view_state, cx); } - if let Some(menu) = element_state.menu_element.as_mut() { + if let Some(menu) = element_state.menu_element.take() { menu.paint(view_state, cx); return; } - let Some(builder) = self.menu_builder.clone() else { + let Some(builder) = self.menu_builder else { return; }; let menu = element_state.menu.clone();