editor: Improve line number width by max lines. (#1291)
This commit is contained in:
parent
6b7a481fc8
commit
13e2b08873
2 changed files with 57 additions and 50 deletions
|
|
@ -1,10 +1,9 @@
|
||||||
use gpui::*;
|
use gpui::*;
|
||||||
use gpui_component::{
|
use gpui_component::{
|
||||||
highlighter::{HighlightTheme, Language},
|
highlighter::Language,
|
||||||
input::{InputEvent, InputState, TabSize, TextInput},
|
input::{InputEvent, InputState, TabSize, TextInput},
|
||||||
resizable::{h_resizable, resizable_panel, ResizableState},
|
resizable::{h_resizable, resizable_panel, ResizableState},
|
||||||
text::{TextView, TextViewStyle},
|
text::TextView,
|
||||||
ActiveTheme as _,
|
|
||||||
};
|
};
|
||||||
use story::Assets;
|
use story::Assets;
|
||||||
|
|
||||||
|
|
@ -48,14 +47,6 @@ impl Example {
|
||||||
|
|
||||||
impl Render for Example {
|
impl Render for Example {
|
||||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
let theme = if cx.theme().mode.is_dark() {
|
|
||||||
HighlightTheme::default_dark()
|
|
||||||
} else {
|
|
||||||
HighlightTheme::default_light()
|
|
||||||
};
|
|
||||||
|
|
||||||
let is_dark = cx.theme().mode.is_dark();
|
|
||||||
|
|
||||||
h_resizable("container", self.resizable_state.clone())
|
h_resizable("container", self.resizable_state.clone())
|
||||||
.child(
|
.child(
|
||||||
resizable_panel().child(
|
resizable_panel().child(
|
||||||
|
|
@ -68,7 +59,7 @@ impl Render for Example {
|
||||||
TextInput::new(&self.input_state)
|
TextInput::new(&self.input_state)
|
||||||
.h_full()
|
.h_full()
|
||||||
.p_0()
|
.p_0()
|
||||||
.appearance(false)
|
.border_0()
|
||||||
.focus_bordered(false),
|
.focus_bordered(false),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -87,12 +78,7 @@ impl Render for Example {
|
||||||
window,
|
window,
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
.selectable()
|
.selectable(),
|
||||||
.style(TextViewStyle {
|
|
||||||
highlight_theme: theme.clone(),
|
|
||||||
is_dark,
|
|
||||||
..Default::default()
|
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use gpui::{
|
||||||
fill, point, px, relative, size, App, Bounds, Corners, Element, ElementId, ElementInputHandler,
|
fill, point, px, relative, size, App, Bounds, Corners, Element, ElementId, ElementInputHandler,
|
||||||
Entity, GlobalElementId, Half, HighlightStyle, Hitbox, IntoElement, LayoutId, MouseButton,
|
Entity, GlobalElementId, Half, HighlightStyle, Hitbox, IntoElement, LayoutId, MouseButton,
|
||||||
MouseMoveEvent, Path, Pixels, Point, ShapedLine, SharedString, Size, Style, TextAlign, TextRun,
|
MouseMoveEvent, Path, Pixels, Point, ShapedLine, SharedString, Size, Style, TextAlign, TextRun,
|
||||||
UnderlineStyle, Window,
|
TextStyle, UnderlineStyle, Window,
|
||||||
};
|
};
|
||||||
use ropey::Rope;
|
use ropey::Rope;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
@ -483,6 +483,45 @@ impl TextElement {
|
||||||
(visible_range, visible_top)
|
(visible_range, visible_top)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return (line_number_width, line_number_len)
|
||||||
|
fn layout_line_numbers(
|
||||||
|
state: &InputState,
|
||||||
|
text: &Rope,
|
||||||
|
font_size: Pixels,
|
||||||
|
style: &TextStyle,
|
||||||
|
window: &mut Window,
|
||||||
|
) -> (Pixels, usize) {
|
||||||
|
let total_lines = text.lines_len();
|
||||||
|
let line_number_len = match total_lines {
|
||||||
|
0..=9999 => 5,
|
||||||
|
10000..=99999 => 6,
|
||||||
|
100000..=999999 => 7,
|
||||||
|
_ => 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
let line_number_width = if state.mode.line_number() {
|
||||||
|
let empty_line_number = window.text_system().shape_line(
|
||||||
|
"+".repeat(line_number_len).into(),
|
||||||
|
font_size,
|
||||||
|
&[TextRun {
|
||||||
|
len: line_number_len,
|
||||||
|
font: style.font(),
|
||||||
|
color: gpui::black(),
|
||||||
|
background_color: None,
|
||||||
|
underline: None,
|
||||||
|
strikethrough: None,
|
||||||
|
}],
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
empty_line_number.width + px(6.) + LINE_NUMBER_RIGHT_MARGIN
|
||||||
|
} else {
|
||||||
|
px(0.)
|
||||||
|
};
|
||||||
|
|
||||||
|
(line_number_width, line_number_len)
|
||||||
|
}
|
||||||
|
|
||||||
/// First usize is the offset of skipped.
|
/// First usize is the offset of skipped.
|
||||||
fn highlight_lines(
|
fn highlight_lines(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
@ -670,39 +709,23 @@ impl Element for TextElement {
|
||||||
|
|
||||||
let (display_text, text_color) = if is_empty {
|
let (display_text, text_color) = if is_empty {
|
||||||
(
|
(
|
||||||
Rope::from(placeholder.as_str()),
|
&Rope::from(placeholder.as_str()),
|
||||||
cx.theme().muted_foreground,
|
cx.theme().muted_foreground,
|
||||||
)
|
)
|
||||||
} else if state.masked {
|
} else if state.masked {
|
||||||
(
|
(
|
||||||
Rope::from("*".repeat(text.chars().count())),
|
&Rope::from("*".repeat(text.chars().count())),
|
||||||
cx.theme().foreground,
|
cx.theme().foreground,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(text.clone(), cx.theme().foreground)
|
(&text, cx.theme().foreground)
|
||||||
};
|
};
|
||||||
|
|
||||||
let text_style = window.text_style();
|
let text_style = window.text_style();
|
||||||
|
|
||||||
// Calculate the width of the line numbers
|
// Calculate the width of the line numbers
|
||||||
let empty_line_number = window.text_system().shape_line(
|
let (line_number_width, line_number_len) =
|
||||||
"++++++".into(),
|
Self::layout_line_numbers(&state, &text, font_size, &text_style, window);
|
||||||
font_size,
|
|
||||||
&[TextRun {
|
|
||||||
len: 6,
|
|
||||||
font: style.font(),
|
|
||||||
color: gpui::black(),
|
|
||||||
background_color: None,
|
|
||||||
underline: None,
|
|
||||||
strikethrough: None,
|
|
||||||
}],
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
let line_number_width = if state.mode.line_number() {
|
|
||||||
empty_line_number.width + px(6.) + LINE_NUMBER_RIGHT_MARGIN
|
|
||||||
} else {
|
|
||||||
px(0.)
|
|
||||||
};
|
|
||||||
|
|
||||||
let run = TextRun {
|
let run = TextRun {
|
||||||
len: display_text.len(),
|
len: display_text.len(),
|
||||||
|
|
@ -881,9 +904,8 @@ impl Element for TextElement {
|
||||||
let state = self.state.read(cx);
|
let state = self.state.read(cx);
|
||||||
let line_numbers = if state.mode.line_number() {
|
let line_numbers = if state.mode.line_number() {
|
||||||
let mut line_numbers = vec![];
|
let mut line_numbers = vec![];
|
||||||
let run_len = 6;
|
|
||||||
let other_line_runs = vec![TextRun {
|
let other_line_runs = vec![TextRun {
|
||||||
len: run_len,
|
len: line_number_len,
|
||||||
font: style.font(),
|
font: style.font(),
|
||||||
color: cx.theme().muted_foreground,
|
color: cx.theme().muted_foreground,
|
||||||
background_color: None,
|
background_color: None,
|
||||||
|
|
@ -891,7 +913,7 @@ impl Element for TextElement {
|
||||||
strikethrough: None,
|
strikethrough: None,
|
||||||
}];
|
}];
|
||||||
let current_line_runs = vec![TextRun {
|
let current_line_runs = vec![TextRun {
|
||||||
len: run_len,
|
len: line_number_len,
|
||||||
font: style.font(),
|
font: style.font(),
|
||||||
color: cx.theme().foreground,
|
color: cx.theme().foreground,
|
||||||
background_color: None,
|
background_color: None,
|
||||||
|
|
@ -902,7 +924,7 @@ impl Element for TextElement {
|
||||||
// build line numbers
|
// build line numbers
|
||||||
for (ix, line) in last_layout.lines.iter().enumerate() {
|
for (ix, line) in last_layout.lines.iter().enumerate() {
|
||||||
let ix = last_layout.visible_range.start + ix;
|
let ix = last_layout.visible_range.start + ix;
|
||||||
let line_no_text = format!("{:>6}", ix + 1);
|
let line_no = format!("{:>width$}", ix + 1, width = line_number_len).into();
|
||||||
|
|
||||||
let runs = if current_row == Some(ix) {
|
let runs = if current_row == Some(ix) {
|
||||||
¤t_line_runs
|
¤t_line_runs
|
||||||
|
|
@ -911,12 +933,11 @@ impl Element for TextElement {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut sub_lines: SmallVec<[ShapedLine; 1]> = SmallVec::new();
|
let mut sub_lines: SmallVec<[ShapedLine; 1]> = SmallVec::new();
|
||||||
sub_lines.push(window.text_system().shape_line(
|
sub_lines.push(
|
||||||
line_no_text.into(),
|
window
|
||||||
font_size,
|
.text_system()
|
||||||
&runs,
|
.shape_line(line_no, font_size, &runs, None),
|
||||||
None,
|
);
|
||||||
));
|
|
||||||
for _ in 0..line.wrap_boundaries.len() {
|
for _ in 0..line.wrap_boundaries.len() {
|
||||||
sub_lines.push(ShapedLine::default());
|
sub_lines.push(ShapedLine::default());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue