editor: Render dirty and conflict markers in multibuffer headers (#36489)

Lukas Wirth created

Release Notes:

- Added rendering of status indicators for multi buffer headers

Change summary

crates/editor/src/element.rs             | 19 +++++++++++++++----
crates/inspector_ui/src/div_inspector.rs | 12 ++++++------
2 files changed, 21 insertions(+), 10 deletions(-)

Detailed changes

crates/editor/src/element.rs 🔗

@@ -82,7 +82,7 @@ use sum_tree::Bias;
 use text::{BufferId, SelectionGoal};
 use theme::{ActiveTheme, Appearance, BufferLineHeight, PlayerColor};
 use ui::{
-    ButtonLike, ContextMenu, KeyBinding, POPOVER_Y_PADDING, Tooltip, h_flex, prelude::*,
+    ButtonLike, ContextMenu, Indicator, KeyBinding, POPOVER_Y_PADDING, Tooltip, h_flex, prelude::*,
     right_click_menu,
 };
 use unicode_segmentation::UnicodeSegmentation;
@@ -3563,9 +3563,8 @@ impl EditorElement {
         cx: &mut App,
     ) -> impl IntoElement {
         let editor = self.editor.read(cx);
-        let file_status = editor
-            .buffer
-            .read(cx)
+        let multi_buffer = editor.buffer.read(cx);
+        let file_status = multi_buffer
             .all_diff_hunks_expanded()
             .then(|| {
                 editor
@@ -3575,6 +3574,17 @@ impl EditorElement {
                     .status_for_buffer_id(for_excerpt.buffer_id, cx)
             })
             .flatten();
+        let indicator = multi_buffer
+            .buffer(for_excerpt.buffer_id)
+            .and_then(|buffer| {
+                let buffer = buffer.read(cx);
+                let indicator_color = match (buffer.has_conflict(), buffer.is_dirty()) {
+                    (true, _) => Some(Color::Warning),
+                    (_, true) => Some(Color::Accent),
+                    (false, false) => None,
+                };
+                indicator_color.map(|indicator_color| Indicator::dot().color(indicator_color))
+            });
 
         let include_root = editor
             .project
@@ -3683,6 +3693,7 @@ impl EditorElement {
                                 })
                                 .take(1),
                         )
+                        .children(indicator)
                         .child(
                             h_flex()
                                 .cursor_pointer()

crates/inspector_ui/src/div_inspector.rs 🔗

@@ -395,11 +395,11 @@ impl DivInspector {
             .zip(self.rust_completion_replace_range.as_ref())
         {
             let before_text = snapshot
-                .text_for_range(0..completion_range.start.to_offset(&snapshot))
+                .text_for_range(0..completion_range.start.to_offset(snapshot))
                 .collect::<String>();
             let after_text = snapshot
                 .text_for_range(
-                    completion_range.end.to_offset(&snapshot)
+                    completion_range.end.to_offset(snapshot)
                         ..snapshot.clip_offset(usize::MAX, Bias::Left),
                 )
                 .collect::<String>();
@@ -702,10 +702,10 @@ impl CompletionProvider for RustStyleCompletionProvider {
 }
 
 fn completion_replace_range(snapshot: &BufferSnapshot, anchor: &Anchor) -> Option<Range<Anchor>> {
-    let point = anchor.to_point(&snapshot);
-    let offset = point.to_offset(&snapshot);
-    let line_start = Point::new(point.row, 0).to_offset(&snapshot);
-    let line_end = Point::new(point.row, snapshot.line_len(point.row)).to_offset(&snapshot);
+    let point = anchor.to_point(snapshot);
+    let offset = point.to_offset(snapshot);
+    let line_start = Point::new(point.row, 0).to_offset(snapshot);
+    let line_end = Point::new(point.row, snapshot.line_len(point.row)).to_offset(snapshot);
     let mut lines = snapshot.text_for_range(line_start..line_end).lines();
     let line = lines.next()?;