editor: Make TextAlign::Center and TextAlign::Right work (#45417)

Closes https://github.com/zed-industries/zed/issues/43208

This PR essentially unblocks the editable number field. The function
that shapes editor lines was hard-coding text alignment to the left,
meaning that whatever different alignment we'd pass through
`EditorStyles`would be ignored. To solve this, I just added a text align
and align width fields to the line paint function and updated all call
sites keeping the default configuration. Had to also add an
`alignment_offset()` helper to make sure the cursor positioning, the
selection background element, and the click-to-focus functionality were
kept in-sync with the non-left aligned editor.

Then... the big star of the show here is being able to add the `mode`
method to the number field, which uses `TextAlign::Center`, thus making
it work as we designed it to work.


https://github.com/user-attachments/assets/3539c976-d7bf-4d94-8188-a14328f94fbf

Next up, is turning the number filed to edit mode where applicable.

Release Notes:

- Fixed a bug where different text alignment configurations (i.e.,
center and right-aligned) wouldn't take effect in editors.
This commit is contained in:
Danilo Leal authored and GitHub committed 2025-12-19 17:37:15 -08:00
1 parent 58461377ca
commit 0facdfa5ca
5 files changed
+164 -50

No files matched your search

+45 -21
View File
@@ -5,8 +5,11 @@ use std::{
str::FromStr,
};
use editor::{Editor, EditorStyle};
use gpui::{ClickEvent, Entity, FocusHandle, Focusable, FontWeight, Modifiers};
use editor::Editor;
use gpui::{
ClickEvent, Entity, FocusHandle, Focusable, FontWeight, Modifiers, TextAlign,
TextStyleRefinement,
};
use settings::{CenteredPaddingSettings, CodeFade, DelayMs, InactiveOpacity, MinimumContrast};
use ui::prelude::*;
@@ -309,6 +312,11 @@ impl<T: NumberFieldType> NumberField<T> {
self
}
pub fn mode(self, mode: NumberFieldMode, cx: &mut App) -> Self {
self.mode.write(cx, mode);
self
}
pub fn on_reset(
mut self,
on_reset: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
@@ -451,9 +459,11 @@ impl<T: NumberFieldType> RenderOnce for NumberField<T> {
|window, cx| {
let previous_focus_handle = window.focused(cx);
let mut editor = Editor::single_line(window, cx);
let mut style = EditorStyle::default();
style.text.text_align = gpui::TextAlign::Right;
editor.set_style(style, window, cx);
editor.set_text_style_refinement(TextStyleRefinement {
text_align: Some(TextAlign::Center),
..Default::default()
});
editor.set_text(format!("{}", self.value), window, cx);
cx.on_focus_out(&editor.focus_handle(cx), window, {
@@ -555,22 +565,36 @@ impl Component for NumberField<usize> {
Some(
v_flex()
.gap_6()
.children(vec![single_example(
"Default Numeric Stepper",
NumberField::new(
"numeric-stepper-component-preview",
*stepper_example.read(cx),
window,
cx,
)
.on_change({
let stepper_example = stepper_example.clone();
move |value, _, cx| stepper_example.write(cx, *value)
})
.min(1.0)
.max(100.0)
.into_any_element(),
)])
.children(vec![
single_example(
"Default Number Field",
NumberField::new("number-field", *stepper_example.read(cx), window, cx)
.on_change({
let stepper_example = stepper_example.clone();
move |value, _, cx| stepper_example.write(cx, *value)
})
.min(1.0)
.max(100.0)
.into_any_element(),
),
single_example(
"Read-Only Number Field",
NumberField::new(
"editable-number-field",
*stepper_example.read(cx),
window,
cx,
)
.on_change({
let stepper_example = stepper_example.clone();
move |value, _, cx| stepper_example.write(cx, *value)
})
.min(1.0)
.max(100.0)
.mode(NumberFieldMode::Edit, cx)
.into_any_element(),
),
])
.into_any_element(),
)
}