Fix active line number highlight (#23266)

Closes #22734

Release Notes:

- Fixed active line number highlight.

---------

Co-authored-by: Danilo <danilo@zed.dev>
This commit is contained in:
João Marcos 2025-01-16 22:23:28 -03:00 committed by GitHub
parent b472bd992f
commit 7ee78a4d35
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 51 additions and 36 deletions

View file

@ -510,7 +510,7 @@ impl EditorElement {
position_map: &PositionMap, position_map: &PositionMap,
text_hitbox: &Hitbox, text_hitbox: &Hitbox,
gutter_hitbox: &Hitbox, gutter_hitbox: &Hitbox,
line_numbers: &HashMap<MultiBufferRow, (ShapedLine, Option<Hitbox>)>, line_numbers: &HashMap<MultiBufferRow, LineNumberLayout>,
cx: &mut ViewContext<Editor>, cx: &mut ViewContext<Editor>,
) { ) {
if cx.default_prevented() { if cx.default_prevented() {
@ -618,8 +618,11 @@ impl EditorElement {
.snapshot .snapshot
.display_point_to_point(DisplayPoint::new(DisplayRow(display_row), 0), Bias::Right) .display_point_to_point(DisplayPoint::new(DisplayRow(display_row), 0), Bias::Right)
.row; .row;
if let Some((_, Some(hitbox))) = line_numbers.get(&MultiBufferRow(multi_buffer_row)) { if line_numbers
if hitbox.contains(&event.position) { .get(&MultiBufferRow(multi_buffer_row))
.and_then(|line_number| line_number.hitbox.as_ref())
.is_some_and(|hitbox| hitbox.contains(&event.position))
{
let scroll_position_row = let scroll_position_row =
position_map.scroll_pixel_position.y / position_map.line_height; position_map.scroll_pixel_position.y / position_map.line_height;
let line_offset_from_top = display_row - scroll_position_row as u32; let line_offset_from_top = display_row - scroll_position_row as u32;
@ -636,7 +639,6 @@ impl EditorElement {
} }
} }
} }
}
fn mouse_right_down( fn mouse_right_down(
editor: &mut Editor, editor: &mut Editor,
@ -2033,11 +2035,10 @@ impl EditorElement {
scroll_position: gpui::Point<f32>, scroll_position: gpui::Point<f32>,
rows: Range<DisplayRow>, rows: Range<DisplayRow>,
buffer_rows: impl Iterator<Item = Option<MultiBufferRow>>, buffer_rows: impl Iterator<Item = Option<MultiBufferRow>>,
active_rows: &BTreeMap<DisplayRow, bool>,
newest_selection_head: Option<DisplayPoint>, newest_selection_head: Option<DisplayPoint>,
snapshot: &EditorSnapshot, snapshot: &EditorSnapshot,
cx: &mut WindowContext, cx: &mut WindowContext,
) -> Arc<HashMap<MultiBufferRow, (ShapedLine, Option<Hitbox>)>> { ) -> Arc<HashMap<MultiBufferRow, LineNumberLayout>> {
let include_line_numbers = snapshot.show_line_numbers.unwrap_or_else(|| { let include_line_numbers = snapshot.show_line_numbers.unwrap_or_else(|| {
EditorSettings::get_global(cx).gutter.line_numbers && snapshot.mode == EditorMode::Full EditorSettings::get_global(cx).gutter.line_numbers && snapshot.mode == EditorMode::Full
}); });
@ -2075,19 +2076,15 @@ impl EditorElement {
.enumerate() .enumerate()
.flat_map(|(ix, buffer_row)| { .flat_map(|(ix, buffer_row)| {
let buffer_row = buffer_row?; let buffer_row = buffer_row?;
let display_row = DisplayRow(rows.start.0 + ix as u32);
let color = if active_rows.contains_key(&display_row) {
cx.theme().colors().editor_active_line_number
} else {
cx.theme().colors().editor_line_number
};
line_number.clear(); line_number.clear();
let default_number = buffer_row.0 + 1; let display_row = DisplayRow(rows.start.0 + ix as u32);
let non_relative_number = buffer_row.0 + 1;
let number = relative_rows let number = relative_rows
.get(&DisplayRow(ix as u32 + rows.start.0)) .get(&display_row)
.unwrap_or(&default_number); .unwrap_or(&non_relative_number);
write!(&mut line_number, "{number}").unwrap(); write!(&mut line_number, "{number}").unwrap();
let color = cx.theme().colors().editor_line_number;
let shaped_line = self let shaped_line = self
.shape_line_number(SharedString::from(&line_number), color, cx) .shape_line_number(SharedString::from(&line_number), color, cx)
.log_err()?; .log_err()?;
@ -2115,7 +2112,12 @@ impl EditorElement {
let multi_buffer_row = DisplayPoint::new(display_row, 0).to_point(snapshot).row; let multi_buffer_row = DisplayPoint::new(display_row, 0).to_point(snapshot).row;
let multi_buffer_row = MultiBufferRow(multi_buffer_row); let multi_buffer_row = MultiBufferRow(multi_buffer_row);
Some((multi_buffer_row, (shaped_line, hitbox))) let line_number = LineNumberLayout {
shaped_line,
hitbox,
display_row,
};
Some((multi_buffer_row, line_number))
}) })
.collect(); .collect();
Arc::new(line_numbers) Arc::new(line_numbers)
@ -3961,17 +3963,26 @@ impl EditorElement {
let line_height = layout.position_map.line_height; let line_height = layout.position_map.line_height;
cx.set_cursor_style(CursorStyle::Arrow, &layout.gutter_hitbox); cx.set_cursor_style(CursorStyle::Arrow, &layout.gutter_hitbox);
for (_, (line, hitbox)) in layout.line_numbers.iter() { for LineNumberLayout {
shaped_line,
hitbox,
display_row,
} in layout.line_numbers.values()
{
let Some(hitbox) = hitbox else { let Some(hitbox) = hitbox else {
continue; continue;
}; };
let color = if !is_singleton && hitbox.is_hovered(cx) {
let is_active = layout.active_rows.contains_key(&display_row);
let color = if is_active {
cx.theme().colors().editor_active_line_number cx.theme().colors().editor_active_line_number
} else { } else {
cx.theme().colors().editor_line_number cx.theme().colors().editor_line_number
}; };
let Some(line) = self let Some(line) = self
.shape_line_number(line.text.clone(), color, cx) .shape_line_number(shaped_line.text.clone(), color, cx)
.log_err() .log_err()
else { else {
continue; continue;
@ -6280,7 +6291,6 @@ impl Element for EditorElement {
scroll_position, scroll_position,
start_row..end_row, start_row..end_row,
buffer_rows.iter().copied(), buffer_rows.iter().copied(),
&active_rows,
newest_selection_head, newest_selection_head,
&snapshot, &snapshot,
cx, cx,
@ -6991,7 +7001,7 @@ pub struct EditorLayout {
active_rows: BTreeMap<DisplayRow, bool>, active_rows: BTreeMap<DisplayRow, bool>,
highlighted_rows: BTreeMap<DisplayRow, Hsla>, highlighted_rows: BTreeMap<DisplayRow, Hsla>,
line_elements: SmallVec<[AnyElement; 1]>, line_elements: SmallVec<[AnyElement; 1]>,
line_numbers: Arc<HashMap<MultiBufferRow, (ShapedLine, Option<Hitbox>)>>, line_numbers: Arc<HashMap<MultiBufferRow, LineNumberLayout>>,
display_hunks: Vec<(DisplayDiffHunk, Option<Hitbox>)>, display_hunks: Vec<(DisplayDiffHunk, Option<Hitbox>)>,
blamed_display_rows: Option<Vec<AnyElement>>, blamed_display_rows: Option<Vec<AnyElement>>,
inline_blame: Option<AnyElement>, inline_blame: Option<AnyElement>,
@ -7019,6 +7029,12 @@ impl EditorLayout {
} }
} }
struct LineNumberLayout {
shaped_line: ShapedLine,
hitbox: Option<Hitbox>,
display_row: DisplayRow,
}
struct ColoredRange<T> { struct ColoredRange<T> {
start: T, start: T,
end: T, end: T,
@ -7661,7 +7677,6 @@ mod tests {
gpui::Point::default(), gpui::Point::default(),
DisplayRow(0)..DisplayRow(6), DisplayRow(0)..DisplayRow(6),
(0..6).map(MultiBufferRow).map(Some), (0..6).map(MultiBufferRow).map(Some),
&Default::default(),
Some(DisplayPoint::new(DisplayRow(0), 0)), Some(DisplayPoint::new(DisplayRow(0), 0)),
&snapshot, &snapshot,
cx, cx,
@ -7911,7 +7926,7 @@ mod tests {
state state
.line_numbers .line_numbers
.get(&MultiBufferRow(0)) .get(&MultiBufferRow(0))
.and_then(|(line, _)| line.text.as_str()), .and_then(|line_number| line_number.shaped_line.text.as_str()),
Some("1") Some("1")
); );
} }

View file

@ -20,7 +20,7 @@ use crate::{
ProjectEnvironment, ProjectEnvironment,
}; };
#[expect(clippy::large_enum_variant)] #[allow(clippy::large_enum_variant)] // platform-dependent warning
pub enum TaskStore { pub enum TaskStore {
Functional(StoreState), Functional(StoreState),
Noop, Noop,