Add a with_style method to Editor

Max Brunsfeld created

Change summary

zed/src/editor.rs         | 24 ++++++++++++++++++++----
zed/src/editor/element.rs | 15 +++++++--------
zed/src/theme.rs          | 21 +++++++++++++++++----
zed/src/workspace.rs      | 13 +++++++------
4 files changed, 51 insertions(+), 22 deletions(-)

Detailed changes

zed/src/editor.rs 🔗

@@ -4,7 +4,8 @@ mod element;
 pub mod movement;
 
 use crate::{
-    settings::{HighlightId, Settings, Theme},
+    settings::{HighlightId, Settings},
+    theme::{EditorStyle, Theme},
     time::ReplicaId,
     util::{post_inc, Bias},
     workspace,
@@ -287,6 +288,7 @@ pub struct Editor {
     scroll_position: Vector2F,
     scroll_top_anchor: Anchor,
     autoscroll_requested: bool,
+    build_style: Option<Box<dyn FnMut(&mut MutableAppContext) -> EditorStyle>>,
     settings: watch::Receiver<Settings>,
     focused: bool,
     cursors_visible: bool,
@@ -366,6 +368,7 @@ impl Editor {
             next_selection_id,
             add_selections_state: None,
             select_larger_syntax_node_stack: Vec::new(),
+            build_style: None,
             scroll_position: Vector2F::zero(),
             scroll_top_anchor: Anchor::min(),
             autoscroll_requested: false,
@@ -378,6 +381,14 @@ impl Editor {
         }
     }
 
+    pub fn with_style(
+        mut self,
+        f: impl 'static + FnMut(&mut MutableAppContext) -> EditorStyle,
+    ) -> Self {
+        self.build_style = Some(Box::new(f));
+        self
+    }
+
     pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
         self.buffer.read(cx).replica_id()
     }
@@ -2522,8 +2533,12 @@ impl Entity for Editor {
 }
 
 impl View for Editor {
-    fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
-        EditorElement::new(self.handle.clone()).boxed()
+    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
+        let style = self
+            .build_style
+            .as_mut()
+            .map_or(Default::default(), |build| build(cx));
+        EditorElement::new(self.handle.clone(), style).boxed()
     }
 
     fn ui_name() -> &'static str {
@@ -2563,7 +2578,8 @@ impl workspace::Item for Buffer {
         settings: watch::Receiver<Settings>,
         cx: &mut ViewContext<Self::View>,
     ) -> Self::View {
-        Editor::for_buffer(handle, settings, cx)
+        Editor::for_buffer(handle, settings.clone(), cx)
+            .with_style(move |_| settings.borrow().theme.editor.clone())
     }
 }
 

zed/src/editor/element.rs 🔗

@@ -1,5 +1,5 @@
 use super::{DisplayPoint, Editor, EditorMode, Insert, Scroll, Select, SelectPhase, Snapshot};
-use crate::time::ReplicaId;
+use crate::{theme::EditorStyle, time::ReplicaId};
 use gpui::{
     color::Color,
     geometry::{
@@ -22,11 +22,12 @@ use std::{
 
 pub struct EditorElement {
     view: WeakViewHandle<Editor>,
+    style: EditorStyle,
 }
 
 impl EditorElement {
-    pub fn new(view: WeakViewHandle<Editor>) -> Self {
-        Self { view }
+    pub fn new(view: WeakViewHandle<Editor>, style: EditorStyle) -> Self {
+        Self { view, style }
     }
 
     fn view<'a>(&self, cx: &'a AppContext) -> &'a Editor {
@@ -189,17 +190,15 @@ impl EditorElement {
         let bounds = gutter_bounds.union_rect(text_bounds);
         let scroll_top = layout.snapshot.scroll_position().y() * layout.line_height;
         let editor = self.view(cx.app);
-        let settings = editor.settings.borrow();
-        let theme = &settings.theme;
         cx.scene.push_quad(Quad {
             bounds: gutter_bounds,
-            background: Some(theme.editor.gutter_background),
+            background: Some(self.style.gutter_background),
             border: Border::new(0., Color::transparent_black()),
             corner_radius: 0.,
         });
         cx.scene.push_quad(Quad {
             bounds: text_bounds,
-            background: Some(theme.editor.background),
+            background: Some(self.style.background),
             border: Border::new(0., Color::transparent_black()),
             corner_radius: 0.,
         });
@@ -226,7 +225,7 @@ impl EditorElement {
                     );
                     cx.scene.push_quad(Quad {
                         bounds: RectF::new(origin, size),
-                        background: Some(theme.editor.active_line_background),
+                        background: Some(self.style.active_line_background),
                         border: Border::default(),
                         corner_radius: 0.,
                     });

zed/src/theme.rs 🔗

@@ -22,7 +22,7 @@ pub struct Theme {
     pub workspace: Workspace,
     pub chat_panel: ChatPanel,
     pub selector: Selector,
-    pub editor: Editor,
+    pub editor: EditorStyle,
     pub syntax: SyntaxTheme,
 }
 
@@ -127,8 +127,8 @@ pub struct ContainedLabel {
     pub label: LabelStyle,
 }
 
-#[derive(Deserialize)]
-pub struct Editor {
+#[derive(Clone, Deserialize)]
+pub struct EditorStyle {
     pub background: Color,
     pub gutter_background: Color,
     pub active_line_background: Color,
@@ -137,7 +137,7 @@ pub struct Editor {
     pub replicas: Vec<Replica>,
 }
 
-#[derive(Clone, Copy, Deserialize)]
+#[derive(Clone, Copy, Default, Deserialize)]
 pub struct Replica {
     pub cursor: Color,
     pub selection: Color,
@@ -164,6 +164,19 @@ impl SyntaxTheme {
     }
 }
 
+impl Default for EditorStyle {
+    fn default() -> Self {
+        Self {
+            background: Default::default(),
+            gutter_background: Default::default(),
+            active_line_background: Default::default(),
+            line_number: Default::default(),
+            line_number_active: Default::default(),
+            replicas: vec![Default::default()],
+        }
+    }
+}
+
 impl<'de> Deserialize<'de> for SyntaxTheme {
     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
     where

zed/src/workspace.rs 🔗

@@ -4,7 +4,7 @@ pub mod sidebar;
 
 use crate::{
     chat_panel::ChatPanel,
-    editor::{Buffer, Editor},
+    editor::Buffer,
     fs::Fs,
     language::LanguageRegistry,
     project_browser::ProjectBrowser,
@@ -565,11 +565,12 @@ impl Workspace {
 
     pub fn open_new_file(&mut self, _: &OpenNew, cx: &mut ViewContext<Self>) {
         let buffer = cx.add_model(|cx| Buffer::new(0, "", cx));
-        let buffer_view =
-            cx.add_view(|cx| Editor::for_buffer(buffer.clone(), self.settings.clone(), cx));
-        self.items.push(ItemHandle::downgrade(&buffer));
-        self.active_pane()
-            .add_item_view(Box::new(buffer_view), cx.as_mut());
+        let item_handle = ItemHandle::downgrade(&buffer);
+        let view = item_handle
+            .add_view(cx.window_id(), self.settings.clone(), cx)
+            .unwrap();
+        self.items.push(item_handle);
+        self.active_pane().add_item_view(view, cx.as_mut());
     }
 
     #[must_use]