commit view: Fix layout shift while loading commit (#44548)

Fixes a few cases where the commit view would layout shift as the diff
loaded. This was caused by:
- Adding the commit message buffer after all the diff files
- Using the gutter dimensions from the last frame for the avatar spacing

Release Notes:

- commit view: Fix layout shift while loading commit

---------

Co-authored-by: MrSubidubi <dev@bahn.sh>
This commit is contained in:
Agus Zubiaga
2025-12-10 15:01:49 +00:00
committed by GitHub
co-authored by MrSubidubi
parent dd431631b4
commit 21f7e6a9e6
10 changed files with 316 additions and 308 deletions
+190 -154
View File
@@ -108,7 +108,7 @@ use gpui::{
DispatchPhase, Edges, Entity, EntityInputHandler, EventEmitter, FocusHandle, FocusOutEvent,
Focusable, FontId, FontWeight, Global, HighlightStyle, Hsla, KeyContext, Modifiers,
MouseButton, MouseDownEvent, MouseMoveEvent, PaintQuad, ParentElement, Pixels, Render,
ScrollHandle, SharedString, Size, Stateful, Styled, Subscription, Task, TextStyle,
ScrollHandle, SharedString, Size, Stateful, Styled, Subscription, Task, TextRun, TextStyle,
TextStyleRefinement, UTF16Selection, UnderlineStyle, UniformListScrollHandle, WeakEntity,
WeakFocusHandle, Window, div, point, prelude::*, pulsating_between, px, relative, size,
};
@@ -575,7 +575,7 @@ impl Default for EditorStyle {
}
}
pub fn make_inlay_hints_style(cx: &mut App) -> HighlightStyle {
pub fn make_inlay_hints_style(cx: &App) -> HighlightStyle {
let show_background = language_settings::language_settings(None, None, cx)
.inlay_hints
.show_background;
@@ -598,7 +598,7 @@ pub fn make_inlay_hints_style(cx: &mut App) -> HighlightStyle {
style
}
pub fn make_suggestion_styles(cx: &mut App) -> EditPredictionStyles {
pub fn make_suggestion_styles(cx: &App) -> EditPredictionStyles {
EditPredictionStyles {
insertion: HighlightStyle {
color: Some(cx.theme().status().predictive),
@@ -1249,6 +1249,7 @@ impl NextScrollCursorCenterTopBottom {
pub struct EditorSnapshot {
pub mode: EditorMode,
show_gutter: bool,
offset_content: bool,
show_line_numbers: Option<bool>,
show_git_diff_gutter: Option<bool>,
show_code_actions: Option<bool>,
@@ -1825,7 +1826,11 @@ impl Editor {
Editor::new_internal(mode, buffer, project, None, window, cx)
}
pub fn sticky_headers(&self, cx: &App) -> Option<Vec<OutlineItem<Anchor>>> {
pub fn sticky_headers(
&self,
style: &EditorStyle,
cx: &App,
) -> Option<Vec<OutlineItem<Anchor>>> {
let multi_buffer = self.buffer().read(cx);
let multi_buffer_snapshot = multi_buffer.snapshot(cx);
let multi_buffer_visible_start = self
@@ -1843,7 +1848,7 @@ impl Editor {
.outline_items_containing(
Point::new(start_row, 0)..Point::new(end_row, 0),
true,
self.style().map(|style| style.syntax.as_ref()),
Some(style.syntax.as_ref()),
)
.into_iter()
.map(|outline_item| OutlineItem {
@@ -2935,6 +2940,7 @@ impl Editor {
EditorSnapshot {
mode: self.mode.clone(),
show_gutter: self.show_gutter,
offset_content: self.offset_content,
show_line_numbers: self.show_line_numbers,
show_git_diff_gutter: self.show_git_diff_gutter,
show_code_actions: self.show_code_actions,
@@ -6895,7 +6901,7 @@ impl Editor {
};
let anchor = self.selections.newest_anchor().head();
let position = self.to_pixel_point(anchor, &snapshot, window);
let position = self.to_pixel_point(anchor, &snapshot, window, cx);
if let (Some(position), Some(last_bounds)) = (position, self.last_bounds) {
self.show_blame_popover(
buffer,
@@ -9208,7 +9214,8 @@ impl Editor {
let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
let line_origin = self.display_to_pixel_point(target_line_end, editor_snapshot, window)?;
let line_origin =
self.display_to_pixel_point(target_line_end, editor_snapshot, window, cx)?;
let start_point = content_origin - point(scroll_pixel_position.x.into(), Pixels::ZERO);
let mut origin = start_point
@@ -9950,8 +9957,7 @@ impl Editor {
}
pub fn render_context_menu(
&self,
style: &EditorStyle,
&mut self,
max_height_in_lines: u32,
window: &mut Window,
cx: &mut Context<Editor>,
@@ -9961,7 +9967,9 @@ impl Editor {
if !menu.visible() {
return None;
};
Some(menu.render(style, max_height_in_lines, window, cx))
self.style
.as_ref()
.map(|style| menu.render(style, max_height_in_lines, window, cx))
}
fn render_context_menu_aside(
@@ -20364,8 +20372,11 @@ impl Editor {
self.style = Some(style);
}
pub fn style(&self) -> Option<&EditorStyle> {
self.style.as_ref()
pub fn style(&mut self, cx: &App) -> &EditorStyle {
if self.style.is_none() {
self.style = Some(self.create_style(cx));
}
self.style.as_ref().unwrap()
}
// Called by the element. This method is not designed to be called outside of the editor
@@ -22989,22 +23000,24 @@ impl Editor {
}
pub fn to_pixel_point(
&self,
&mut self,
source: multi_buffer::Anchor,
editor_snapshot: &EditorSnapshot,
window: &mut Window,
cx: &App,
) -> Option<gpui::Point<Pixels>> {
let source_point = source.to_display_point(editor_snapshot);
self.display_to_pixel_point(source_point, editor_snapshot, window)
self.display_to_pixel_point(source_point, editor_snapshot, window, cx)
}
pub fn display_to_pixel_point(
&self,
&mut self,
source: DisplayPoint,
editor_snapshot: &EditorSnapshot,
window: &mut Window,
cx: &App,
) -> Option<gpui::Point<Pixels>> {
let line_height = self.style()?.text.line_height_in_pixels(window.rem_size());
let line_height = self.style(cx).text.line_height_in_pixels(window.rem_size());
let text_layout_details = self.text_layout_details(window);
let scroll_top = text_layout_details
.scroll_anchor
@@ -23068,10 +23081,6 @@ impl Editor {
}
}
pub fn last_gutter_dimensions(&self) -> &GutterDimensions {
&self.gutter_dimensions
}
pub fn wait_for_diff_to_load(&self) -> Option<Shared<Task<()>>> {
self.load_diff_task.clone()
}
@@ -23171,6 +23180,57 @@ impl Editor {
// skip any LSP updates for it.
self.active_diagnostics == ActiveDiagnostic::All || !self.mode().is_full()
}
fn create_style(&self, cx: &App) -> EditorStyle {
let settings = ThemeSettings::get_global(cx);
let mut text_style = match self.mode {
EditorMode::SingleLine | EditorMode::AutoHeight { .. } => TextStyle {
color: cx.theme().colors().editor_foreground,
font_family: settings.ui_font.family.clone(),
font_features: settings.ui_font.features.clone(),
font_fallbacks: settings.ui_font.fallbacks.clone(),
font_size: rems(0.875).into(),
font_weight: settings.ui_font.weight,
line_height: relative(settings.buffer_line_height.value()),
..Default::default()
},
EditorMode::Full { .. } | EditorMode::Minimap { .. } => TextStyle {
color: cx.theme().colors().editor_foreground,
font_family: settings.buffer_font.family.clone(),
font_features: settings.buffer_font.features.clone(),
font_fallbacks: settings.buffer_font.fallbacks.clone(),
font_size: settings.buffer_font_size(cx).into(),
font_weight: settings.buffer_font.weight,
line_height: relative(settings.buffer_line_height.value()),
..Default::default()
},
};
if let Some(text_style_refinement) = &self.text_style_refinement {
text_style.refine(text_style_refinement)
}
let background = match self.mode {
EditorMode::SingleLine => cx.theme().system().transparent,
EditorMode::AutoHeight { .. } => cx.theme().system().transparent,
EditorMode::Full { .. } => cx.theme().colors().editor_background,
EditorMode::Minimap { .. } => cx.theme().colors().editor_background.opacity(0.7),
};
EditorStyle {
background,
border: cx.theme().colors().border,
local_player: cx.theme().players().local(),
text: text_style,
scrollbar_width: EditorElement::SCROLLBAR_WIDTH,
syntax: cx.theme().syntax().clone(),
status: cx.theme().status().clone(),
inlay_hints_style: make_inlay_hints_style(cx),
edit_prediction_styles: make_suggestion_styles(cx),
unnecessary_code_fade: settings.unnecessary_code_fade,
show_underlines: self.diagnostics_enabled(),
}
}
}
fn edit_for_markdown_paste<'a>(
@@ -24698,94 +24758,98 @@ impl EditorSnapshot {
self.scroll_anchor.scroll_position(&self.display_snapshot)
}
fn gutter_dimensions(
pub fn gutter_dimensions(
&self,
font_id: FontId,
font_size: Pixels,
max_line_number_width: Pixels,
style: &EditorStyle,
window: &mut Window,
cx: &App,
) -> Option<GutterDimensions> {
if !self.show_gutter {
return None;
) -> GutterDimensions {
if self.show_gutter
&& let Some(ch_width) = cx.text_system().ch_width(font_id, font_size).log_err()
&& let Some(ch_advance) = cx.text_system().ch_advance(font_id, font_size).log_err()
{
let show_git_gutter = self.show_git_diff_gutter.unwrap_or_else(|| {
matches!(
ProjectSettings::get_global(cx).git.git_gutter,
GitGutterSetting::TrackedFiles
)
});
let gutter_settings = EditorSettings::get_global(cx).gutter;
let show_line_numbers = self
.show_line_numbers
.unwrap_or(gutter_settings.line_numbers);
let line_gutter_width = if show_line_numbers {
// Avoid flicker-like gutter resizes when the line number gains another digit by
// only resizing the gutter on files with > 10**min_line_number_digits lines.
let min_width_for_number_on_gutter =
ch_advance * gutter_settings.min_line_number_digits as f32;
self.max_line_number_width(style, window)
.max(min_width_for_number_on_gutter)
} else {
0.0.into()
};
let show_runnables = self.show_runnables.unwrap_or(gutter_settings.runnables);
let show_breakpoints = self.show_breakpoints.unwrap_or(gutter_settings.breakpoints);
let git_blame_entries_width =
self.git_blame_gutter_max_author_length
.map(|max_author_length| {
let renderer = cx.global::<GlobalBlameRenderer>().0.clone();
const MAX_RELATIVE_TIMESTAMP: &str = "60 minutes ago";
/// The number of characters to dedicate to gaps and margins.
const SPACING_WIDTH: usize = 4;
let max_char_count = max_author_length.min(renderer.max_author_length())
+ ::git::SHORT_SHA_LENGTH
+ MAX_RELATIVE_TIMESTAMP.len()
+ SPACING_WIDTH;
ch_advance * max_char_count
});
let is_singleton = self.buffer_snapshot().is_singleton();
let mut left_padding = git_blame_entries_width.unwrap_or(Pixels::ZERO);
left_padding += if !is_singleton {
ch_width * 4.0
} else if show_runnables || show_breakpoints {
ch_width * 3.0
} else if show_git_gutter && show_line_numbers {
ch_width * 2.0
} else if show_git_gutter || show_line_numbers {
ch_width
} else {
px(0.)
};
let shows_folds = is_singleton && gutter_settings.folds;
let right_padding = if shows_folds && show_line_numbers {
ch_width * 4.0
} else if shows_folds || (!is_singleton && show_line_numbers) {
ch_width * 3.0
} else if show_line_numbers {
ch_width
} else {
px(0.)
};
GutterDimensions {
left_padding,
right_padding,
width: line_gutter_width + left_padding + right_padding,
margin: GutterDimensions::default_gutter_margin(font_id, font_size, cx),
git_blame_entries_width,
}
} else if self.offset_content {
GutterDimensions::default_with_margin(font_id, font_size, cx)
} else {
GutterDimensions::default()
}
let ch_width = cx.text_system().ch_width(font_id, font_size).log_err()?;
let ch_advance = cx.text_system().ch_advance(font_id, font_size).log_err()?;
let show_git_gutter = self.show_git_diff_gutter.unwrap_or_else(|| {
matches!(
ProjectSettings::get_global(cx).git.git_gutter,
GitGutterSetting::TrackedFiles
)
});
let gutter_settings = EditorSettings::get_global(cx).gutter;
let show_line_numbers = self
.show_line_numbers
.unwrap_or(gutter_settings.line_numbers);
let line_gutter_width = if show_line_numbers {
// Avoid flicker-like gutter resizes when the line number gains another digit by
// only resizing the gutter on files with > 10**min_line_number_digits lines.
let min_width_for_number_on_gutter =
ch_advance * gutter_settings.min_line_number_digits as f32;
max_line_number_width.max(min_width_for_number_on_gutter)
} else {
0.0.into()
};
let show_runnables = self.show_runnables.unwrap_or(gutter_settings.runnables);
let show_breakpoints = self.show_breakpoints.unwrap_or(gutter_settings.breakpoints);
let git_blame_entries_width =
self.git_blame_gutter_max_author_length
.map(|max_author_length| {
let renderer = cx.global::<GlobalBlameRenderer>().0.clone();
const MAX_RELATIVE_TIMESTAMP: &str = "60 minutes ago";
/// The number of characters to dedicate to gaps and margins.
const SPACING_WIDTH: usize = 4;
let max_char_count = max_author_length.min(renderer.max_author_length())
+ ::git::SHORT_SHA_LENGTH
+ MAX_RELATIVE_TIMESTAMP.len()
+ SPACING_WIDTH;
ch_advance * max_char_count
});
let is_singleton = self.buffer_snapshot().is_singleton();
let mut left_padding = git_blame_entries_width.unwrap_or(Pixels::ZERO);
left_padding += if !is_singleton {
ch_width * 4.0
} else if show_runnables || show_breakpoints {
ch_width * 3.0
} else if show_git_gutter && show_line_numbers {
ch_width * 2.0
} else if show_git_gutter || show_line_numbers {
ch_width
} else {
px(0.)
};
let shows_folds = is_singleton && gutter_settings.folds;
let right_padding = if shows_folds && show_line_numbers {
ch_width * 4.0
} else if shows_folds || (!is_singleton && show_line_numbers) {
ch_width * 3.0
} else if show_line_numbers {
ch_width
} else {
px(0.)
};
Some(GutterDimensions {
left_padding,
right_padding,
width: line_gutter_width + left_padding + right_padding,
margin: GutterDimensions::default_gutter_margin(font_id, font_size, cx),
git_blame_entries_width,
})
}
pub fn render_crease_toggle(
@@ -24868,6 +24932,28 @@ impl EditorSnapshot {
None
}
}
pub fn max_line_number_width(&self, style: &EditorStyle, window: &mut Window) -> Pixels {
let digit_count = self.widest_line_number().ilog10() + 1;
column_pixels(style, digit_count as usize, window)
}
}
pub fn column_pixels(style: &EditorStyle, column: usize, window: &Window) -> Pixels {
let font_size = style.text.font_size.to_pixels(window.rem_size());
let layout = window.text_system().shape_line(
SharedString::from(" ".repeat(column)),
font_size,
&[TextRun {
len: column,
font: style.text.font(),
color: Hsla::default(),
..Default::default()
}],
None,
);
layout.width
}
impl Deref for EditorSnapshot {
@@ -24948,57 +25034,7 @@ impl Focusable for Editor {
impl Render for Editor {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let settings = ThemeSettings::get_global(cx);
let mut text_style = match self.mode {
EditorMode::SingleLine | EditorMode::AutoHeight { .. } => TextStyle {
color: cx.theme().colors().editor_foreground,
font_family: settings.ui_font.family.clone(),
font_features: settings.ui_font.features.clone(),
font_fallbacks: settings.ui_font.fallbacks.clone(),
font_size: rems(0.875).into(),
font_weight: settings.ui_font.weight,
line_height: relative(settings.buffer_line_height.value()),
..Default::default()
},
EditorMode::Full { .. } | EditorMode::Minimap { .. } => TextStyle {
color: cx.theme().colors().editor_foreground,
font_family: settings.buffer_font.family.clone(),
font_features: settings.buffer_font.features.clone(),
font_fallbacks: settings.buffer_font.fallbacks.clone(),
font_size: settings.buffer_font_size(cx).into(),
font_weight: settings.buffer_font.weight,
line_height: relative(settings.buffer_line_height.value()),
..Default::default()
},
};
if let Some(text_style_refinement) = &self.text_style_refinement {
text_style.refine(text_style_refinement)
}
let background = match self.mode {
EditorMode::SingleLine => cx.theme().system().transparent,
EditorMode::AutoHeight { .. } => cx.theme().system().transparent,
EditorMode::Full { .. } => cx.theme().colors().editor_background,
EditorMode::Minimap { .. } => cx.theme().colors().editor_background.opacity(0.7),
};
EditorElement::new(
&cx.entity(),
EditorStyle {
background,
border: cx.theme().colors().border,
local_player: cx.theme().players().local(),
text: text_style,
scrollbar_width: EditorElement::SCROLLBAR_WIDTH,
syntax: cx.theme().syntax().clone(),
status: cx.theme().status().clone(),
inlay_hints_style: make_inlay_hints_style(cx),
edit_prediction_styles: make_suggestion_styles(cx),
unnecessary_code_fade: ThemeSettings::get_global(cx).unnecessary_code_fade,
show_underlines: self.diagnostics_enabled(),
},
)
EditorElement::new(&cx.entity(), self.create_style(cx))
}
}
+11 -15
View File
@@ -2218,10 +2218,9 @@ async fn test_move_start_of_paragraph_end_of_paragraph(cx: &mut TestAppContext)
init_test(cx, |_| {});
let mut cx = EditorTestContext::new(cx).await;
let line_height = cx.editor(|editor, window, _| {
let line_height = cx.update_editor(|editor, window, cx| {
editor
.style()
.unwrap()
.style(cx)
.text
.line_height_in_pixels(window.rem_size())
});
@@ -2334,10 +2333,9 @@ async fn test_move_start_of_paragraph_end_of_paragraph(cx: &mut TestAppContext)
async fn test_scroll_page_up_page_down(cx: &mut TestAppContext) {
init_test(cx, |_| {});
let mut cx = EditorTestContext::new(cx).await;
let line_height = cx.editor(|editor, window, _| {
let line_height = cx.update_editor(|editor, window, cx| {
editor
.style()
.unwrap()
.style(cx)
.text
.line_height_in_pixels(window.rem_size())
});
@@ -2400,8 +2398,7 @@ async fn test_autoscroll(cx: &mut TestAppContext) {
let line_height = cx.update_editor(|editor, window, cx| {
editor.set_vertical_scroll_margin(2, cx);
editor
.style()
.unwrap()
.style(cx)
.text
.line_height_in_pixels(window.rem_size())
});
@@ -2480,10 +2477,9 @@ async fn test_move_page_up_page_down(cx: &mut TestAppContext) {
init_test(cx, |_| {});
let mut cx = EditorTestContext::new(cx).await;
let line_height = cx.editor(|editor, window, _cx| {
let line_height = cx.update_editor(|editor, window, cx| {
editor
.style()
.unwrap()
.style(cx)
.text
.line_height_in_pixels(window.rem_size())
});
@@ -28311,7 +28307,8 @@ async fn test_sticky_scroll(cx: &mut TestAppContext) {
let mut sticky_headers = |offset: ScrollOffset| {
cx.update_editor(|e, window, cx| {
e.scroll(gpui::Point { x: 0., y: offset }, None, window, cx);
EditorElement::sticky_headers(&e, &e.snapshot(window, cx), cx)
let style = e.style(cx).clone();
EditorElement::sticky_headers(&e, &e.snapshot(window, cx), &style, cx)
.into_iter()
.map(
|StickyHeader {
@@ -28365,10 +28362,9 @@ async fn test_scroll_by_clicking_sticky_header(cx: &mut TestAppContext) {
});
let mut cx = EditorTestContext::new(cx).await;
let line_height = cx.editor(|editor, window, _cx| {
let line_height = cx.update_editor(|editor, window, cx| {
editor
.style()
.unwrap()
.style(cx)
.text
.line_height_in_pixels(window.rem_size())
});
+29 -59
View File
@@ -11,6 +11,7 @@ use crate::{
SelectedTextHighlight, Selection, SelectionDragState, SelectionEffects, SizingBehavior,
SoftWrap, StickyHeaderExcerpt, ToPoint, ToggleFold, ToggleFoldAll,
code_context_menus::{CodeActionsMenu, MENU_ASIDE_MAX_WIDTH, MENU_ASIDE_MIN_WIDTH, MENU_GAP},
column_pixels,
display_map::{
Block, BlockContext, BlockStyle, ChunkRendererId, DisplaySnapshot, EditorMargins,
HighlightKey, HighlightedChunk, ToDisplayPoint,
@@ -2269,7 +2270,8 @@ impl EditorElement {
};
let padding = ProjectSettings::get_global(cx).diagnostics.inline.padding as f32 * em_width;
let min_x = self.column_pixels(
let min_x = column_pixels(
&self.style,
ProjectSettings::get_global(cx)
.diagnostics
.inline
@@ -2572,7 +2574,8 @@ impl EditorElement {
let padded_line_end = line_end + padding;
let min_column_in_pixels = self.column_pixels(
let min_column_in_pixels = column_pixels(
&self.style,
ProjectSettings::get_global(cx).git.inline_blame.min_column as usize,
window,
);
@@ -2796,7 +2799,7 @@ impl EditorElement {
.enumerate()
.filter_map(|(i, indent_guide)| {
let single_indent_width =
self.column_pixels(indent_guide.tab_size as usize, window);
column_pixels(&self.style, indent_guide.tab_size as usize, window);
let total_width = single_indent_width * indent_guide.depth as f32;
let start_x = Pixels::from(
ScrollOffset::from(content_origin.x + total_width)
@@ -2853,7 +2856,7 @@ impl EditorElement {
.wrap_guides(cx)
.into_iter()
.flat_map(|(guide, active)| {
let wrap_position = self.column_pixels(guide, window);
let wrap_position = column_pixels(&self.style, guide, window);
let wrap_guide_x = wrap_position + horizontal_offset;
let display_wrap_guide = wrap_guide_x >= content_origin
&& wrap_guide_x <= hitbox.bounds.right() - vertical_scrollbar_width;
@@ -4619,6 +4622,7 @@ impl EditorElement {
gutter_dimensions: &GutterDimensions,
gutter_hitbox: &Hitbox,
text_hitbox: &Hitbox,
style: &EditorStyle,
window: &mut Window,
cx: &mut App,
) -> Option<StickyHeaders> {
@@ -4626,7 +4630,7 @@ impl EditorElement {
.show_line_numbers
.unwrap_or_else(|| EditorSettings::get_global(cx).gutter.line_numbers);
let rows = Self::sticky_headers(self.editor.read(cx), snapshot, cx);
let rows = Self::sticky_headers(self.editor.read(cx), snapshot, style, cx);
let mut lines = Vec::<StickyHeaderLine>::new();
@@ -4685,6 +4689,7 @@ impl EditorElement {
pub(crate) fn sticky_headers(
editor: &Editor,
snapshot: &EditorSnapshot,
style: &EditorStyle,
cx: &App,
) -> Vec<StickyHeader> {
let scroll_top = snapshot.scroll_position().y;
@@ -4692,7 +4697,7 @@ impl EditorElement {
let mut end_rows = Vec::<DisplayRow>::new();
let mut rows = Vec::<StickyHeader>::new();
let items = editor.sticky_headers(cx).unwrap_or_default();
let items = editor.sticky_headers(style, cx).unwrap_or_default();
for item in items {
let start_point = item.range.start.to_point(snapshot.buffer_snapshot());
@@ -5255,7 +5260,7 @@ impl EditorElement {
) -> Option<AnyElement> {
let max_height_in_lines = ((height - POPOVER_Y_PADDING) / line_height).floor() as u32;
self.editor.update(cx, |editor, cx| {
editor.render_context_menu(&self.style, max_height_in_lines, window, cx)
editor.render_context_menu(max_height_in_lines, window, cx)
})
}
@@ -5282,16 +5287,18 @@ impl EditorElement {
window: &mut Window,
cx: &mut App,
) -> Option<AnyElement> {
let position = self.editor.update(cx, |editor, _cx| {
let position = self.editor.update(cx, |editor, cx| {
let visible_start_point = editor.display_to_pixel_point(
DisplayPoint::new(visible_range.start, 0),
editor_snapshot,
window,
cx,
)?;
let visible_end_point = editor.display_to_pixel_point(
DisplayPoint::new(visible_range.end, 0),
editor_snapshot,
window,
cx,
)?;
let mouse_context_menu = editor.mouse_context_menu.as_ref()?;
@@ -5299,7 +5306,8 @@ impl EditorElement {
MenuPosition::PinnedToScreen(point) => (None, point),
MenuPosition::PinnedToEditor { source, offset } => {
let source_display_point = source.to_display_point(editor_snapshot);
let source_point = editor.to_pixel_point(source, editor_snapshot, window)?;
let source_point =
editor.to_pixel_point(source, editor_snapshot, window, cx)?;
let position = content_origin + source_point + offset;
(Some(source_display_point), position)
}
@@ -7773,29 +7781,6 @@ impl EditorElement {
});
}
fn column_pixels(&self, column: usize, window: &Window) -> Pixels {
let style = &self.style;
let font_size = style.text.font_size.to_pixels(window.rem_size());
let layout = window.text_system().shape_line(
SharedString::from(" ".repeat(column)),
font_size,
&[TextRun {
len: column,
font: style.text.font(),
color: Hsla::default(),
..Default::default()
}],
None,
);
layout.width
}
fn max_line_number_width(&self, snapshot: &EditorSnapshot, window: &mut Window) -> Pixels {
let digit_count = snapshot.widest_line_number().ilog10() + 1;
self.column_pixels(digit_count as usize, window)
}
fn shape_line_number(
&self,
text: SharedString,
@@ -8943,8 +8928,6 @@ impl Element for EditorElement {
max_lines,
} => {
let editor_handle = cx.entity();
let max_line_number_width =
self.max_line_number_width(&editor.snapshot(window, cx), window);
window.request_measured_layout(
Style::default(),
move |known_dimensions, available_space, window, cx| {
@@ -8954,7 +8937,6 @@ impl Element for EditorElement {
editor,
min_lines,
max_lines,
max_line_number_width,
known_dimensions,
available_space.width,
window,
@@ -9041,15 +9023,10 @@ impl Element for EditorElement {
.gutter_dimensions(
font_id,
font_size,
self.max_line_number_width(&snapshot, window),
style,
window,
cx,
)
.or_else(|| {
self.editor.read(cx).offset_content.then(|| {
GutterDimensions::default_with_margin(font_id, font_size, cx)
})
})
.unwrap_or_default();
);
let text_width = bounds.size.width - gutter_dimensions.width;
let settings = EditorSettings::get_global(cx);
@@ -9740,6 +9717,7 @@ impl Element for EditorElement {
&gutter_dimensions,
&gutter_hitbox,
&text_hitbox,
&style,
window,
cx,
)
@@ -11456,7 +11434,6 @@ fn compute_auto_height_layout(
editor: &mut Editor,
min_lines: usize,
max_lines: Option<usize>,
max_line_number_width: Pixels,
known_dimensions: Size<Option<Pixels>>,
available_width: AvailableSpace,
window: &mut Window,
@@ -11480,14 +11457,7 @@ fn compute_auto_height_layout(
let em_width = window.text_system().em_width(font_id, font_size).unwrap();
let mut snapshot = editor.snapshot(window, cx);
let gutter_dimensions = snapshot
.gutter_dimensions(font_id, font_size, max_line_number_width, cx)
.or_else(|| {
editor
.offset_content
.then(|| GutterDimensions::default_with_margin(font_id, font_size, cx))
})
.unwrap_or_default();
let gutter_dimensions = snapshot.gutter_dimensions(font_id, font_size, style, window, cx);
editor.gutter_dimensions = gutter_dimensions;
let text_width = width - gutter_dimensions.width;
@@ -11550,7 +11520,7 @@ mod tests {
});
let cx = &mut VisualTestContext::from_window(*window, cx);
let editor = window.root(cx).unwrap();
let style = cx.update(|_, cx| editor.read(cx).style().unwrap().clone());
let style = cx.update(|_, cx| editor.update(cx, |editor, cx| editor.style(cx).clone()));
for x in 1..=100 {
let (_, state) = cx.draw(
@@ -11578,7 +11548,7 @@ mod tests {
});
let cx = &mut VisualTestContext::from_window(*window, cx);
let editor = window.root(cx).unwrap();
let style = cx.update(|_, cx| editor.read(cx).style().unwrap().clone());
let style = cx.update(|_, cx| editor.update(cx, |editor, cx| editor.style(cx).clone()));
for x in 1..=100 {
let (_, state) = cx.draw(
@@ -11603,7 +11573,7 @@ mod tests {
});
let editor = window.root(cx).unwrap();
let style = cx.update(|cx| editor.read(cx).style().unwrap().clone());
let style = editor.update(cx, |editor, cx| editor.style(cx).clone());
let line_height = window
.update(cx, |_, window, _| {
style.text.line_height_in_pixels(window.rem_size())
@@ -11751,7 +11721,7 @@ mod tests {
});
let editor = window.root(cx).unwrap();
let style = cx.update(|cx| editor.read(cx).style().unwrap().clone());
let style = editor.update(cx, |editor, cx| editor.style(cx).clone());
let line_height = window
.update(cx, |_, window, _| {
style.text.line_height_in_pixels(window.rem_size())
@@ -11878,7 +11848,7 @@ mod tests {
});
let cx = &mut VisualTestContext::from_window(*window, cx);
let editor = window.root(cx).unwrap();
let style = cx.update(|_, cx| editor.read(cx).style().unwrap().clone());
let style = cx.update(|_, cx| editor.update(cx, |editor, cx| editor.style(cx).clone()));
window
.update(cx, |editor, window, cx| {
@@ -11949,7 +11919,7 @@ mod tests {
});
let cx = &mut VisualTestContext::from_window(*window, cx);
let editor = window.root(cx).unwrap();
let style = cx.update(|_, cx| editor.read(cx).style().unwrap().clone());
let style = cx.update(|_, cx| editor.update(cx, |editor, cx| editor.style(cx).clone()));
window
.update(cx, |editor, window, cx| {
editor.set_placeholder_text("hello", window, cx);
@@ -12189,7 +12159,7 @@ mod tests {
let cx = &mut VisualTestContext::from_window(*window, cx);
let editor = window.root(cx).unwrap();
let style = cx.update(|_, cx| editor.read(cx).style().unwrap().clone());
let style = editor.update(cx, |editor, cx| editor.style(cx).clone());
window
.update(cx, |editor, _, cx| {
editor.set_soft_wrap_mode(language_settings::SoftWrap::EditorWidth, cx);
+1 -1
View File
@@ -59,7 +59,7 @@ impl MouseContextMenu {
x: editor.gutter_dimensions.width,
y: Pixels::ZERO,
};
let source_position = editor.to_pixel_point(source, &editor_snapshot, window)?;
let source_position = editor.to_pixel_point(source, &editor_snapshot, window, cx)?;
let menu_position = MenuPosition::PinnedToEditor {
source,
offset: position - (source_position + content_origin),
@@ -283,8 +283,7 @@ impl EditorTestContext {
.head();
let pixel_position = editor.pixel_position_of_newest_cursor.unwrap();
let line_height = editor
.style()
.unwrap()
.style(cx)
.text
.line_height_in_pixels(window.rem_size());
let snapshot = editor.snapshot(window, cx);