@@ -88,6 +88,7 @@ pub use multi_buffer::{
};
use ordered_float::OrderedFloat;
use parking_lot::{Mutex, RwLock};
+use project::project_settings::{GitGutterSetting, ProjectSettings};
use project::{FormatTrigger, Location, Project, ProjectPath, ProjectTransaction};
use rand::prelude::*;
use rpc::proto::*;
@@ -443,7 +444,8 @@ pub struct EditorSnapshot {
}
pub struct GutterDimensions {
- pub padding: Pixels,
+ pub left_padding: Pixels,
+ pub right_padding: Pixels,
pub width: Pixels,
pub margin: Pixels,
}
@@ -451,7 +453,8 @@ pub struct GutterDimensions {
impl Default for GutterDimensions {
fn default() -> Self {
Self {
- padding: Pixels::ZERO,
+ left_padding: Pixels::ZERO,
+ right_padding: Pixels::ZERO,
width: Pixels::ZERO,
margin: Pixels::ZERO,
}
@@ -4058,7 +4061,8 @@ impl Editor {
if self.available_code_actions.is_some() {
Some(
IconButton::new("code_actions_indicator", ui::IconName::Bolt)
- .icon_size(IconSize::Small)
+ .icon_size(IconSize::XSmall)
+ .size(ui::ButtonSize::None)
.icon_color(Color::Muted)
.selected(is_active)
.on_click(cx.listener(|editor, _e, cx| {
@@ -9636,23 +9640,50 @@ impl EditorSnapshot {
max_line_number_width: Pixels,
cx: &AppContext,
) -> GutterDimensions {
- if self.show_gutter {
- let descent = cx.text_system().descent(font_id, font_size);
- let gutter_padding_factor = 4.0;
- let gutter_padding = (em_width * gutter_padding_factor).round();
+ if !self.show_gutter {
+ return GutterDimensions::default();
+ }
+ let descent = cx.text_system().descent(font_id, font_size);
+
+ let show_git_gutter = matches!(
+ ProjectSettings::get_global(cx).git.git_gutter,
+ Some(GitGutterSetting::TrackedFiles)
+ );
+ let gutter_settings = EditorSettings::get_global(cx).gutter;
+
+ let line_gutter_width = if gutter_settings.line_numbers {
// Avoid flicker-like gutter resizes when the line number gains another digit and only resize the gutter on files with N*10^5 lines.
let min_width_for_number_on_gutter = em_width * 4.0;
- let gutter_width =
- max_line_number_width.max(min_width_for_number_on_gutter) + gutter_padding * 2.0;
- let gutter_margin = -descent;
+ max_line_number_width.max(min_width_for_number_on_gutter)
+ } else {
+ 0.0.into()
+ };
- GutterDimensions {
- padding: gutter_padding,
- width: gutter_width,
- margin: gutter_margin,
- }
+ let left_padding = if gutter_settings.code_actions {
+ em_width * 3.0
+ } else if show_git_gutter && gutter_settings.line_numbers {
+ em_width * 2.0
+ } else if show_git_gutter || gutter_settings.line_numbers {
+ em_width
} else {
- GutterDimensions::default()
+ px(0.)
+ };
+
+ let right_padding = if gutter_settings.folds && gutter_settings.line_numbers {
+ em_width * 4.0
+ } else if gutter_settings.folds {
+ em_width * 3.0
+ } else if gutter_settings.line_numbers {
+ em_width
+ } else {
+ px(0.)
+ };
+
+ GutterDimensions {
+ left_padding,
+ right_padding,
+ width: line_gutter_width + left_padding + right_padding,
+ margin: -descent,
}
}
}
@@ -10159,9 +10190,14 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, _is_valid: bool) -> Ren
.group(group_id.clone())
.relative()
.size_full()
- .pl(cx.gutter_width)
- .w(cx.max_width + cx.gutter_width)
- .child(div().flex().w(cx.anchor_x - cx.gutter_width).flex_shrink())
+ .pl(cx.gutter_dimensions.width)
+ .w(cx.max_width + cx.gutter_dimensions.width)
+ .child(
+ div()
+ .flex()
+ .w(cx.anchor_x - cx.gutter_dimensions.width)
+ .flex_shrink(),
+ )
.child(div().flex().flex_shrink_0().child(
StyledText::new(text_without_backticks.clone()).with_highlights(
&text_style,
@@ -12,9 +12,9 @@ use crate::{
mouse_context_menu,
scroll::scroll_amount::ScrollAmount,
CursorShape, DisplayPoint, DocumentHighlightRead, DocumentHighlightWrite, Editor, EditorMode,
- EditorSettings, EditorSnapshot, EditorStyle, HalfPageDown, HalfPageUp, HoveredCursor, LineDown,
- LineUp, OpenExcerpts, PageDown, PageUp, Point, SelectPhase, Selection, SoftWrap, ToPoint,
- CURSORS_VISIBLE_FOR, MAX_LINE_LEN,
+ EditorSettings, EditorSnapshot, EditorStyle, GutterDimensions, HalfPageDown, HalfPageUp,
+ HoveredCursor, LineDown, LineUp, OpenExcerpts, PageDown, PageUp, Point, SelectPhase, Selection,
+ SoftWrap, ToPoint, CURSORS_VISIBLE_FOR, MAX_LINE_LEN,
};
use anyhow::Result;
use collections::{BTreeMap, HashMap};
@@ -716,20 +716,22 @@ impl EditorElement {
let scroll_position = layout.position_map.snapshot.scroll_position();
let scroll_top = scroll_position.y * line_height;
- let show_gutter = matches!(
+ let show_git_gutter = matches!(
ProjectSettings::get_global(cx).git.git_gutter,
Some(GitGutterSetting::TrackedFiles)
);
- if show_gutter {
+ if show_git_gutter {
Self::paint_diff_hunks(bounds, layout, cx);
}
+ let gutter_settings = EditorSettings::get_global(cx).gutter;
+
for (ix, line) in layout.line_numbers.iter().enumerate() {
if let Some(line) = line {
let line_origin = bounds.origin
+ point(
- bounds.size.width - line.width - layout.gutter_padding,
+ bounds.size.width - line.width - layout.gutter_dimensions.right_padding,
ix as f32 * line_height - (scroll_top % line_height),
);
@@ -740,6 +742,7 @@ impl EditorElement {
cx.with_z_index(1, |cx| {
for (ix, fold_indicator) in layout.fold_indicators.drain(..).enumerate() {
if let Some(fold_indicator) = fold_indicator {
+ debug_assert!(gutter_settings.folds);
let mut fold_indicator = fold_indicator.into_any_element();
let available_space = size(
AvailableSpace::MinContent,
@@ -748,11 +751,12 @@ impl EditorElement {
let fold_indicator_size = fold_indicator.measure(available_space, cx);
let position = point(
- bounds.size.width - layout.gutter_padding,
+ bounds.size.width - layout.gutter_dimensions.right_padding,
ix as f32 * line_height - (scroll_top % line_height),
);
let centering_offset = point(
- (layout.gutter_padding + layout.gutter_margin - fold_indicator_size.width)
+ (layout.gutter_dimensions.right_padding + layout.gutter_dimensions.margin
+ - fold_indicator_size.width)
/ 2.,
(line_height - fold_indicator_size.height) / 2.,
);
@@ -762,6 +766,7 @@ impl EditorElement {
}
if let Some(indicator) = layout.code_actions_indicator.take() {
+ debug_assert!(gutter_settings.code_actions);
let mut button = indicator.button.into_any_element();
let available_space = size(
AvailableSpace::MinContent,
@@ -772,7 +777,9 @@ impl EditorElement {
let mut x = Pixels::ZERO;
let mut y = indicator.row as f32 * line_height - scroll_top;
// Center indicator.
- x += ((layout.gutter_padding + layout.gutter_margin) - indicator_size.width) / 2.;
+ x += (layout.gutter_dimensions.margin + layout.gutter_dimensions.left_padding
+ - indicator_size.width)
+ / 2.;
y += (line_height - indicator_size.height) / 2.;
button.draw(bounds.origin + point(x, y), available_space, cx);
@@ -887,7 +894,8 @@ impl EditorElement {
cx: &mut ElementContext,
) {
let start_row = layout.visible_display_row_range.start;
- let content_origin = text_bounds.origin + point(layout.gutter_margin, Pixels::ZERO);
+ let content_origin =
+ text_bounds.origin + point(layout.gutter_dimensions.margin, Pixels::ZERO);
let line_end_overshoot = 0.15 * layout.position_map.line_height;
let whitespace_setting = self
.editor
@@ -1156,7 +1164,8 @@ impl EditorElement {
layout: &LayoutState,
cx: &mut ElementContext,
) {
- let content_origin = text_bounds.origin + point(layout.gutter_margin, Pixels::ZERO);
+ let content_origin =
+ text_bounds.origin + point(layout.gutter_dimensions.margin, Pixels::ZERO);
let line_end_overshoot = layout.line_end_overshoot();
// A softer than perfect black
@@ -1182,7 +1191,8 @@ impl EditorElement {
layout: &mut LayoutState,
cx: &mut ElementContext,
) {
- let content_origin = text_bounds.origin + point(layout.gutter_margin, Pixels::ZERO);
+ let content_origin =
+ text_bounds.origin + point(layout.gutter_dimensions.margin, Pixels::ZERO);
let start_row = layout.visible_display_row_range.start;
if let Some((position, mut context_menu)) = layout.context_menu.take() {
let available_space = size(AvailableSpace::MinContent, AvailableSpace::MinContent);
@@ -1819,7 +1829,10 @@ impl EditorElement {
Vec<Option<(FoldStatus, BufferRow, bool)>>,
) {
let font_size = self.style.text.font_size.to_pixels(cx.rem_size());
- let include_line_numbers = snapshot.mode == EditorMode::Full;
+ let include_line_numbers =
+ EditorSettings::get_global(cx).gutter.line_numbers && snapshot.mode == EditorMode::Full;
+ let include_fold_statuses =
+ EditorSettings::get_global(cx).gutter.folds && snapshot.mode == EditorMode::Full;
let mut shaped_line_numbers = Vec::with_capacity(rows.len());
let mut fold_statuses = Vec::with_capacity(rows.len());
let mut line_number = String::new();
@@ -1864,6 +1877,8 @@ impl EditorElement {
.shape_line(line_number.clone().into(), font_size, &[run])
.unwrap();
shaped_line_numbers.push(Some(shaped_line));
+ }
+ if include_fold_statuses {
fold_statuses.push(
is_singleton
.then(|| {
@@ -1960,7 +1975,13 @@ impl EditorElement {
.unwrap()
.width;
- let gutter_dimensions = snapshot.gutter_dimensions(font_id, font_size, em_width, self.max_line_number_width(&snapshot, cx), cx);
+ let gutter_dimensions = snapshot.gutter_dimensions(
+ font_id,
+ font_size,
+ em_width,
+ self.max_line_number_width(&snapshot, cx),
+ cx,
+ );
editor.gutter_width = gutter_dimensions.width;
@@ -2213,8 +2234,7 @@ impl EditorElement {
bounds.size.width,
scroll_width,
text_width,
- gutter_dimensions.padding,
- gutter_dimensions.width,
+ &gutter_dimensions,
em_width,
gutter_dimensions.width + gutter_dimensions.margin,
line_height,
@@ -2251,6 +2271,8 @@ impl EditorElement {
snapshot = editor.snapshot(cx);
}
+ let gutter_settings = EditorSettings::get_global(cx).gutter;
+
let mut context_menu = None;
let mut code_actions_indicator = None;
if let Some(newest_selection_head) = newest_selection_head {
@@ -2272,12 +2294,14 @@ impl EditorElement {
Some(crate::ContextMenu::CodeActions(_))
);
- code_actions_indicator = editor
- .render_code_actions_indicator(&style, active, cx)
- .map(|element| CodeActionsIndicator {
- row: newest_selection_head.row(),
- button: element,
- });
+ if gutter_settings.code_actions {
+ code_actions_indicator = editor
+ .render_code_actions_indicator(&style, active, cx)
+ .map(|element| CodeActionsIndicator {
+ row: newest_selection_head.row(),
+ button: element,
+ });
+ }
}
}
@@ -2295,29 +2319,32 @@ impl EditorElement {
None
} else {
editor.hover_state.render(
- &snapshot,
- &style,
- visible_rows,
- max_size,
- editor.workspace.as_ref().map(|(w, _)| w.clone()),
- cx,
- )
+ &snapshot,
+ &style,
+ visible_rows,
+ max_size,
+ editor.workspace.as_ref().map(|(w, _)| w.clone()),
+ cx,
+ )
};
let editor_view = cx.view().clone();
- let fold_indicators = cx.with_element_context(|cx| {
-
- cx.with_element_id(Some("gutter_fold_indicators"), |_cx| {
- editor.render_fold_indicators(
- fold_statuses,
- &style,
- editor.gutter_hovered,
- line_height,
- gutter_dimensions.margin,
- editor_view,
- )
- })
- });
+ let fold_indicators = if gutter_settings.folds {
+ cx.with_element_context(|cx| {
+ cx.with_element_id(Some("gutter_fold_indicators"), |_cx| {
+ editor.render_fold_indicators(
+ fold_statuses,
+ &style,
+ editor.gutter_hovered,
+ line_height,
+ gutter_dimensions.margin,
+ editor_view,
+ )
+ })
+ })
+ } else {
+ Vec::new()
+ };
let invisible_symbol_font_size = font_size / 2.;
let tab_invisible = cx
@@ -2370,13 +2397,12 @@ impl EditorElement {
visible_display_row_range: start_row..end_row,
wrap_guides,
gutter_size,
- gutter_padding: gutter_dimensions.padding,
+ gutter_dimensions,
text_size,
scrollbar_row_range,
show_scrollbars,
is_singleton,
max_row,
- gutter_margin: gutter_dimensions.margin,
active_rows,
highlighted_rows,
highlighted_ranges,
@@ -2403,8 +2429,7 @@ impl EditorElement {
editor_width: Pixels,
scroll_width: Pixels,
text_width: Pixels,
- gutter_padding: Pixels,
- gutter_width: Pixels,
+ gutter_dimensions: &GutterDimensions,
em_width: Pixels,
text_x: Pixels,
line_height: Pixels,
@@ -2447,9 +2472,8 @@ impl EditorElement {
block.render(&mut BlockContext {
context: cx,
anchor_x,
- gutter_padding,
+ gutter_dimensions,
line_height,
- gutter_width,
em_width,
block_id,
max_width: scroll_width.max(text_width),
@@ -2553,12 +2577,14 @@ impl EditorElement {
h_flex()
.id(("collapsed context", block_id))
.size_full()
- .gap(gutter_padding)
+ .gap(gutter_dimensions.left_padding + gutter_dimensions.right_padding)
.child(
h_flex()
.justify_end()
.flex_none()
- .w(gutter_width - gutter_padding)
+ .w(gutter_dimensions.width
+ - (gutter_dimensions.left_padding
+ + gutter_dimensions.right_padding))
.h_full()
.text_buffer(cx)
.text_color(cx.theme().colors().editor_line_number)
@@ -2619,7 +2645,7 @@ impl EditorElement {
BlockStyle::Sticky => editor_width,
BlockStyle::Flex => editor_width
.max(fixed_block_max_width)
- .max(gutter_width + scroll_width),
+ .max(gutter_dimensions.width + scroll_width),
BlockStyle::Fixed => unreachable!(),
};
let available_space = size(
@@ -2636,7 +2662,7 @@ impl EditorElement {
});
}
(
- scroll_width.max(fixed_block_max_width - gutter_width),
+ scroll_width.max(fixed_block_max_width - gutter_dimensions.width),
blocks,
)
}
@@ -3153,8 +3179,7 @@ type BufferRow = u32;
pub struct LayoutState {
position_map: Arc<PositionMap>,
gutter_size: Size<Pixels>,
- gutter_padding: Pixels,
- gutter_margin: Pixels,
+ gutter_dimensions: GutterDimensions,
text_size: gpui::Size<Pixels>,
mode: EditorMode,
wrap_guides: SmallVec<[(Pixels, bool); 2]>,