Added fold changes on gutter hover

Mikayla Maki created

Change summary

crates/editor/src/display_map.rs |  2 
crates/editor/src/editor.rs      | 38 +++++++++++++++++++++++++++------
crates/editor/src/element.rs     | 16 ++++++++++++-
crates/theme/src/theme.rs        |  1 
styles/src/styleTree/editor.ts   |  3 +
5 files changed, 49 insertions(+), 11 deletions(-)

Detailed changes

crates/editor/src/display_map.rs 🔗

@@ -24,7 +24,7 @@ pub use block_map::{
     BlockDisposition, BlockId, BlockProperties, BlockStyle, RenderBlock, TransformBlock,
 };
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub enum FoldStatus {
     Folded,
     Foldable,

crates/editor/src/editor.rs 🔗

@@ -171,6 +171,11 @@ pub struct UnfoldAt {
     pub display_row: DisplayRow,
 }
 
+#[derive(Clone, Default, Deserialize, PartialEq)]
+pub struct GutterHover {
+    pub hovered: bool,
+}
+
 actions!(
     editor,
     [
@@ -270,7 +275,8 @@ impl_actions!(
         ConfirmCodeAction,
         ToggleComments,
         FoldAt,
-        UnfoldAt
+        UnfoldAt,
+        GutterHover
     ]
 );
 
@@ -364,6 +370,7 @@ pub fn init(cx: &mut MutableAppContext) {
     cx.add_action(Editor::fold_at);
     cx.add_action(Editor::unfold_lines);
     cx.add_action(Editor::unfold_at);
+    cx.add_action(Editor::gutter_hover);
     cx.add_action(Editor::fold_selected_ranges);
     cx.add_action(Editor::show_completions);
     cx.add_action(Editor::toggle_code_actions);
@@ -495,6 +502,7 @@ pub struct Editor {
     leader_replica_id: Option<u16>,
     remote_id: Option<ViewId>,
     hover_state: HoverState,
+    gutter_hovered: bool,
     link_go_to_definition_state: LinkGoToDefinitionState,
     _subscriptions: Vec<Subscription>,
 }
@@ -1166,6 +1174,7 @@ impl Editor {
             remote_id: None,
             hover_state: Default::default(),
             link_go_to_definition_state: Default::default(),
+            gutter_hovered: false,
             _subscriptions: vec![
                 cx.observe(&buffer, Self::on_buffer_changed),
                 cx.subscribe(&buffer, Self::on_buffer_event),
@@ -2688,6 +2697,7 @@ impl Editor {
         &self,
         fold_data: Option<Vec<(u32, FoldStatus)>>,
         style: &EditorStyle,
+        gutter_hovered: bool,
         cx: &mut RenderContext<Self>,
     ) -> Option<Vec<(u32, ElementBox)>> {
         enum FoldIndicators {}
@@ -2695,26 +2705,31 @@ impl Editor {
         fold_data.map(|fold_data| {
             fold_data
                 .iter()
+                .copied()
                 .map(|(fold_location, fold_status)| {
                     (
-                        *fold_location,
+                        fold_location,
                         MouseEventHandler::<FoldIndicators>::new(
-                            *fold_location as usize,
+                            fold_location as usize,
                             cx,
                             |_, _| -> ElementBox {
-                                Svg::new(match *fold_status {
+                                Svg::new(match fold_status {
                                     FoldStatus::Folded => "icons/chevron_right_8.svg",
                                     FoldStatus::Foldable => "icons/chevron_down_8.svg",
                                 })
-                                .with_color(style.folds.indicator)
+                                .with_color(
+                                    if gutter_hovered || fold_status == FoldStatus::Folded {
+                                        style.folds.indicator
+                                    } else {
+                                        style.folds.faded_indicator
+                                    },
+                                )
                                 .boxed()
                             },
                         )
                         .with_cursor_style(CursorStyle::PointingHand)
                         .with_padding(Padding::uniform(3.))
                         .on_down(MouseButton::Left, {
-                            let fold_location = *fold_location;
-                            let fold_status = *fold_status;
                             move |_, cx| {
                                 cx.dispatch_any_action(match fold_status {
                                     FoldStatus::Folded => Box::new(UnfoldAt {
@@ -5838,6 +5853,15 @@ impl Editor {
         }
     }
 
+    pub fn gutter_hover(
+        &mut self,
+        GutterHover { hovered }: &GutterHover,
+        cx: &mut ViewContext<Self>,
+    ) {
+        self.gutter_hovered = *hovered;
+        cx.notify();
+    }
+
     pub fn insert_blocks(
         &mut self,
         blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,

crates/editor/src/element.rs 🔗

@@ -14,7 +14,7 @@ use crate::{
     },
     mouse_context_menu::DeployMouseContextMenu,
     scroll::actions::Scroll,
-    EditorStyle,
+    EditorStyle, GutterHover,
 };
 use clock::ReplicaId;
 use collections::{BTreeMap, HashMap};
@@ -213,6 +213,17 @@ impl EditorElement {
                     }
                 }),
         );
+
+        enum GutterHandlers {}
+        cx.scene.push_mouse_region(
+            MouseRegion::new::<GutterHandlers>(view.id(), view.id() + 1, gutter_bounds).on_hover(
+                |hover, cx| {
+                    cx.dispatch_action(GutterHover {
+                        hovered: hover.started,
+                    })
+                },
+            ),
+        )
     }
 
     fn mouse_down(
@@ -419,6 +430,7 @@ impl EditorElement {
         });
 
         cx.dispatch_action(HoverAt { point });
+
         true
     }
 
@@ -1815,7 +1827,7 @@ impl Element for EditorElement {
             hover = view.hover_state.render(&snapshot, &style, visible_rows, cx);
             mode = view.mode;
 
-            view.render_fold_indicators(folds, &style, cx)
+            view.render_fold_indicators(folds, &style, view.gutter_hovered, cx)
         });
 
         if let Some((_, context_menu)) = context_menu.as_mut() {

crates/theme/src/theme.rs 🔗

@@ -643,6 +643,7 @@ pub struct CodeActions {
 pub struct Folds {
     #[serde(default)]
     pub indicator: Color,
+    pub faded_indicator: Color,
     pub fold_background: Color,
 }
 

styles/src/styleTree/editor.ts 🔗

@@ -49,7 +49,8 @@ export default function editor(colorScheme: ColorScheme) {
         },
         folds: {
             indicator: foreground(layer, "variant"),
-            fold_background: foreground(layer, "variant"),
+            fadedIndicator: background(layer, "on"),
+            foldBackground: foreground(layer, "variant"),
         },
         diff: {
             deleted: foreground(layer, "negative"),