From 712d47d94fe065ef0be4e5100279e7ee099deb9c Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 8 Jun 2022 15:31:29 +0200 Subject: [PATCH] Render a "Jump to Buffer" icon on all excerpt headers --- crates/diagnostics/src/diagnostics.rs | 64 ++------------------ crates/editor/src/display_map/block_map.rs | 2 + crates/editor/src/editor.rs | 4 ++ crates/editor/src/element.rs | 68 ++++++++++++++++++++-- crates/language/src/buffer.rs | 4 +- crates/theme/src/theme.rs | 2 +- styles/src/styleTree/editor.ts | 16 ++--- 7 files changed, 86 insertions(+), 74 deletions(-) diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index a2f16fa0c4..c7d97c1ef3 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -9,13 +9,13 @@ use editor::{ ToOffset, }; use gpui::{ - actions, elements::*, fonts::TextStyle, impl_internal_actions, platform::CursorStyle, - serde_json, AnyViewHandle, AppContext, Entity, ModelHandle, MutableAppContext, RenderContext, - Task, View, ViewContext, ViewHandle, WeakViewHandle, + actions, elements::*, fonts::TextStyle, impl_internal_actions, serde_json, AnyViewHandle, + AppContext, Entity, ModelHandle, MutableAppContext, RenderContext, Task, View, ViewContext, + ViewHandle, WeakViewHandle, }; use language::{ Anchor, Bias, Buffer, Diagnostic, DiagnosticEntry, DiagnosticSeverity, Point, Selection, - SelectionGoal, ToPoint, + SelectionGoal, }; use project::{DiagnosticSummary, Project, ProjectPath}; use serde_json::json; @@ -342,20 +342,13 @@ impl ProjectDiagnosticsEditor { is_first_excerpt_for_group = false; let mut primary = group.entries[group.primary_ix].diagnostic.clone(); - let anchor = group.entries[group.primary_ix].range.start; - let position = anchor.to_point(&snapshot); primary.message = primary.message.split('\n').next().unwrap().to_string(); group_state.block_count += 1; blocks_to_add.push(BlockProperties { position: header_position, height: 2, - render: diagnostic_header_renderer( - primary, - path.clone(), - position, - anchor, - ), + render: diagnostic_header_renderer(primary), disposition: BlockDisposition::Above, }); } @@ -612,18 +605,10 @@ impl workspace::Item for ProjectDiagnosticsEditor { } } -fn diagnostic_header_renderer( - diagnostic: Diagnostic, - path: ProjectPath, - position: Point, - anchor: Anchor, -) -> RenderBlock { - enum JumpIcon {} - +fn diagnostic_header_renderer(diagnostic: Diagnostic) -> RenderBlock { let (message, highlights) = highlight_diagnostic_message(&diagnostic.message); Arc::new(move |cx| { let settings = cx.global::(); - let tooltip_style = settings.theme.tooltip.clone(); let theme = &settings.theme.editor; let style = theme.diagnostic_header.clone(); let font_size = (style.text_scale_factor * settings.buffer_font_size).round(); @@ -664,43 +649,6 @@ fn diagnostic_header_renderer( .aligned() .boxed() })) - .with_child( - MouseEventHandler::new::(diagnostic.group_id, cx, |state, _| { - let style = style.jump_icon.style_for(state, false); - Svg::new("icons/jump.svg") - .with_color(style.color) - .constrained() - .with_width(style.icon_width) - .aligned() - .contained() - .with_style(style.container) - .constrained() - .with_width(style.button_width) - .with_height(style.button_width) - .boxed() - }) - .with_cursor_style(CursorStyle::PointingHand) - .on_click({ - let path = path.clone(); - move |_, _, cx| { - cx.dispatch_action(Jump { - path: path.clone(), - position, - anchor, - }); - } - }) - .with_tooltip( - diagnostic.group_id, - "Jump to diagnostic".to_string(), - Some(Box::new(editor::OpenExcerpts)), - tooltip_style, - cx, - ) - .aligned() - .flex_float() - .boxed(), - ) .contained() .with_style(style.container) .with_padding_left(x_padding) diff --git a/crates/editor/src/display_map/block_map.rs b/crates/editor/src/display_map/block_map.rs index 43b28974a9..36abef60e5 100644 --- a/crates/editor/src/display_map/block_map.rs +++ b/crates/editor/src/display_map/block_map.rs @@ -97,6 +97,7 @@ struct Transform { pub enum TransformBlock { Custom(Arc), ExcerptHeader { + key: usize, buffer: BufferSnapshot, range: ExcerptRange, height: u8, @@ -359,6 +360,7 @@ impl BlockMap { .from_point(Point::new(excerpt_boundary.row, 0), Bias::Left) .row(), TransformBlock::ExcerptHeader { + key: excerpt_boundary.key, buffer: excerpt_boundary.buffer, range: excerpt_boundary.range, height: if excerpt_boundary.starts_new_buffer { diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 6e1b146bad..8cd2e8a96d 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -5849,9 +5849,13 @@ impl Editor { } else { buffer.clip_point(position, Bias::Left) }; + + let nav_history = editor.nav_history.take(); editor.change_selections(Some(Autoscroll::Newest), cx, |s| { s.select_ranges([cursor..cursor]); }); + editor.nav_history = nav_history; + Some(()) })?; Some(()) diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index f3ecc6e773..d73569a03f 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -27,6 +27,7 @@ use gpui::{ }; use json::json; use language::{Bias, DiagnosticSeverity, Selection}; +use project::ProjectPath; use settings::Settings; use smallvec::SmallVec; use std::{ @@ -795,6 +796,7 @@ impl EditorElement { return Default::default(); }; + let tooltip_style = cx.global::().theme.tooltip.clone(); let scroll_x = snapshot.scroll_position.x(); snapshot .blocks_in_range(rows.clone()) @@ -827,10 +829,60 @@ impl EditorElement { }) } TransformBlock::ExcerptHeader { + key, buffer, + range, starts_new_buffer, .. } => { + let jump_icon = project::File::from_dyn(buffer.file()).map(|file| { + let jump_position = range + .primary + .as_ref() + .map_or(range.context.start, |primary| primary.start); + let jump_action = crate::Jump { + path: ProjectPath { + worktree_id: file.worktree_id(cx), + path: file.path.clone(), + }, + position: language::ToPoint::to_point(&jump_position, buffer), + anchor: jump_position, + }; + + enum JumpIcon {} + cx.render(&editor, |_, cx| { + MouseEventHandler::new::(*key, cx, |state, _| { + let style = style.jump_icon.style_for(state, false); + Svg::new("icons/jump.svg") + .with_color(style.color) + .constrained() + .with_width(style.icon_width) + .aligned() + .contained() + .with_style(style.container) + .constrained() + .with_width(style.button_width) + .with_height(style.button_width) + .boxed() + }) + .with_cursor_style(CursorStyle::PointingHand) + .on_click({ + move |_, _, cx| cx.dispatch_action(jump_action.clone()) + }) + .with_tooltip( + *key, + "Jump to Buffer".to_string(), + Some(Box::new(crate::OpenExcerpts)), + tooltip_style.clone(), + cx, + ) + .aligned() + .flex_float() + .boxed() + }) + }); + + let padding = gutter_padding + scroll_x * em_width; if *starts_new_buffer { let style = &self.style.diagnostic_path_header; let font_size = @@ -854,6 +906,7 @@ impl EditorElement { ) .contained() .with_style(style.filename.container) + .aligned() .boxed(), ) .with_children(parent_path.map(|path| { @@ -863,20 +916,25 @@ impl EditorElement { ) .contained() .with_style(style.path.container) + .aligned() .boxed() })) - .aligned() - .left() + .with_children(jump_icon) .contained() .with_style(style.container) - .with_padding_left(gutter_padding + scroll_x * em_width) + .with_padding_left(padding) + .with_padding_right(padding) .expanded() .named("path header block") } else { let text_style = self.style.text.clone(); - Label::new("…".to_string(), text_style) + Flex::row() + .with_child(Label::new("…".to_string(), text_style).boxed()) + .with_children(jump_icon) .contained() - .with_padding_left(gutter_padding + scroll_x * em_width) + .with_padding_left(padding) + .with_padding_right(padding) + .expanded() .named("collapsed context") } } diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index de7425b76b..425bff2242 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -1980,8 +1980,8 @@ impl BufferSnapshot { self.selections_update_count } - pub fn file(&self) -> Option<&Arc> { - self.file.as_ref() + pub fn file(&self) -> Option<&dyn File> { + self.file.as_deref() } pub fn file_update_count(&self) -> usize { diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 8e282100d4..80e9a8619f 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -454,6 +454,7 @@ pub struct Editor { pub code_actions_indicator: Color, pub unnecessary_code_fade: f32, pub hover_popover: HoverPopover, + pub jump_icon: Interactive, } #[derive(Clone, Deserialize, Default)] @@ -473,7 +474,6 @@ pub struct DiagnosticHeader { pub code: ContainedText, pub text_scale_factor: f32, pub icon_width_factor: f32, - pub jump_icon: Interactive, } #[derive(Clone, Deserialize, Default)] diff --git a/styles/src/styleTree/editor.ts b/styles/src/styleTree/editor.ts index 14e7f9449f..9637e969d1 100644 --- a/styles/src/styleTree/editor.ts +++ b/styles/src/styleTree/editor.ts @@ -101,14 +101,6 @@ export default function editor(theme: Theme) { background: backgroundColor(theme, 300), iconWidthFactor: 1.5, textScaleFactor: 0.857, // NateQ: Will we need dynamic sizing for text? If so let's create tokens for these. - jumpIcon: { - color: iconColor(theme, "primary"), - iconWidth: 10, - buttonWidth: 10, - hover: { - color: iconColor(theme, "active") - } - }, border: border(theme, "secondary", { bottom: true, top: true, @@ -147,6 +139,14 @@ export default function editor(theme: Theme) { invalidInformationDiagnostic: diagnostic(theme, "muted"), invalidWarningDiagnostic: diagnostic(theme, "muted"), hover_popover: hoverPopover(theme), + jumpIcon: { + color: iconColor(theme, "primary"), + iconWidth: 10, + buttonWidth: 10, + hover: { + color: iconColor(theme, "active") + } + }, syntax, }; }