editor: Use measure_indent_width for indent guides width. (#1428)

Continue #1426, this changes I was forgotten to push before #1426
merged.
This commit is contained in:
Jason Lee 2025-10-24 20:18:30 +08:00 committed by GitHub
parent 178269be63
commit 6ebb9418a0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 42 additions and 12 deletions

View file

@ -9,7 +9,7 @@ use std::{
use anyhow::Ok;
use gpui::{prelude::FluentBuilder, *};
use gpui_component::{
ActiveTheme, ContextModal, IconName, IndexPath, Selectable, Sizable,
ActiveTheme, ContextModal, IconName, IndexPath, Sizable,
button::{Button, ButtonVariants as _},
dropdown::{Dropdown, DropdownEvent, DropdownState},
h_flex,
@ -998,16 +998,18 @@ impl Render for Example {
Button::new("soft-wrap")
.ghost()
.xsmall()
.when(self.soft_wrap, |this| this.icon(IconName::Check))
.label("Soft Wrap")
.selected(self.soft_wrap)
.on_click(cx.listener(Self::toggle_soft_wrap))
})
.child({
Button::new("indent-guides")
.ghost()
.xsmall()
.when(self.indent_guides, |this| {
this.icon(IconName::Check)
})
.label("Indent Guides")
.selected(self.indent_guides)
.on_click(cx.listener(Self::toggle_indent_guides))
}),
)

View file

@ -1084,7 +1084,8 @@ impl Element for TextElement {
};
let hover_definition_hitbox = self.layout_hover_definition_hitbox(state, window, cx);
let indent_guides_path = self.layout_indent_guides(state, &last_layout);
let indent_guides_path =
self.layout_indent_guides(state, &last_layout, &text_style, window);
PrepaintState {
bounds,
@ -1194,7 +1195,7 @@ impl Element for TextElement {
// Paint indent guides
if let Some(path) = prepaint.indent_guides_path.take() {
window.paint_path(path, cx.theme().secondary);
window.paint_path(path, cx.theme().border.opacity(0.85));
}
// Paint selections

View file

@ -1,5 +1,6 @@
use gpui::{
point, px, Context, EntityInputHandler as _, Path, PathBuilder, Pixels, SharedString, Window,
point, px, Context, EntityInputHandler as _, Hsla, Path, PathBuilder, Pixels, SharedString,
TextRun, TextStyle, Window,
};
use ropey::RopeSlice;
@ -80,21 +81,46 @@ impl InputMode {
}
impl TextElement {
/// Measure the indent width in pixels for given column count.
fn measure_indent_width(&self, style: &TextStyle, column: usize, window: &Window) -> Pixels {
let font_size = style.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.font(),
color: Hsla::default(),
background_color: None,
strikethrough: None,
underline: None,
}],
None,
);
layout.width
}
pub(super) fn layout_indent_guides(
&self,
state: &InputState,
last_layout: &LastLayout,
text_style: &TextStyle,
window: &mut Window,
) -> Option<Path<Pixels>> {
if !state.mode.has_indent_guides() {
return None;
}
let indent_width =
self.measure_indent_width(text_style, state.mode.tab_size().tab_size, window);
let tab_size = state.mode.tab_size();
let line_height = last_layout.line_height;
let visible_range = last_layout.visible_range.clone();
let mut builder = PathBuilder::stroke(px(1.));
let mut offset_y =
last_layout.visible_top + state.scroll_handle.offset().y + (line_height * 2 - px(3.));
last_layout.visible_top + state.scroll_handle.offset().y + (line_height * 2 - px(3.5));
let mut last_indents = vec![];
for ix in visible_range {
let line = state.text.slice_line(ix);
@ -103,12 +129,13 @@ impl TextElement {
if line.len() > 0 {
let indent_count = tab_size.indent_count(&line);
for offset in (0..indent_count).step_by(tab_size.tab_size) {
let mut pos = line_layout
.position_for_index(offset, line_height)
.unwrap_or(point(px(0.), px(0.)));
let x = if indent_count > 0 {
indent_width * offset as f32 / tab_size.tab_size as f32
} else {
px(0.)
};
pos.x += last_layout.line_number_width;
pos.y += offset_y;
let pos = point(x + last_layout.line_number_width, offset_y);
builder.move_to(pos);
builder.line_to(point(pos.x, pos.y + line_height));