Fine tune UX for new numeric stepper
This commit is contained in:
parent
b775a2e3cb
commit
e47b9d3b38
4 changed files with 193 additions and 140 deletions
|
@ -69,6 +69,20 @@ impl<'a, T: 'static> Context<'a, T> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Observe changes to ourselves
|
||||||
|
pub fn observe_self(
|
||||||
|
&mut self,
|
||||||
|
mut on_event: impl FnMut(&mut T, &mut Context<T>) + 'static,
|
||||||
|
) -> Subscription
|
||||||
|
where
|
||||||
|
T: 'static,
|
||||||
|
{
|
||||||
|
let this = self.entity();
|
||||||
|
self.app.observe(&this, move |this, cx| {
|
||||||
|
this.update(cx, |this, cx| on_event(this, cx))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Subscribe to an event type from another entity
|
/// Subscribe to an event type from another entity
|
||||||
pub fn subscribe<T2, Evt>(
|
pub fn subscribe<T2, Evt>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -4838,6 +4838,12 @@ impl<T: Into<SharedString>> From<(ElementId, T)> for ElementId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<core::panic::Location<'static>> for ElementId {
|
||||||
|
fn from(value: core::panic::Location<'static>) -> Self {
|
||||||
|
Self::CodeLocation(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A rectangle to be rendered in the window at the given position and size.
|
/// A rectangle to be rendered in the window at the given position and size.
|
||||||
/// Passed as an argument [`Window::paint_quad`].
|
/// Passed as an argument [`Window::paint_quad`].
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
|
@ -15,6 +15,7 @@ use ui::{
|
||||||
ButtonLike, ListItem, ListItemSpacing, PopoverMenu, SwitchField, ToggleButtonGroup,
|
ButtonLike, ListItem, ListItemSpacing, PopoverMenu, SwitchField, ToggleButtonGroup,
|
||||||
ToggleButtonGroupStyle, ToggleButtonSimple, ToggleState, Tooltip, prelude::*,
|
ToggleButtonGroupStyle, ToggleButtonSimple, ToggleState, Tooltip, prelude::*,
|
||||||
};
|
};
|
||||||
|
use ui_input::NumericStepper;
|
||||||
|
|
||||||
use crate::{ImportCursorSettings, ImportVsCodeSettings, SettingsImportState};
|
use crate::{ImportCursorSettings, ImportVsCodeSettings, SettingsImportState};
|
||||||
|
|
||||||
|
@ -109,7 +110,7 @@ fn write_ui_font_family(font: SharedString, cx: &mut App) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _write_ui_font_size(size: Pixels, cx: &mut App) {
|
fn write_ui_font_size(size: Pixels, cx: &mut App) {
|
||||||
let fs = <dyn Fs>::global(cx);
|
let fs = <dyn Fs>::global(cx);
|
||||||
|
|
||||||
update_settings_file::<ThemeSettings>(fs, cx, move |theme_settings, _| {
|
update_settings_file::<ThemeSettings>(fs, cx, move |theme_settings, _| {
|
||||||
|
@ -117,7 +118,7 @@ fn _write_ui_font_size(size: Pixels, cx: &mut App) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _write_buffer_font_size(size: Pixels, cx: &mut App) {
|
fn write_buffer_font_size(size: Pixels, cx: &mut App) {
|
||||||
let fs = <dyn Fs>::global(cx);
|
let fs = <dyn Fs>::global(cx);
|
||||||
|
|
||||||
update_settings_file::<ThemeSettings>(fs, cx, move |theme_settings, _| {
|
update_settings_file::<ThemeSettings>(fs, cx, move |theme_settings, _| {
|
||||||
|
@ -277,10 +278,10 @@ fn render_font_customization_section(
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) -> impl IntoElement {
|
) -> impl IntoElement {
|
||||||
let theme_settings = ThemeSettings::get_global(cx);
|
let theme_settings = ThemeSettings::get_global(cx);
|
||||||
// let ui_font_size = theme_settings.ui_font_size(cx);
|
let ui_font_size = theme_settings.ui_font_size(cx);
|
||||||
let ui_font_family = theme_settings.ui_font.family.clone();
|
let ui_font_family = theme_settings.ui_font.family.clone();
|
||||||
let buffer_font_family = theme_settings.buffer_font.family.clone();
|
let buffer_font_family = theme_settings.buffer_font.family.clone();
|
||||||
// let buffer_font_size = theme_settings.buffer_font_size(cx);
|
let buffer_font_size = theme_settings.buffer_font_size(cx);
|
||||||
|
|
||||||
let ui_font_picker =
|
let ui_font_picker =
|
||||||
cx.new(|cx| font_picker(ui_font_family.clone(), write_ui_font_family, window, cx));
|
cx.new(|cx| font_picker(ui_font_family.clone(), write_ui_font_family, window, cx));
|
||||||
|
@ -306,62 +307,53 @@ fn render_font_customization_section(
|
||||||
.gap_1()
|
.gap_1()
|
||||||
.child(Label::new("UI Font"))
|
.child(Label::new("UI Font"))
|
||||||
.child(
|
.child(
|
||||||
h_flex().w_full().justify_between().gap_2().child(
|
h_flex()
|
||||||
PopoverMenu::new("ui-font-picker")
|
.w_full()
|
||||||
.menu({
|
.justify_between()
|
||||||
let ui_font_picker = ui_font_picker.clone();
|
.gap_2()
|
||||||
move |_window, _cx| Some(ui_font_picker.clone())
|
.child(
|
||||||
})
|
PopoverMenu::new("ui-font-picker")
|
||||||
.trigger(
|
.menu({
|
||||||
ButtonLike::new("ui-font-family-button")
|
let ui_font_picker = ui_font_picker.clone();
|
||||||
.style(ButtonStyle::Outlined)
|
move |_window, _cx| Some(ui_font_picker.clone())
|
||||||
.size(ButtonSize::Medium)
|
})
|
||||||
.full_width()
|
.trigger(
|
||||||
.tab_index({
|
ButtonLike::new("ui-font-family-button")
|
||||||
*tab_index += 1;
|
.style(ButtonStyle::Outlined)
|
||||||
*tab_index - 1
|
.size(ButtonSize::Medium)
|
||||||
})
|
.full_width()
|
||||||
.child(
|
.tab_index({
|
||||||
h_flex()
|
*tab_index += 1;
|
||||||
.w_full()
|
*tab_index - 1
|
||||||
.justify_between()
|
})
|
||||||
.child(Label::new(ui_font_family))
|
.child(
|
||||||
.child(
|
h_flex()
|
||||||
Icon::new(IconName::ChevronUpDown)
|
.w_full()
|
||||||
.color(Color::Muted)
|
.justify_between()
|
||||||
.size(IconSize::XSmall),
|
.child(Label::new(ui_font_family))
|
||||||
),
|
.child(
|
||||||
),
|
Icon::new(IconName::ChevronUpDown)
|
||||||
)
|
.color(Color::Muted)
|
||||||
.full_width(true)
|
.size(IconSize::XSmall),
|
||||||
.anchor(gpui::Corner::TopLeft)
|
),
|
||||||
.offset(gpui::Point {
|
),
|
||||||
x: px(0.0),
|
)
|
||||||
y: px(4.0),
|
.full_width(true)
|
||||||
})
|
.anchor(gpui::Corner::TopLeft)
|
||||||
.with_handle(ui_font_handle),
|
.offset(gpui::Point {
|
||||||
), // .child(
|
x: px(0.0),
|
||||||
// NumericStepper::new(
|
y: px(4.0),
|
||||||
// "ui-font-size",
|
})
|
||||||
// ui_font_size.to_string(),
|
.with_handle(ui_font_handle),
|
||||||
// move |size, cx| {
|
)
|
||||||
// write_ui_font_size(Pixels::from(size), cx);
|
.child(font_picker_stepper(
|
||||||
// },
|
"ui-font-size",
|
||||||
// move |_, _, cx| {
|
&ui_font_size,
|
||||||
// write_ui_font_size(ui_font_size - px(1.), cx);
|
tab_index,
|
||||||
// },
|
write_ui_font_size,
|
||||||
// move |_, _, cx| {
|
window,
|
||||||
// write_ui_font_size(ui_font_size + px(1.), cx);
|
cx,
|
||||||
// },
|
)),
|
||||||
// window,
|
|
||||||
// cx,
|
|
||||||
// )
|
|
||||||
// .style(ui_input::NumericStepperStyle::Outlined)
|
|
||||||
// .tab_index({
|
|
||||||
// *tab_index += 2;
|
|
||||||
// *tab_index - 2
|
|
||||||
// }),
|
|
||||||
// ),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
|
@ -370,66 +362,99 @@ fn render_font_customization_section(
|
||||||
.gap_1()
|
.gap_1()
|
||||||
.child(Label::new("Editor Font"))
|
.child(Label::new("Editor Font"))
|
||||||
.child(
|
.child(
|
||||||
h_flex().w_full().justify_between().gap_2().child(
|
h_flex()
|
||||||
PopoverMenu::new("buffer-font-picker")
|
.w_full()
|
||||||
.menu({
|
.justify_between()
|
||||||
let buffer_font_picker = buffer_font_picker.clone();
|
.gap_2()
|
||||||
move |_window, _cx| Some(buffer_font_picker.clone())
|
.child(
|
||||||
})
|
PopoverMenu::new("buffer-font-picker")
|
||||||
.trigger(
|
.menu({
|
||||||
ButtonLike::new("buffer-font-family-button")
|
let buffer_font_picker = buffer_font_picker.clone();
|
||||||
.style(ButtonStyle::Outlined)
|
move |_window, _cx| Some(buffer_font_picker.clone())
|
||||||
.size(ButtonSize::Medium)
|
})
|
||||||
.full_width()
|
.trigger(
|
||||||
.tab_index({
|
ButtonLike::new("buffer-font-family-button")
|
||||||
*tab_index += 1;
|
.style(ButtonStyle::Outlined)
|
||||||
*tab_index - 1
|
.size(ButtonSize::Medium)
|
||||||
})
|
.full_width()
|
||||||
.child(
|
.tab_index({
|
||||||
h_flex()
|
*tab_index += 1;
|
||||||
.w_full()
|
*tab_index - 1
|
||||||
.justify_between()
|
})
|
||||||
.child(Label::new(buffer_font_family))
|
.child(
|
||||||
.child(
|
h_flex()
|
||||||
Icon::new(IconName::ChevronUpDown)
|
.w_full()
|
||||||
.color(Color::Muted)
|
.justify_between()
|
||||||
.size(IconSize::XSmall),
|
.child(Label::new(buffer_font_family))
|
||||||
),
|
.child(
|
||||||
),
|
Icon::new(IconName::ChevronUpDown)
|
||||||
)
|
.color(Color::Muted)
|
||||||
.full_width(true)
|
.size(IconSize::XSmall),
|
||||||
.anchor(gpui::Corner::TopLeft)
|
),
|
||||||
.offset(gpui::Point {
|
),
|
||||||
x: px(0.0),
|
)
|
||||||
y: px(4.0),
|
.full_width(true)
|
||||||
})
|
.anchor(gpui::Corner::TopLeft)
|
||||||
.with_handle(buffer_font_handle),
|
.offset(gpui::Point {
|
||||||
), // .child( todo!
|
x: px(0.0),
|
||||||
// NumericStepper::new(
|
y: px(4.0),
|
||||||
// "buffer-font-size",
|
})
|
||||||
// buffer_font_size.to_string(),
|
.with_handle(buffer_font_handle),
|
||||||
// move |size, cx| {
|
)
|
||||||
// write_buffer_font_size(Pixels::from(size), cx);
|
.child(font_picker_stepper(
|
||||||
// },
|
"buffer-font-size",
|
||||||
// move |_, _, cx| {
|
&buffer_font_size,
|
||||||
// write_buffer_font_size(buffer_font_size - px(1.), cx);
|
tab_index,
|
||||||
// },
|
write_buffer_font_size,
|
||||||
// move |_, _, cx| {
|
window,
|
||||||
// write_buffer_font_size(buffer_font_size + px(1.), cx);
|
cx,
|
||||||
// },
|
)),
|
||||||
// window,
|
|
||||||
// cx,
|
|
||||||
// )
|
|
||||||
// .style(ui_input::NumericStepperStyle::Outlined)
|
|
||||||
// .tab_index({
|
|
||||||
// *tab_index += 2;
|
|
||||||
// *tab_index - 2
|
|
||||||
// }),
|
|
||||||
// ),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn font_picker_stepper(
|
||||||
|
id: &'static str,
|
||||||
|
font_size: &Pixels,
|
||||||
|
tab_index: &mut isize,
|
||||||
|
write_font_size: fn(Pixels, &mut App),
|
||||||
|
window: &mut Window,
|
||||||
|
cx: &mut App,
|
||||||
|
) -> NumericStepper<u32> {
|
||||||
|
window.with_id(id, |window| {
|
||||||
|
let optimistic_font_size: gpui::Entity<Option<u32>> = window.use_state(cx, |_, _| None);
|
||||||
|
optimistic_font_size.update(cx, |optimistic_font_size, _| {
|
||||||
|
if let Some(optimistic_font_size_val) = optimistic_font_size {
|
||||||
|
if *optimistic_font_size_val == font_size.0 as u32 {
|
||||||
|
*optimistic_font_size = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let stepper_font_size = optimistic_font_size
|
||||||
|
.read(cx)
|
||||||
|
.unwrap_or_else(|| font_size.0 as u32);
|
||||||
|
|
||||||
|
NumericStepper::new(
|
||||||
|
SharedString::new(format!("{}-stepper", id)),
|
||||||
|
stepper_font_size,
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
.on_change(move |new_value, _, cx| {
|
||||||
|
optimistic_font_size.write(cx, Some(*new_value));
|
||||||
|
write_font_size(Pixels::from(*new_value), cx);
|
||||||
|
})
|
||||||
|
.style(ui_input::NumericStepperStyle::Outlined)
|
||||||
|
.tab_index({
|
||||||
|
*tab_index += 2;
|
||||||
|
*tab_index - 2
|
||||||
|
})
|
||||||
|
.min(6)
|
||||||
|
.max(32)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
type FontPicker = Picker<FontPickerDelegate>;
|
type FontPicker = Picker<FontPickerDelegate>;
|
||||||
|
|
||||||
pub struct FontPickerDelegate {
|
pub struct FontPickerDelegate {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::{
|
use std::{
|
||||||
fmt::Display,
|
fmt::Display,
|
||||||
ops::{Add, Sub},
|
ops::{Add, Sub},
|
||||||
|
rc::Rc,
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -115,7 +116,7 @@ impl_numeric_stepper_int!(u64);
|
||||||
#[derive(RegisterComponent)]
|
#[derive(RegisterComponent)]
|
||||||
pub struct NumericStepper<T = usize> {
|
pub struct NumericStepper<T = usize> {
|
||||||
id: ElementId,
|
id: ElementId,
|
||||||
value: Entity<T>,
|
value: T,
|
||||||
style: NumericStepperStyle,
|
style: NumericStepperStyle,
|
||||||
focus_handle: FocusHandle,
|
focus_handle: FocusHandle,
|
||||||
mode: Entity<NumericStepperMode>,
|
mode: Entity<NumericStepperMode>,
|
||||||
|
@ -126,16 +127,12 @@ pub struct NumericStepper<T = usize> {
|
||||||
min_value: T,
|
min_value: T,
|
||||||
max_value: T,
|
max_value: T,
|
||||||
on_reset: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
|
on_reset: Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
|
||||||
|
on_change: Rc<dyn Fn(&T, &mut Window, &mut App) + 'static>,
|
||||||
tab_index: Option<isize>,
|
tab_index: Option<isize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: NumericStepperType> NumericStepper<T> {
|
impl<T: NumericStepperType> NumericStepper<T> {
|
||||||
pub fn new(
|
pub fn new(id: impl Into<ElementId>, value: T, window: &mut Window, cx: &mut App) -> Self {
|
||||||
id: impl Into<ElementId>,
|
|
||||||
value: Entity<T>,
|
|
||||||
window: &mut Window,
|
|
||||||
cx: &mut App,
|
|
||||||
) -> Self {
|
|
||||||
let id = id.into();
|
let id = id.into();
|
||||||
|
|
||||||
let (mode, focus_handle) = window.with_id(id.clone(), |window| {
|
let (mode, focus_handle) = window.with_id(id.clone(), |window| {
|
||||||
|
@ -157,6 +154,7 @@ impl<T: NumericStepperType> NumericStepper<T> {
|
||||||
min_value: T::min_value(),
|
min_value: T::min_value(),
|
||||||
max_value: T::max_value(),
|
max_value: T::max_value(),
|
||||||
on_reset: None,
|
on_reset: None,
|
||||||
|
on_change: Rc::new(|_, _, _| {}),
|
||||||
tab_index: None,
|
tab_index: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -208,6 +206,11 @@ impl<T: NumericStepperType> NumericStepper<T> {
|
||||||
self.tab_index = Some(tab_index);
|
self.tab_index = Some(tab_index);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn on_change(mut self, on_change: impl Fn(&T, &mut Window, &mut App) + 'static) -> Self {
|
||||||
|
self.on_change = Rc::new(on_change);
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: NumericStepperType> IntoElement for NumericStepper<T> {
|
impl<T: NumericStepperType> IntoElement for NumericStepper<T> {
|
||||||
|
@ -274,14 +277,14 @@ impl<T: NumericStepperType> RenderOnce for NumericStepper<T> {
|
||||||
.map(|decrement| {
|
.map(|decrement| {
|
||||||
let decrement_handler = {
|
let decrement_handler = {
|
||||||
let value = self.value.clone();
|
let value = self.value.clone();
|
||||||
|
let on_change = self.on_change.clone();
|
||||||
let focus = self.focus_handle.clone();
|
let focus = self.focus_handle.clone();
|
||||||
let min = self.min_value;
|
let min = self.min_value;
|
||||||
move |click: &ClickEvent, window: &mut Window, cx: &mut App| {
|
move |click: &ClickEvent, window: &mut Window, cx: &mut App| {
|
||||||
let step = get_step(click.modifiers());
|
let step = get_step(click.modifiers());
|
||||||
let current_value = *value.read(cx);
|
let new_value = value - step;
|
||||||
let new_value = current_value - step;
|
|
||||||
let new_value = if new_value < min { min } else { new_value };
|
let new_value = if new_value < min { min } else { new_value };
|
||||||
value.write(cx, new_value);
|
on_change(&new_value, window, cx);
|
||||||
window.focus(&focus);
|
window.focus(&focus);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -328,7 +331,7 @@ impl<T: NumericStepperType> RenderOnce for NumericStepper<T> {
|
||||||
.child(match *self.mode.read(cx) {
|
.child(match *self.mode.read(cx) {
|
||||||
NumericStepperMode::Read => div()
|
NumericStepperMode::Read => div()
|
||||||
.id("numeric_stepper_label")
|
.id("numeric_stepper_label")
|
||||||
.child(Label::new((self.format)(self.value.read(cx))).mx_3())
|
.child(Label::new((self.format)(&self.value)).mx_3())
|
||||||
.on_click({
|
.on_click({
|
||||||
let mode = self.mode.clone();
|
let mode = self.mode.clone();
|
||||||
|
|
||||||
|
@ -347,17 +350,13 @@ impl<T: NumericStepperType> RenderOnce for NumericStepper<T> {
|
||||||
|window, cx| {
|
|window, cx| {
|
||||||
let mut editor = Editor::single_line(window, cx);
|
let mut editor = Editor::single_line(window, cx);
|
||||||
|
|
||||||
editor.set_text(
|
editor.set_text(format!("{}", self.value), window, cx);
|
||||||
format!("{}", self.value.read(cx)),
|
|
||||||
window,
|
|
||||||
cx,
|
|
||||||
);
|
|
||||||
cx.on_focus_out(&editor.focus_handle(cx), window, {
|
cx.on_focus_out(&editor.focus_handle(cx), window, {
|
||||||
let mode = self.mode.clone();
|
let mode = self.mode.clone();
|
||||||
let value = self.value.clone();
|
|
||||||
let min = self.min_value;
|
let min = self.min_value;
|
||||||
let max = self.max_value;
|
let max = self.max_value;
|
||||||
move |this, _, _window, cx| {
|
let on_change = self.on_change.clone();
|
||||||
|
move |this, _, window, cx| {
|
||||||
if let Ok(new_value) =
|
if let Ok(new_value) =
|
||||||
this.text(cx).parse::<T>()
|
this.text(cx).parse::<T>()
|
||||||
{
|
{
|
||||||
|
@ -368,7 +367,8 @@ impl<T: NumericStepperType> RenderOnce for NumericStepper<T> {
|
||||||
} else {
|
} else {
|
||||||
new_value
|
new_value
|
||||||
};
|
};
|
||||||
value.write(cx, new_value);
|
|
||||||
|
on_change(&new_value, window, cx);
|
||||||
};
|
};
|
||||||
mode.write(cx, NumericStepperMode::Read);
|
mode.write(cx, NumericStepperMode::Read);
|
||||||
}
|
}
|
||||||
|
@ -397,13 +397,13 @@ impl<T: NumericStepperType> RenderOnce for NumericStepper<T> {
|
||||||
let increment_handler = {
|
let increment_handler = {
|
||||||
let value = self.value.clone();
|
let value = self.value.clone();
|
||||||
let focus = self.focus_handle.clone();
|
let focus = self.focus_handle.clone();
|
||||||
|
let on_change = self.on_change.clone();
|
||||||
let max = self.max_value;
|
let max = self.max_value;
|
||||||
move |click: &ClickEvent, window: &mut Window, cx: &mut App| {
|
move |click: &ClickEvent, window: &mut Window, cx: &mut App| {
|
||||||
let step = get_step(click.modifiers());
|
let step = get_step(click.modifiers());
|
||||||
let current_value = *value.read(cx);
|
let new_value = value + step;
|
||||||
let new_value = current_value + step;
|
|
||||||
let new_value = if new_value > max { max } else { new_value };
|
let new_value = if new_value > max { max } else { new_value };
|
||||||
value.write(cx, new_value);
|
on_change(&new_value, window, cx);
|
||||||
window.focus(&focus);
|
window.focus(&focus);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -474,20 +474,28 @@ impl Component for NumericStepper<usize> {
|
||||||
"Default",
|
"Default",
|
||||||
NumericStepper::new(
|
NumericStepper::new(
|
||||||
"numeric-stepper-component-preview",
|
"numeric-stepper-component-preview",
|
||||||
first_stepper,
|
*first_stepper.read(cx),
|
||||||
window,
|
window,
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
|
.on_change({
|
||||||
|
let first_stepper = first_stepper.clone();
|
||||||
|
move |value, _, cx| first_stepper.write(cx, *value)
|
||||||
|
})
|
||||||
.into_any_element(),
|
.into_any_element(),
|
||||||
),
|
),
|
||||||
single_example(
|
single_example(
|
||||||
"Outlined",
|
"Outlined",
|
||||||
NumericStepper::new(
|
NumericStepper::new(
|
||||||
"numeric-stepper-with-border-component-preview",
|
"numeric-stepper-with-border-component-preview",
|
||||||
second_stepper,
|
*second_stepper.read(cx),
|
||||||
window,
|
window,
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
|
.on_change({
|
||||||
|
let second_stepper = second_stepper.clone();
|
||||||
|
move |value, _, cx| second_stepper.write(cx, *value)
|
||||||
|
})
|
||||||
.min(1.0)
|
.min(1.0)
|
||||||
.max(100.0)
|
.max(100.0)
|
||||||
.style(NumericStepperStyle::Outlined)
|
.style(NumericStepperStyle::Outlined)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue