Add support for typing in the numeric stepper componenets
This commit is contained in:
parent
43b4363b34
commit
c5a258e0b8
9 changed files with 156 additions and 31 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -11095,6 +11095,7 @@ dependencies = [
|
|||
"telemetry",
|
||||
"theme",
|
||||
"ui",
|
||||
"ui_input",
|
||||
"util",
|
||||
"vim_mode_setting",
|
||||
"workspace",
|
||||
|
@ -17514,6 +17515,7 @@ dependencies = [
|
|||
"component",
|
||||
"editor",
|
||||
"gpui",
|
||||
"menu",
|
||||
"settings",
|
||||
"theme",
|
||||
"ui",
|
||||
|
|
|
@ -5,8 +5,7 @@ use project::project_settings::{InlineBlameSettings, ProjectSettings};
|
|||
use settings::{EditableSettingControl, Settings};
|
||||
use theme::{FontFamilyCache, FontFamilyName, ThemeSettings};
|
||||
use ui::{
|
||||
CheckboxWithLabel, ContextMenu, DropdownMenu, NumericStepper, SettingsContainer, SettingsGroup,
|
||||
prelude::*,
|
||||
CheckboxWithLabel, ContextMenu, DropdownMenu, SettingsContainer, SettingsGroup, prelude::*,
|
||||
};
|
||||
|
||||
use crate::EditorSettings;
|
||||
|
@ -139,21 +138,12 @@ impl EditableSettingControl for BufferFontSizeControl {
|
|||
|
||||
impl RenderOnce for BufferFontSizeControl {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let value = Self::read(cx);
|
||||
let _value = Self::read(cx);
|
||||
|
||||
h_flex()
|
||||
.gap_2()
|
||||
.child(Icon::new(IconName::FontSize))
|
||||
.child(NumericStepper::new(
|
||||
"buffer-font-size",
|
||||
value.to_string(),
|
||||
move |_, _, cx| {
|
||||
Self::write(value - px(1.), cx);
|
||||
},
|
||||
move |_, _, cx| {
|
||||
Self::write(value + px(1.), cx);
|
||||
},
|
||||
))
|
||||
.child(div()) // todo!(Numeric stepper was here)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ settings.workspace = true
|
|||
telemetry.workspace = true
|
||||
theme.workspace = true
|
||||
ui.workspace = true
|
||||
ui_input.workspace = true
|
||||
util.workspace = true
|
||||
vim_mode_setting.workspace = true
|
||||
workspace-hack.workspace = true
|
||||
|
|
|
@ -12,10 +12,10 @@ use project::project_settings::ProjectSettings;
|
|||
use settings::{Settings as _, update_settings_file};
|
||||
use theme::{FontFamilyCache, FontFamilyName, ThemeSettings};
|
||||
use ui::{
|
||||
ButtonLike, ListItem, ListItemSpacing, NumericStepper, PopoverMenu, SwitchField,
|
||||
ToggleButtonGroup, ToggleButtonGroupStyle, ToggleButtonSimple, ToggleState, Tooltip,
|
||||
prelude::*,
|
||||
ButtonLike, ListItem, ListItemSpacing, PopoverMenu, SwitchField, ToggleButtonGroup,
|
||||
ToggleButtonGroupStyle, ToggleButtonSimple, ToggleState, Tooltip, prelude::*,
|
||||
};
|
||||
use ui_input::NumericStepper;
|
||||
|
||||
use crate::{ImportCursorSettings, ImportVsCodeSettings, SettingsImportState};
|
||||
|
||||
|
@ -350,14 +350,19 @@ fn render_font_customization_section(
|
|||
NumericStepper::new(
|
||||
"ui-font-size",
|
||||
ui_font_size.to_string(),
|
||||
move |size, cx| {
|
||||
write_ui_font_size(Pixels::from(size), cx);
|
||||
},
|
||||
move |_, _, cx| {
|
||||
write_ui_font_size(ui_font_size - px(1.), cx);
|
||||
},
|
||||
move |_, _, cx| {
|
||||
write_ui_font_size(ui_font_size + px(1.), cx);
|
||||
},
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
.style(ui::NumericStepperStyle::Outlined)
|
||||
.style(ui_input::NumericStepperStyle::Outlined)
|
||||
.tab_index({
|
||||
*tab_index += 2;
|
||||
*tab_index - 2
|
||||
|
@ -414,14 +419,19 @@ fn render_font_customization_section(
|
|||
NumericStepper::new(
|
||||
"buffer-font-size",
|
||||
buffer_font_size.to_string(),
|
||||
move |size, cx| {
|
||||
write_buffer_font_size(Pixels::from(size), cx);
|
||||
},
|
||||
move |_, _, cx| {
|
||||
write_buffer_font_size(buffer_font_size - px(1.), cx);
|
||||
},
|
||||
move |_, _, cx| {
|
||||
write_buffer_font_size(buffer_font_size + px(1.), cx);
|
||||
},
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
.style(ui::NumericStepperStyle::Outlined)
|
||||
.style(ui_input::NumericStepperStyle::Outlined)
|
||||
.tab_index({
|
||||
*tab_index += 2;
|
||||
*tab_index - 2
|
||||
|
|
|
@ -6,9 +6,10 @@ use theme::{
|
|||
FontFamilyCache, FontFamilyName, SystemAppearance, ThemeMode, ThemeRegistry, ThemeSettings,
|
||||
};
|
||||
use ui::{
|
||||
CheckboxWithLabel, ContextMenu, DropdownMenu, NumericStepper, SettingsContainer, SettingsGroup,
|
||||
ToggleButton, prelude::*,
|
||||
CheckboxWithLabel, ContextMenu, DropdownMenu, SettingsContainer, SettingsGroup, ToggleButton,
|
||||
prelude::*,
|
||||
};
|
||||
use ui_input::NumericStepper;
|
||||
|
||||
#[derive(IntoElement)]
|
||||
pub struct AppearanceSettingsControls {}
|
||||
|
@ -254,7 +255,7 @@ impl EditableSettingControl for UiFontSizeControl {
|
|||
}
|
||||
|
||||
impl RenderOnce for UiFontSizeControl {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let value = Self::read(cx);
|
||||
|
||||
h_flex()
|
||||
|
@ -263,12 +264,17 @@ impl RenderOnce for UiFontSizeControl {
|
|||
.child(NumericStepper::new(
|
||||
"ui-font-size",
|
||||
value.to_string(),
|
||||
move |size, cx| {
|
||||
Self::write(Pixels::from(size), cx);
|
||||
},
|
||||
move |_, _, cx| {
|
||||
Self::write(value - px(1.), cx);
|
||||
},
|
||||
move |_, _, cx| {
|
||||
Self::write(value + px(1.), cx);
|
||||
},
|
||||
window,
|
||||
cx,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ mod list;
|
|||
mod modal;
|
||||
mod navigable;
|
||||
mod notification;
|
||||
mod numeric_stepper;
|
||||
mod popover;
|
||||
mod popover_menu;
|
||||
mod progress;
|
||||
|
@ -65,7 +64,6 @@ pub use list::*;
|
|||
pub use modal::*;
|
||||
pub use navigable::*;
|
||||
pub use notification::*;
|
||||
pub use numeric_stepper::*;
|
||||
pub use popover::*;
|
||||
pub use popover_menu::*;
|
||||
pub use progress::*;
|
||||
|
|
|
@ -15,6 +15,7 @@ path = "src/ui_input.rs"
|
|||
component.workspace = true
|
||||
editor.workspace = true
|
||||
gpui.workspace = true
|
||||
menu.workspace = true
|
||||
settings.workspace = true
|
||||
theme.workspace = true
|
||||
ui.workspace = true
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use gpui::ClickEvent;
|
||||
use editor::Editor;
|
||||
use gpui::{ClickEvent, Entity, Focusable};
|
||||
|
||||
use crate::{IconButtonShape, prelude::*};
|
||||
use ui::{IconButtonShape, prelude::*};
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum NumericStepperStyle {
|
||||
|
@ -9,11 +10,21 @@ pub enum NumericStepperStyle {
|
|||
Ghost,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum NumericStepperMode {
|
||||
#[default]
|
||||
Read,
|
||||
Edit,
|
||||
}
|
||||
|
||||
#[derive(IntoElement, RegisterComponent)]
|
||||
pub struct NumericStepper {
|
||||
id: ElementId,
|
||||
value: SharedString,
|
||||
style: NumericStepperStyle,
|
||||
input_field: Entity<Editor>,
|
||||
mode: Entity<NumericStepperMode>,
|
||||
set_value_to: Box<dyn Fn(usize, &mut App) + 'static>,
|
||||
on_decrement: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,
|
||||
on_increment: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,
|
||||
/// Whether to reserve space for the reset button.
|
||||
|
@ -26,15 +37,61 @@ impl NumericStepper {
|
|||
pub fn new(
|
||||
id: impl Into<ElementId>,
|
||||
value: impl Into<SharedString>,
|
||||
set_value_to: impl Fn(usize, &mut App) + 'static,
|
||||
on_decrement: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
|
||||
on_increment: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Self {
|
||||
let id = id.into();
|
||||
let value = value.into();
|
||||
|
||||
let (input_field, mode) = window.with_global_id(id.clone(), |global_id, window| {
|
||||
// todo! Make sure that using this api is inline and appropriate with the codebase
|
||||
window.with_element_state::<(Entity<Editor>, Entity<NumericStepperMode>), _>(
|
||||
global_id,
|
||||
|mut editor, window| {
|
||||
let state = editor
|
||||
.get_or_insert_with(|| {
|
||||
let mode = cx.new(|_| NumericStepperMode::default());
|
||||
let weak_mode = mode.downgrade();
|
||||
let editor = cx.new(|cx| {
|
||||
let editor = Editor::single_line(window, cx);
|
||||
|
||||
cx.on_focus_out(
|
||||
&editor.focus_handle(cx),
|
||||
window,
|
||||
move |this, _, window, cx| {
|
||||
this.clear(window, cx);
|
||||
|
||||
weak_mode
|
||||
.update(cx, |mode, _| *mode = NumericStepperMode::Read)
|
||||
.ok();
|
||||
},
|
||||
)
|
||||
.detach();
|
||||
|
||||
editor
|
||||
});
|
||||
|
||||
(editor, mode)
|
||||
})
|
||||
.clone();
|
||||
|
||||
(state.clone(), state)
|
||||
},
|
||||
)
|
||||
});
|
||||
|
||||
Self {
|
||||
id: id.into(),
|
||||
value: value.into(),
|
||||
style: NumericStepperStyle::default(),
|
||||
id,
|
||||
value,
|
||||
input_field,
|
||||
mode,
|
||||
set_value_to: Box::new(set_value_to),
|
||||
on_decrement: Box::new(on_decrement),
|
||||
on_increment: Box::new(on_increment),
|
||||
style: NumericStepperStyle::default(),
|
||||
reserve_space_for_reset: false,
|
||||
on_reset: None,
|
||||
tab_index: None,
|
||||
|
@ -74,7 +131,7 @@ impl RenderOnce for NumericStepper {
|
|||
let mut tab_index = self.tab_index;
|
||||
|
||||
h_flex()
|
||||
.id(self.id)
|
||||
.id(self.id.clone())
|
||||
.gap_1()
|
||||
.map(|element| {
|
||||
if let Some(on_reset) = self.on_reset {
|
||||
|
@ -146,7 +203,59 @@ impl RenderOnce for NumericStepper {
|
|||
)
|
||||
}
|
||||
})
|
||||
.child(Label::new(self.value).mx_3())
|
||||
.child(if matches!(self.mode.read(cx), NumericStepperMode::Read) {
|
||||
div()
|
||||
.id(SharedString::new(format!(
|
||||
"numeric_stepper_label{}",
|
||||
&self.id,
|
||||
)))
|
||||
.child(Label::new(self.value).mx_3())
|
||||
.on_click({
|
||||
let mode = self.mode.downgrade();
|
||||
let input_field_focus_handle = self.input_field.focus_handle(cx);
|
||||
|
||||
move |click, window, cx| {
|
||||
if click.click_count() == 2 {
|
||||
mode.update(cx, |mode, _| {
|
||||
*mode = NumericStepperMode::Edit;
|
||||
})
|
||||
.ok();
|
||||
|
||||
window.focus(&input_field_focus_handle);
|
||||
}
|
||||
}
|
||||
})
|
||||
.into_any_element()
|
||||
} else {
|
||||
div()
|
||||
.child(self.input_field.clone())
|
||||
.child("todo!(This should be removed. It's only here to get input_field to render correctly)")
|
||||
.on_action::<menu::Confirm>({
|
||||
let input_field = self.input_field.downgrade();
|
||||
let mode = self.mode.downgrade();
|
||||
let set_value = self.set_value_to;
|
||||
|
||||
move |_, _, cx| {
|
||||
input_field
|
||||
.update(cx, |input_field, cx| {
|
||||
if let Some(number) =
|
||||
input_field.text(cx).parse::<usize>().ok()
|
||||
{
|
||||
set_value(number, cx);
|
||||
|
||||
mode.update(cx, |mode, _| {
|
||||
*mode = NumericStepperMode::Read
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.w_full()
|
||||
.mx_3()
|
||||
.into_any_element()
|
||||
})
|
||||
.map(|increment| {
|
||||
if is_outlined {
|
||||
increment.child(
|
||||
|
@ -201,7 +310,7 @@ impl Component for NumericStepper {
|
|||
Some("A button used to increment or decrement a numeric value.")
|
||||
}
|
||||
|
||||
fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
|
||||
fn preview(window: &mut Window, cx: &mut App) -> Option<AnyElement> {
|
||||
Some(
|
||||
v_flex()
|
||||
.gap_6()
|
||||
|
@ -213,8 +322,11 @@ impl Component for NumericStepper {
|
|||
NumericStepper::new(
|
||||
"numeric-stepper-component-preview",
|
||||
"10",
|
||||
move |_, _| {},
|
||||
move |_, _, _| {},
|
||||
move |_, _, _| {},
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
.into_any_element(),
|
||||
),
|
||||
|
@ -223,8 +335,11 @@ impl Component for NumericStepper {
|
|||
NumericStepper::new(
|
||||
"numeric-stepper-with-border-component-preview",
|
||||
"10",
|
||||
move |_, _| {},
|
||||
move |_, _, _| {},
|
||||
move |_, _, _| {},
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
.style(NumericStepperStyle::Outlined)
|
||||
.into_any_element(),
|
|
@ -4,10 +4,12 @@
|
|||
//!
|
||||
//! It can't be located in the `ui` crate because it depends on `editor`.
|
||||
//!
|
||||
mod numeric_stepper;
|
||||
|
||||
use component::{example_group, single_example};
|
||||
use editor::{Editor, EditorElement, EditorStyle};
|
||||
use gpui::{App, Entity, FocusHandle, Focusable, FontStyle, Hsla, TextStyle};
|
||||
pub use numeric_stepper::*;
|
||||
use settings::Settings;
|
||||
use theme::ThemeSettings;
|
||||
use ui::prelude::*;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue