WIP

Nathan Sobo created

Change summary

crates/editor/src/editor.rs                    |  1 
crates/gpui/playground/ui/src/playground_ui.rs | 70 ++++++++++++++++++--
crates/gpui/src/elements.rs                    | 13 +++
crates/gpui/src/elements/node.rs               | 12 ++-
crates/language_tools/src/syntax_tree_view.rs  |  1 
crates/terminal_view/src/terminal_element.rs   |  1 
6 files changed, 86 insertions(+), 12 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -8305,6 +8305,7 @@ fn build_style(
                 font_size,
                 font_properties,
                 underline: Default::default(),
+                soft_wrap: false,
             },
             placeholder_text: None,
             line_height_scalar,

crates/gpui/playground/ui/src/playground_ui.rs 🔗

@@ -1,6 +1,6 @@
 use gpui::{
     elements::node::{column, length::auto, row, text},
-    AnyElement, Element, View, ViewContext,
+    AnyElement, Element, LayoutContext, View, ViewContext,
 };
 use std::{borrow::Cow, marker::PhantomData};
 use tokens::{margin::m4, text::lg};
@@ -58,22 +58,78 @@ impl<V: View, D: DialogDelegate<V>> Dialog<V, D> {
     }
 }
 
-struct Button<V: View, F: FnOnce(&mut V, &mut ViewContext<V>)> {
+#[derive(Element)]
+struct Button<V: View, D: 'static, H: ClickHandler<V, D>> {
     label: Cow<'static, str>,
-    on_click: Option<F>,
+    click_handler: Option<H>,
+    data: Option<D>,
     view_type: PhantomData<V>,
 }
 
-fn button<V: View, F: FnOnce(&mut V, &mut ViewContext<V>)>(
-    label: impl Into<Cow<'static, str>>,
-) -> Button<V, F> {
+pub trait ClickHandler<V, D>: 'static {
+    fn handle(&self, view: &mut V, data: &D, cx: &mut ViewContext<V>);
+}
+
+impl<V: View, M, F: 'static + Fn(&mut V, &M, &mut ViewContext<V>)> ClickHandler<V, M> for F {
+    fn handle(&self, view: &mut V, data: &M, cx: &mut ViewContext<V>) {
+        self(view, data, cx)
+    }
+}
+
+impl<V, D> ClickHandler<V, D> for () {
+    fn handle(&self, view: &mut V, data: &D, cx: &mut ViewContext<V>) {}
+}
+
+fn button<V>(label: impl Into<Cow<'static, str>>) -> Button<V, (), ()>
+where
+    V: View,
+{
     Button {
         label: label.into(),
-        on_click: None,
+        click_handler: None,
+        data: None,
         view_type: PhantomData,
     }
 }
 
+impl<V, D, F> Button<V, D, F>
+where
+    V: View,
+    F: ClickHandler<V, D>,
+{
+    fn render(&mut self, _: &mut V, _: &mut LayoutContext<V>) -> AnyElement<V> {
+        todo!()
+    }
+}
+
+impl<V: View> Button<V, (), ()> {
+    fn data<D>(self, data: D) -> Button<V, D, ()>
+    where
+        D: 'static + FnOnce(&mut V, &D, &mut ViewContext<V>),
+    {
+        Button {
+            label: self.label,
+            click_handler: self.click_handler,
+            data: Some(data),
+            view_type: self.view_type,
+        }
+    }
+}
+
+impl<V: View, D> Button<V, D, ()> {
+    fn click<H>(self, handler: H) -> Button<V, D, H>
+    where
+        H: 'static + Fn(&mut V, &D, &mut ViewContext<V>),
+    {
+        Button {
+            label: self.label,
+            click_handler: Some(handler),
+            data: self.data,
+            view_type: self.view_type,
+        }
+    }
+}
+
 impl<V: View, D: DialogDelegate<V>> Dialog<V, D> {
     pub fn render(&mut self, _: &mut V, _: &mut gpui::ViewContext<V>) -> AnyElement<V> {
         column()

crates/gpui/src/elements.rs 🔗

@@ -28,7 +28,11 @@ pub use self::{
 };
 pub use crate::window::ChildView;
 
-use self::{clipped::Clipped, expanded::Expanded};
+use self::{
+    clipped::Clipped,
+    expanded::Expanded,
+    node::{length::Length, node, Node},
+};
 use crate::{
     geometry::{
         rect::RectF,
@@ -200,6 +204,13 @@ pub trait Element<V: View>: 'static {
     {
         MouseEventHandler::for_child(self.into_any(), region_id)
     }
+
+    fn margin_left(self, margin_left: impl Into<Length>) -> Node<V>
+    where
+        Self: Sized,
+    {
+        node(self).margin_left(margin_left)
+    }
 }
 
 trait AnyElementState<V: View> {

crates/gpui/src/elements/node.rs 🔗

@@ -24,6 +24,10 @@ pub struct Node<V: View> {
     content: Vec<AnyElement<V>>,
 }
 
+pub fn node<V: View>(child: impl Element<V>) -> Node<V> {
+    Node::default().child(child)
+}
+
 pub fn column<V: View>() -> Node<V> {
     Node::default()
 }
@@ -119,13 +123,13 @@ impl<V: View> Node<V> {
         self
     }
 
-    pub fn margin_left(mut self, left: Length) -> Self {
-        self.style.margin.left = left;
+    pub fn margin_left(mut self, left: impl Into<Length>) -> Self {
+        self.style.margin.left = left.into();
         self
     }
 
-    pub fn margin_right(mut self, right: Length) -> Self {
-        self.style.margin.right = right;
+    pub fn margin_right(mut self, right: impl Into<Length>) -> Self {
+        self.style.margin.right = right.into();
         self
     }
 

crates/language_tools/src/syntax_tree_view.rs 🔗

@@ -373,6 +373,7 @@ impl View for SyntaxTreeView {
             font_size,
             font_properties: Default::default(),
             underline: Default::default(),
+            soft_wrap: false,
         };
 
         let line_height = cx.font_cache().line_height(font_size);

crates/terminal_view/src/terminal_element.rs 🔗

@@ -562,6 +562,7 @@ impl Element<TerminalView> for TerminalElement {
             font_size,
             font_properties: Default::default(),
             underline: Default::default(),
+            soft_wrap: false,
         };
         let selection_color = settings.theme.editor.selection.selection;
         let match_color = settings.theme.search.match_background;