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:
parent
178269be63
commit
6ebb9418a0
3 changed files with 42 additions and 12 deletions
|
|
@ -9,7 +9,7 @@ use std::{
|
||||||
use anyhow::Ok;
|
use anyhow::Ok;
|
||||||
use gpui::{prelude::FluentBuilder, *};
|
use gpui::{prelude::FluentBuilder, *};
|
||||||
use gpui_component::{
|
use gpui_component::{
|
||||||
ActiveTheme, ContextModal, IconName, IndexPath, Selectable, Sizable,
|
ActiveTheme, ContextModal, IconName, IndexPath, Sizable,
|
||||||
button::{Button, ButtonVariants as _},
|
button::{Button, ButtonVariants as _},
|
||||||
dropdown::{Dropdown, DropdownEvent, DropdownState},
|
dropdown::{Dropdown, DropdownEvent, DropdownState},
|
||||||
h_flex,
|
h_flex,
|
||||||
|
|
@ -998,16 +998,18 @@ impl Render for Example {
|
||||||
Button::new("soft-wrap")
|
Button::new("soft-wrap")
|
||||||
.ghost()
|
.ghost()
|
||||||
.xsmall()
|
.xsmall()
|
||||||
|
.when(self.soft_wrap, |this| this.icon(IconName::Check))
|
||||||
.label("Soft Wrap")
|
.label("Soft Wrap")
|
||||||
.selected(self.soft_wrap)
|
|
||||||
.on_click(cx.listener(Self::toggle_soft_wrap))
|
.on_click(cx.listener(Self::toggle_soft_wrap))
|
||||||
})
|
})
|
||||||
.child({
|
.child({
|
||||||
Button::new("indent-guides")
|
Button::new("indent-guides")
|
||||||
.ghost()
|
.ghost()
|
||||||
.xsmall()
|
.xsmall()
|
||||||
|
.when(self.indent_guides, |this| {
|
||||||
|
this.icon(IconName::Check)
|
||||||
|
})
|
||||||
.label("Indent Guides")
|
.label("Indent Guides")
|
||||||
.selected(self.indent_guides)
|
|
||||||
.on_click(cx.listener(Self::toggle_indent_guides))
|
.on_click(cx.listener(Self::toggle_indent_guides))
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1084,7 +1084,8 @@ impl Element for TextElement {
|
||||||
};
|
};
|
||||||
|
|
||||||
let hover_definition_hitbox = self.layout_hover_definition_hitbox(state, window, cx);
|
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 {
|
PrepaintState {
|
||||||
bounds,
|
bounds,
|
||||||
|
|
@ -1194,7 +1195,7 @@ impl Element for TextElement {
|
||||||
|
|
||||||
// Paint indent guides
|
// Paint indent guides
|
||||||
if let Some(path) = prepaint.indent_guides_path.take() {
|
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
|
// Paint selections
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use gpui::{
|
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;
|
use ropey::RopeSlice;
|
||||||
|
|
||||||
|
|
@ -80,21 +81,46 @@ impl InputMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextElement {
|
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(
|
pub(super) fn layout_indent_guides(
|
||||||
&self,
|
&self,
|
||||||
state: &InputState,
|
state: &InputState,
|
||||||
last_layout: &LastLayout,
|
last_layout: &LastLayout,
|
||||||
|
text_style: &TextStyle,
|
||||||
|
window: &mut Window,
|
||||||
) -> Option<Path<Pixels>> {
|
) -> Option<Path<Pixels>> {
|
||||||
if !state.mode.has_indent_guides() {
|
if !state.mode.has_indent_guides() {
|
||||||
return None;
|
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 tab_size = state.mode.tab_size();
|
||||||
let line_height = last_layout.line_height;
|
let line_height = last_layout.line_height;
|
||||||
let visible_range = last_layout.visible_range.clone();
|
let visible_range = last_layout.visible_range.clone();
|
||||||
let mut builder = PathBuilder::stroke(px(1.));
|
let mut builder = PathBuilder::stroke(px(1.));
|
||||||
let mut offset_y =
|
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![];
|
let mut last_indents = vec![];
|
||||||
for ix in visible_range {
|
for ix in visible_range {
|
||||||
let line = state.text.slice_line(ix);
|
let line = state.text.slice_line(ix);
|
||||||
|
|
@ -103,12 +129,13 @@ impl TextElement {
|
||||||
if line.len() > 0 {
|
if line.len() > 0 {
|
||||||
let indent_count = tab_size.indent_count(&line);
|
let indent_count = tab_size.indent_count(&line);
|
||||||
for offset in (0..indent_count).step_by(tab_size.tab_size) {
|
for offset in (0..indent_count).step_by(tab_size.tab_size) {
|
||||||
let mut pos = line_layout
|
let x = if indent_count > 0 {
|
||||||
.position_for_index(offset, line_height)
|
indent_width * offset as f32 / tab_size.tab_size as f32
|
||||||
.unwrap_or(point(px(0.), px(0.)));
|
} else {
|
||||||
|
px(0.)
|
||||||
|
};
|
||||||
|
|
||||||
pos.x += last_layout.line_number_width;
|
let pos = point(x + last_layout.line_number_width, offset_y);
|
||||||
pos.y += offset_y;
|
|
||||||
|
|
||||||
builder.move_to(pos);
|
builder.move_to(pos);
|
||||||
builder.line_to(point(pos.x, pos.y + line_height));
|
builder.line_to(point(pos.x, pos.y + line_height));
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue