diff --git a/crates/gpui/playground/src/playground.rs b/crates/gpui/playground/src/playground.rs index a5ecd7104e..9a2f30c444 100644 --- a/crates/gpui/playground/src/playground.rs +++ b/crates/gpui/playground/src/playground.rs @@ -14,10 +14,10 @@ fn main() { } #[derive(Clone, Default)] -struct Playground(playground_ui::Playground); +struct Playground(playground_ui::Playground); impl Deref for Playground { - type Target = playground_ui::Playground; + type Target = playground_ui::Playground; fn deref(&self) -> &Self::Target { &self.0 diff --git a/crates/gpui/playground/ui/src/playground_ui.rs b/crates/gpui/playground/ui/src/playground_ui.rs index bcad09d483..6bce415335 100644 --- a/crates/gpui/playground/ui/src/playground_ui.rs +++ b/crates/gpui/playground/ui/src/playground_ui.rs @@ -2,16 +2,16 @@ use gpui::{ elements::node::{column, length::auto, row, text}, AnyElement, Element, LayoutContext, View, ViewContext, }; -use std::{borrow::Cow, marker::PhantomData}; +use std::{borrow::Cow, cell::RefCell, marker::PhantomData, rc::Rc}; use tokens::{margin::m4, text::lg}; mod tokens; #[derive(Element, Clone, Default)] -pub struct Playground; +pub struct Playground(PhantomData); -impl Playground { - pub fn render(&mut self, _: &mut V, _: &mut gpui::ViewContext) -> AnyElement { +impl Playground { + pub fn render(&mut self, _: &mut V, _: &mut gpui::ViewContext) -> AnyElement { column() .width(auto()) .child( @@ -22,30 +22,25 @@ impl Playground { .into_any() } - fn action_1(&mut self, data: &usize, _: &mut ViewContext) { + fn action_1(_: &mut V, data: &usize, _: &mut ViewContext) { println!("action 1: data is {}", *data); } - fn action_2(&mut self, data: &usize, _: &mut ViewContext) { + fn action_2(_: &mut V, data: &usize, _: &mut ViewContext) { println!("action 1: data is {}", *data); } } -pub trait DialogDelegate: 'static { - fn handle_confirm(&mut self, view: &mut V, button: B); -} +pub trait DialogDelegate: 'static {} -impl DialogDelegate for () { - fn handle_cancel(&mut self, view: &mut V, button: B) {} - fn handle_confirm(&mut self, _: &mut V, _: B) {} -} +impl DialogDelegate for () {} #[derive(Element)] pub struct Dialog> { title: Cow<'static, str>, description: Cow<'static, str>, delegate: Option>>, - buttons: Vec Button>>, + buttons: Vec AnyElement>>, view_type: PhantomData, } @@ -64,19 +59,21 @@ pub fn dialog( impl> Dialog { pub fn delegate(mut self, delegate: D) -> Dialog { - let old_delegate = self.delegate.replace(delegate); + let old_delegate = self.delegate.replace(Rc::new(RefCell::new(delegate))); debug_assert!(old_delegate.is_none(), "delegate already set"); self } - pub fn button(mut self, label: L, data: D, handler: H) -> Self + pub fn button(mut self, label: L, data: Data, handler: H) -> Self where - L: Into>, - D: 'static, - H: ClickHandler, + L: 'static + Into>, + Data: 'static + Clone, + H: ClickHandler, { - self.buttons - .push(|| button(label).data(data).click(handler)); + let label = label.into(); + self.buttons.push(Box::new(move || { + button(label).data(data).click(handler).into_any() + })); self } } @@ -128,7 +125,7 @@ where impl Button { fn data(self, data: D) -> Button where - D: 'static + FnOnce(&mut V, &D, &mut ViewContext), + D: 'static, { Button { label: self.label, @@ -142,7 +139,7 @@ impl Button { impl Button { fn click(self, handler: H) -> Button where - H: 'static + Fn(&mut V, &D, &mut ViewContext), + H: 'static + ClickHandler, { Button { label: self.label, @@ -155,12 +152,10 @@ impl Button { impl> Dialog { pub fn render(&mut self, _: &mut V, _: &mut gpui::ViewContext) -> AnyElement { - let delegate = self.delegate.clone(); - column() .child(text(self.title.clone()).text_size(lg())) .child(text(self.description.clone()).margins(m4(), auto())) - .child(row().children(self.buttons.iter().map(|button| (button)()))) + .child(row().children(self.buttons.drain(..).map(|button| (button)()))) .into_any() } } diff --git a/crates/gpui/src/elements/node.rs b/crates/gpui/src/elements/node.rs index 26c5ee9720..e0cfafbdcb 100644 --- a/crates/gpui/src/elements/node.rs +++ b/crates/gpui/src/elements/node.rs @@ -273,7 +273,7 @@ impl Node { } } - fn paint_2d_children( + fn paint_children_xy( &mut self, scene: &mut SceneBuilder, axis: Axis2d, @@ -395,15 +395,7 @@ impl Element for Node { let mut layout = NodeLayout::default(); let size = if let Some(axis) = self.style.axis.to_2d() { - self.layout_xy( - axis, - constraint.max, - cx.rem_pixels(), - &mut layout, - &mut layout.padding, - view, - cx, - ) + self.layout_xy(axis, constraint.max, cx.rem_pixels(), &mut layout, view, cx) } else { todo!() }; @@ -421,11 +413,6 @@ impl Element for Node { cx: &mut PaintContext, ) -> Self::PaintState { let rem_pixels = cx.rem_pixels(); - // let margin: Edges = todo!(); // &self.style.margin.to_pixels(rem_size); - // - - let size = bounds.size(); - let margined_bounds = RectF::from_points( bounds.origin() + vec2f(layout.margins.left, layout.margins.top), bounds.lower_right() - vec2f(layout.margins.right, layout.margins.bottom), @@ -434,7 +421,7 @@ impl Element for Node { // Paint drop shadow for shadow in &self.style.shadows { scene.push_shadow(scene::Shadow { - bounds: margin_bounds + shadow.offset, + bounds: margined_bounds + shadow.offset, corner_radius: self.style.corner_radius, sigma: shadow.blur, color: shadow.color, @@ -451,7 +438,7 @@ impl Element for Node { // } // } - // Render the background and/or the border (if it not an overlay border). + // Render the background and/or the border. let Fill::Color(fill_color) = self.style.fill; let is_fill_visible = !fill_color.is_fully_transparent(); if is_fill_visible || self.style.borders.is_visible() { @@ -472,38 +459,25 @@ impl Element for Node { } if !self.children.is_empty() { - let padded_bounds = RectF::from_points( - margined_bounds.origin() + vec2f(layout.padding.left, layout.padding.top), - margined_bounds.lower_right() - vec2f(layout.padding.right, layout.padding.bottom), - ); - // Account for padding first. - let padding: Edges = todo!(); // &self.style.padding.to_pixels(rem_size); + let borders = &self.style.borders; let padded_bounds = RectF::from_points( - margined_bounds.origin() + vec2f(padding.left, padding.top), - margined_bounds.lower_right() - vec2f(padding.right, padding.top), + margined_bounds.origin() + + vec2f( + borders.left_width() + layout.padding.left, + borders.top_width() + layout.padding.top, + ), + margined_bounds.lower_right() + - vec2f( + layout.padding.right + borders.right_width(), + layout.padding.bottom + borders.bottom_width(), + ), ); - match self.style.axis { - Axis3d::X => self.paint_2d_children( - scene, - Axis2d::X, - padded_bounds, - visible_bounds, - layout, - view, - cx, - ), - Axis3d::Y => self.paint_2d_children( - scene, - Axis2d::Y, - padded_bounds, - visible_bounds, - layout, - view, - cx, - ), - Axis3d::Z => todo!(), + if let Some(axis) = self.style.axis.to_2d() { + self.paint_children_xy(scene, axis, padded_bounds, visible_bounds, layout, view, cx) + } else { + todo!(); } } } @@ -631,7 +605,7 @@ pub struct NodeStyle { text: OptionalTextStyle, opacity: f32, fill: Fill, - borders: Border, + borders: Borders, corner_radius: f32, shadows: Vec, } @@ -673,7 +647,7 @@ struct Size { height: T, } -impl Size { +impl Size { fn get(&self, axis: Axis2d) -> T { match axis { Axis2d::X => self.width, @@ -682,7 +656,7 @@ impl Size { } } -impl> Size> { +impl> Size> { fn add_assign_optional(&mut self, rhs: Size>) { self.width = optional_add(self.width, rhs.width); self.height = optional_add(self.height, rhs.height); @@ -843,7 +817,7 @@ impl Default for Fill { } #[derive(Clone, Default)] -struct Border { +struct Borders { color: Color, width: f32, top: bool, @@ -852,13 +826,45 @@ struct Border { right: bool, } -impl Border { +impl Borders { fn is_visible(&self) -> bool { self.width > 0. && !self.color.is_fully_transparent() && (self.top || self.bottom || self.left || self.right) } + fn top_width(&self) -> f32 { + if self.top { + self.width + } else { + 0. + } + } + + fn bottom_width(&self) -> f32 { + if self.bottom { + self.width + } else { + 0. + } + } + + fn left_width(&self) -> f32 { + if self.left { + self.width + } else { + 0. + } + } + + fn right_width(&self) -> f32 { + if self.right { + self.width + } else { + 0. + } + } + fn size(&self) -> Vector2F { let width = if self.left { self.width } else { 0. } + if self.right { self.width } else { 0. }; @@ -1078,7 +1084,7 @@ pub fn text(text: impl Into>) -> Node { } #[derive(Default)] -struct NodeLayout { +pub struct NodeLayout { content_size: Vector2F, margins: Edges, padding: Edges,