diff --git a/crates/gpui/examples/components.rs b/crates/gpui/examples/components.rs index 09a732c6c1b640ebdead04d960ebc83fae3f15a3..cf695ea834b4424a243b40f6d49222f6bb8a54d2 100644 --- a/crates/gpui/examples/components.rs +++ b/crates/gpui/examples/components.rs @@ -1,9 +1,8 @@ use button_component::Button; -use component::Component; use gpui::{ color::Color, - elements::{ContainerStyle, Flex, Label, ParentElement}, + elements::{Component, ContainerStyle, Flex, Label, ParentElement}, fonts::{self, TextStyle}, platform::WindowOptions, AnyElement, App, Element, Entity, View, ViewContext, @@ -115,12 +114,12 @@ mod theme { // Component creation: mod toggleable_button { use gpui::{ - elements::{ContainerStyle, LabelStyle}, + elements::{Component, ContainerStyle, LabelStyle}, scene::MouseClick, EventContext, View, }; - use crate::{button_component::Button, component::Component, theme::Toggleable}; + use crate::{button_component::Button, theme::Toggleable}; pub struct ToggleableButton { active: bool, @@ -172,14 +171,12 @@ mod toggleable_button { mod button_component { use gpui::{ - elements::{ContainerStyle, Label, LabelStyle, MouseEventHandler}, + elements::{Component, ContainerStyle, Label, LabelStyle, MouseEventHandler}, platform::MouseButton, scene::MouseClick, AnyElement, Element, EventContext, TypeTag, View, ViewContext, }; - use crate::component::Component; - type ClickHandler = Box)>; pub struct Button { @@ -238,88 +235,3 @@ mod button_component { } } } - -mod component { - - use gpui::{AnyElement, Element, View, ViewContext}; - use pathfinder_geometry::vector::Vector2F; - - pub trait Component { - fn render(self, v: &mut V, cx: &mut ViewContext) -> AnyElement; - - fn into_element(self) -> ComponentAdapter - where - Self: Sized, - { - ComponentAdapter::new(self) - } - } - - pub struct ComponentAdapter { - component: Option, - phantom: std::marker::PhantomData, - } - - impl ComponentAdapter { - pub fn new(e: E) -> Self { - Self { - component: Some(e), - phantom: std::marker::PhantomData, - } - } - } - - impl + 'static> Element for ComponentAdapter { - type LayoutState = AnyElement; - - type PaintState = (); - - fn layout( - &mut self, - constraint: gpui::SizeConstraint, - view: &mut V, - cx: &mut gpui::LayoutContext, - ) -> (Vector2F, Self::LayoutState) { - let component = self.component.take().unwrap(); - let mut element = component.render(view, cx.view_context()); - let constraint = element.layout(constraint, view, cx); - (constraint, element) - } - - fn paint( - &mut self, - scene: &mut gpui::SceneBuilder, - bounds: gpui::geometry::rect::RectF, - visible_bounds: gpui::geometry::rect::RectF, - layout: &mut Self::LayoutState, - view: &mut V, - cx: &mut gpui::PaintContext, - ) -> Self::PaintState { - layout.paint(scene, bounds.origin(), visible_bounds, view, cx) - } - - fn rect_for_text_range( - &self, - _: std::ops::Range, - _: gpui::geometry::rect::RectF, - _: gpui::geometry::rect::RectF, - _: &Self::LayoutState, - _: &Self::PaintState, - _: &V, - _: &ViewContext, - ) -> Option { - todo!() - } - - fn debug( - &self, - _: gpui::geometry::rect::RectF, - _: &Self::LayoutState, - _: &Self::PaintState, - _: &V, - _: &ViewContext, - ) -> serde_json::Value { - todo!() - } - } -} diff --git a/crates/gpui/src/elements.rs b/crates/gpui/src/elements.rs index 16c750ea8ed9905c794364f03acbc67ca5ae0289..35ecf0545a06693dea61a8411d65518d00a5e3a5 100644 --- a/crates/gpui/src/elements.rs +++ b/crates/gpui/src/elements.rs @@ -1,6 +1,7 @@ mod align; mod canvas; mod clipped; +mod component; mod constrained_box; mod container; mod empty; @@ -21,9 +22,9 @@ mod tooltip; mod uniform_list; pub use self::{ - align::*, canvas::*, constrained_box::*, container::*, empty::*, flex::*, hook::*, image::*, - keystroke_label::*, label::*, list::*, mouse_event_handler::*, overlay::*, resizable::*, - stack::*, svg::*, text::*, tooltip::*, uniform_list::*, + align::*, canvas::*, component::*, constrained_box::*, container::*, empty::*, flex::*, + hook::*, image::*, keystroke_label::*, label::*, list::*, mouse_event_handler::*, overlay::*, + resizable::*, stack::*, svg::*, text::*, tooltip::*, uniform_list::*, }; pub use crate::window::ChildView; diff --git a/crates/gpui/src/elements/component.rs b/crates/gpui/src/elements/component.rs new file mode 100644 index 0000000000000000000000000000000000000000..1c4359e2c35fc54d97b40695d96922eda3210649 --- /dev/null +++ b/crates/gpui/src/elements/component.rs @@ -0,0 +1,87 @@ +use std::marker::PhantomData; + +use pathfinder_geometry::{rect::RectF, vector::Vector2F}; + +use crate::{ + AnyElement, Element, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, View, + ViewContext, +}; + +pub trait Component { + fn render(self, v: &mut V, cx: &mut ViewContext) -> AnyElement; + + fn into_element(self) -> ComponentAdapter + where + Self: Sized, + { + ComponentAdapter::new(self) + } +} + +pub struct ComponentAdapter { + component: Option, + phantom: PhantomData, +} + +impl ComponentAdapter { + pub fn new(e: E) -> Self { + Self { + component: Some(e), + phantom: PhantomData, + } + } +} + +impl + 'static> Element for ComponentAdapter { + type LayoutState = AnyElement; + + type PaintState = (); + + fn layout( + &mut self, + constraint: SizeConstraint, + view: &mut V, + cx: &mut LayoutContext, + ) -> (Vector2F, Self::LayoutState) { + let component = self.component.take().unwrap(); + let mut element = component.render(view, cx.view_context()); + let constraint = element.layout(constraint, view, cx); + (constraint, element) + } + + fn paint( + &mut self, + scene: &mut SceneBuilder, + bounds: RectF, + visible_bounds: RectF, + layout: &mut Self::LayoutState, + view: &mut V, + cx: &mut PaintContext, + ) -> Self::PaintState { + layout.paint(scene, bounds.origin(), visible_bounds, view, cx) + } + + fn rect_for_text_range( + &self, + range_utf16: std::ops::Range, + _: RectF, + _: RectF, + element: &Self::LayoutState, + _: &Self::PaintState, + view: &V, + cx: &ViewContext, + ) -> Option { + element.rect_for_text_range(range_utf16, view, cx) + } + + fn debug( + &self, + _: RectF, + element: &Self::LayoutState, + _: &Self::PaintState, + view: &V, + cx: &ViewContext, + ) -> serde_json::Value { + element.debug(view, cx) + } +}