Refactor Slider, Input, InputOtp to use EventEmiter to emit change (#45)
This commit is contained in:
parent
f6146220e4
commit
bac5392e0a
7 changed files with 108 additions and 107 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, AppContext, ClickEvent, FocusHandle, InteractiveElement, IntoElement, KeyBinding,
|
actions, AppContext, FocusHandle, InteractiveElement, IntoElement, KeyBinding,
|
||||||
ParentElement as _, Render, SharedString, Styled, View, ViewContext, VisualContext,
|
ParentElement as _, Render, SharedString, Styled, View, ViewContext, VisualContext,
|
||||||
WindowContext,
|
WindowContext,
|
||||||
};
|
};
|
||||||
|
|
@ -7,7 +7,7 @@ use gpui::{
|
||||||
use ui::{
|
use ui::{
|
||||||
button::Button,
|
button::Button,
|
||||||
h_flex,
|
h_flex,
|
||||||
input::{InputOtp, TextEvent, TextInput},
|
input::{InputEvent, InputOtp, TextInput},
|
||||||
prelude::FluentBuilder as _,
|
prelude::FluentBuilder as _,
|
||||||
v_flex, Clickable, FocusableCycle, IconName, Size,
|
v_flex, Clickable, FocusableCycle, IconName, Size,
|
||||||
};
|
};
|
||||||
|
|
@ -86,16 +86,15 @@ impl InputStory {
|
||||||
.placeholder("This input have prefix and suffix.")
|
.placeholder("This input have prefix and suffix.")
|
||||||
});
|
});
|
||||||
|
|
||||||
let view = cx.view().clone();
|
let otp_input = cx.new_view(|cx| InputOtp::new(6, cx).masked(true));
|
||||||
let otp_input = cx.new_view(|cx| {
|
cx.subscribe(&otp_input, |this, _, ev: &InputEvent, cx| match ev {
|
||||||
InputOtp::new(6, cx)
|
InputEvent::Change(text) => {
|
||||||
.masked(true)
|
this.otp_value = Some(text.clone());
|
||||||
.on_change(move |value: &SharedString, cx| {
|
cx.notify();
|
||||||
view.update(cx, |view, _| {
|
}
|
||||||
view.otp_value = Some(value.clone());
|
_ => {}
|
||||||
})
|
})
|
||||||
})
|
.detach();
|
||||||
});
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
input1,
|
input1,
|
||||||
|
|
@ -126,11 +125,6 @@ impl InputStory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
fn on_change(ev: &ClickEvent, cx: &mut WindowContext) {
|
|
||||||
println!("Input changed: {:?}", ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
|
fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
|
||||||
self.cycle_focus(true, cx);
|
self.cycle_focus(true, cx);
|
||||||
}
|
}
|
||||||
|
|
@ -142,14 +136,14 @@ impl InputStory {
|
||||||
fn on_input_event(
|
fn on_input_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: View<TextInput>,
|
_: View<TextInput>,
|
||||||
event: &TextEvent,
|
event: &InputEvent,
|
||||||
_cx: &mut ViewContext<Self>,
|
_cx: &mut ViewContext<Self>,
|
||||||
) {
|
) {
|
||||||
match event {
|
match event {
|
||||||
TextEvent::Input { text } => println!("Input: {}", text),
|
InputEvent::Change(text) => println!("Change: {}", text),
|
||||||
TextEvent::PressEnter => println!("PressEnter"),
|
InputEvent::PressEnter => println!("PressEnter"),
|
||||||
TextEvent::Focus => println!("Focus"),
|
InputEvent::Focus => println!("Focus"),
|
||||||
TextEvent::Blur => println!("Blur"),
|
InputEvent::Blur => println!("Blur"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -183,25 +177,35 @@ impl Render for InputStory {
|
||||||
.justify_start()
|
.justify_start()
|
||||||
.gap_3()
|
.gap_3()
|
||||||
.child(
|
.child(
|
||||||
section("Normal Input", cx)
|
h_flex()
|
||||||
.child(self.input1.clone())
|
.gap_3()
|
||||||
.child(self.input2.clone()),
|
.items_start()
|
||||||
|
.child(
|
||||||
|
section("Normal Input", cx)
|
||||||
|
.child(self.input1.clone())
|
||||||
|
.child(self.input2.clone()),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
section("Input State", cx)
|
||||||
|
.child(self.disabled_input.clone())
|
||||||
|
.child(self.mash_input.clone()),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
section("Input State", cx)
|
h_flex()
|
||||||
.child(self.disabled_input.clone())
|
.gap_3()
|
||||||
.child(self.mash_input.clone()),
|
.items_start()
|
||||||
)
|
.child(
|
||||||
.child(
|
section("Preifx and Suffix", cx)
|
||||||
section("Preifx and Suffix", cx)
|
.child(self.prefix_input1.clone())
|
||||||
.child(self.prefix_input1.clone())
|
.child(self.both_input1.clone())
|
||||||
.child(self.both_input1.clone())
|
.child(self.suffix_input1.clone()),
|
||||||
.child(self.suffix_input1.clone()),
|
)
|
||||||
)
|
.child(
|
||||||
.child(
|
section("Input Size", cx)
|
||||||
section("Input Size", cx)
|
.child(self.large_input.clone())
|
||||||
.child(self.large_input.clone())
|
.child(self.small_input.clone()),
|
||||||
.child(self.small_input.clone()),
|
),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
section("Input OTP", cx).child(
|
section("Input OTP", cx).child(
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,13 @@ use gpui::{
|
||||||
WindowContext,
|
WindowContext,
|
||||||
};
|
};
|
||||||
use ui::{
|
use ui::{
|
||||||
button::Button, divider::Divider, h_flex, indicator::Indicator, progress::Progress,
|
button::Button,
|
||||||
slider::Slider, v_flex, Clickable, IconName, Size,
|
divider::Divider,
|
||||||
|
h_flex,
|
||||||
|
indicator::Indicator,
|
||||||
|
progress::Progress,
|
||||||
|
slider::{Slider, SliderEvent},
|
||||||
|
v_flex, Clickable, IconName, Size,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct ProgressStory {
|
pub struct ProgressStory {
|
||||||
|
|
@ -21,31 +26,36 @@ impl ProgressStory {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new(cx: &mut ViewContext<Self>) -> Self {
|
fn new(cx: &mut ViewContext<Self>) -> Self {
|
||||||
let slider1 = Slider::horizontal()
|
let slider1 = cx.new_view(|_| {
|
||||||
.min(-255.)
|
Slider::horizontal()
|
||||||
.max(255.)
|
.min(-255.)
|
||||||
.default_value(15.)
|
.max(255.)
|
||||||
.step(15.)
|
.default_value(15.)
|
||||||
.on_change(cx.listener(|this, value, cx| {
|
.step(15.)
|
||||||
|
});
|
||||||
|
cx.subscribe(&slider1, |this, _, event: &SliderEvent, cx| match event {
|
||||||
|
SliderEvent::Change(value) => {
|
||||||
this.slider1_value = *value;
|
this.slider1_value = *value;
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}));
|
}
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
|
||||||
let slider2 = Slider::horizontal()
|
let slider2 = cx.new_view(|_| Slider::horizontal().min(0.).max(5.).step(1.0));
|
||||||
.min(0.)
|
cx.subscribe(&slider2, |this, _, event: &SliderEvent, cx| match event {
|
||||||
.max(5.)
|
SliderEvent::Change(value) => {
|
||||||
.step(1.0)
|
|
||||||
.on_change(cx.listener(|this, value, cx| {
|
|
||||||
this.slider2_value = *value;
|
this.slider2_value = *value;
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}));
|
}
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
value: 50.,
|
value: 50.,
|
||||||
slider1_value: 15.,
|
slider1_value: 15.,
|
||||||
slider2_value: 1.,
|
slider2_value: 1.,
|
||||||
slider1: cx.new_view(|_| slider1),
|
slider1,
|
||||||
slider2: cx.new_view(|_| slider2),
|
slider2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use gpui::{
|
||||||
use ui::{
|
use ui::{
|
||||||
button::Button,
|
button::Button,
|
||||||
h_flex,
|
h_flex,
|
||||||
input::{TextEvent, TextInput},
|
input::{InputEvent, TextInput},
|
||||||
theme::ActiveTheme,
|
theme::ActiveTheme,
|
||||||
v_flex,
|
v_flex,
|
||||||
webview::WebView,
|
webview::WebView,
|
||||||
|
|
@ -44,8 +44,8 @@ impl WebViewStory {
|
||||||
|
|
||||||
cx.subscribe(
|
cx.subscribe(
|
||||||
&address_input,
|
&address_input,
|
||||||
|this: &mut Self, input, event: &TextEvent, cx| match event {
|
|this: &mut Self, input, event: &InputEvent, cx| match event {
|
||||||
TextEvent::PressEnter => {
|
InputEvent::PressEnter => {
|
||||||
let url = input.read(cx).text();
|
let url = input.read(cx).text();
|
||||||
this.webview.update(cx, |view, _| {
|
this.webview.update(cx, |view, _| {
|
||||||
view.load_url(&url);
|
view.load_url(&url);
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,8 @@ actions!(
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
pub enum TextEvent {
|
pub enum InputEvent {
|
||||||
Input { text: SharedString },
|
Change(SharedString),
|
||||||
PressEnter,
|
PressEnter,
|
||||||
Focus,
|
Focus,
|
||||||
Blur,
|
Blur,
|
||||||
|
|
@ -113,7 +113,7 @@ pub struct TextInput {
|
||||||
size: Size,
|
size: Size,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventEmitter<TextEvent> for TextInput {}
|
impl EventEmitter<InputEvent> for TextInput {}
|
||||||
|
|
||||||
impl TextInput {
|
impl TextInput {
|
||||||
pub fn new(cx: &mut ViewContext<Self>) -> Self {
|
pub fn new(cx: &mut ViewContext<Self>) -> Self {
|
||||||
|
|
@ -292,7 +292,7 @@ impl TextInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enter(&mut self, _: &Enter, cx: &mut ViewContext<Self>) {
|
fn enter(&mut self, _: &Enter, cx: &mut ViewContext<Self>) {
|
||||||
cx.emit(TextEvent::PressEnter);
|
cx.emit(InputEvent::PressEnter);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clean(&mut self, _: &ClickEvent, cx: &mut ViewContext<Self>) {
|
fn clean(&mut self, _: &ClickEvent, cx: &mut ViewContext<Self>) {
|
||||||
|
|
@ -505,7 +505,7 @@ impl TextInput {
|
||||||
self.blink_cursor.update(cx, |cursor, cx| {
|
self.blink_cursor.update(cx, |cursor, cx| {
|
||||||
cursor.start(cx);
|
cursor.start(cx);
|
||||||
});
|
});
|
||||||
cx.emit(TextEvent::Focus);
|
cx.emit(InputEvent::Focus);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
|
|
@ -513,7 +513,7 @@ impl TextInput {
|
||||||
self.blink_cursor.update(cx, |cursor, cx| {
|
self.blink_cursor.update(cx, |cursor, cx| {
|
||||||
cursor.stop(cx);
|
cursor.stop(cx);
|
||||||
});
|
});
|
||||||
cx.emit(TextEvent::Blur);
|
cx.emit(InputEvent::Blur);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pause_blink_cursor(&mut self, cx: &mut ViewContext<Self>) {
|
fn pause_blink_cursor(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
|
|
@ -571,9 +571,7 @@ impl ViewInputHandler for TextInput {
|
||||||
(self.text[0..range.start].to_owned() + new_text + &self.text[range.end..]).into();
|
(self.text[0..range.start].to_owned() + new_text + &self.text[range.end..]).into();
|
||||||
self.selected_range = range.start + new_text.len()..range.start + new_text.len();
|
self.selected_range = range.start + new_text.len()..range.start + new_text.len();
|
||||||
self.marked_range.take();
|
self.marked_range.take();
|
||||||
cx.emit(TextEvent::Input {
|
cx.emit(InputEvent::Change(self.text.clone()));
|
||||||
text: self.text.clone(),
|
|
||||||
});
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -602,9 +600,7 @@ impl ViewInputHandler for TextInput {
|
||||||
.map(|range_utf16| self.range_from_utf16(range_utf16))
|
.map(|range_utf16| self.range_from_utf16(range_utf16))
|
||||||
.map(|new_range| new_range.start + range.start..new_range.end + range.end)
|
.map(|new_range| new_range.start + range.start..new_range.end + range.end)
|
||||||
.unwrap_or_else(|| range.start + new_text.len()..range.start + new_text.len());
|
.unwrap_or_else(|| range.start + new_text.len()..range.start + new_text.len());
|
||||||
cx.emit(TextEvent::Input {
|
cx.emit(InputEvent::Change(self.text.clone()));
|
||||||
text: self.text.clone(),
|
|
||||||
});
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,17 @@
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, prelude::FluentBuilder as _, AnyElement, Context, FocusHandle, FocusableView,
|
div, prelude::FluentBuilder as _, AnyElement, Context, EventEmitter, FocusHandle,
|
||||||
InteractiveElement, IntoElement, KeyDownEvent, Model, MouseButton, MouseDownEvent,
|
FocusableView, InteractiveElement, IntoElement, KeyDownEvent, Model, MouseButton,
|
||||||
ParentElement as _, Render, SharedString, Styled as _, ViewContext, WindowContext,
|
MouseDownEvent, ParentElement as _, Render, SharedString, Styled as _, ViewContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{h_flex, theme::ActiveTheme, v_flex};
|
use crate::{h_flex, theme::ActiveTheme, v_flex};
|
||||||
|
|
||||||
use super::blink_cursor::BlinkCursor;
|
use super::{blink_cursor::BlinkCursor, InputEvent};
|
||||||
|
|
||||||
|
pub enum InputOptEvent {
|
||||||
|
/// When all OTP input have filled, this event will be triggered.
|
||||||
|
Change(SharedString),
|
||||||
|
}
|
||||||
|
|
||||||
pub struct InputOtp {
|
pub struct InputOtp {
|
||||||
focus_handle: FocusHandle,
|
focus_handle: FocusHandle,
|
||||||
|
|
@ -15,7 +20,6 @@ pub struct InputOtp {
|
||||||
masked: bool,
|
masked: bool,
|
||||||
value: SharedString,
|
value: SharedString,
|
||||||
blink_cursor: Model<BlinkCursor>,
|
blink_cursor: Model<BlinkCursor>,
|
||||||
on_change: Option<Box<dyn Fn(&SharedString, &mut WindowContext) + 'static>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InputOtp {
|
impl InputOtp {
|
||||||
|
|
@ -28,7 +32,6 @@ impl InputOtp {
|
||||||
number_of_groups: 2,
|
number_of_groups: 2,
|
||||||
value: SharedString::default(),
|
value: SharedString::default(),
|
||||||
masked: false,
|
masked: false,
|
||||||
on_change: None,
|
|
||||||
blink_cursor: blink_cursor.clone(),
|
blink_cursor: blink_cursor.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -65,15 +68,6 @@ impl InputOtp {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set callback to be called when the value of the OTP Input changes (All OTP input have filled).
|
|
||||||
pub fn on_change<F>(mut self, f: F) -> Self
|
|
||||||
where
|
|
||||||
F: Fn(&SharedString, &mut WindowContext) + 'static,
|
|
||||||
{
|
|
||||||
self.on_change = Some(Box::new(f));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_input_mouse_down(&mut self, _: &MouseDownEvent, cx: &mut ViewContext<Self>) {
|
fn on_input_mouse_down(&mut self, _: &MouseDownEvent, cx: &mut ViewContext<Self>) {
|
||||||
cx.focus(&self.focus_handle);
|
cx.focus(&self.focus_handle);
|
||||||
}
|
}
|
||||||
|
|
@ -108,9 +102,7 @@ impl InputOtp {
|
||||||
self.value = SharedString::from(chars.iter().collect::<String>());
|
self.value = SharedString::from(chars.iter().collect::<String>());
|
||||||
|
|
||||||
if self.value.chars().count() == self.length {
|
if self.value.chars().count() == self.length {
|
||||||
if let Some(on_change) = &self.on_change {
|
cx.emit(InputEvent::Change(self.value.clone()));
|
||||||
on_change(&self.value, cx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
cx.notify()
|
cx.notify()
|
||||||
}
|
}
|
||||||
|
|
@ -119,12 +111,14 @@ impl InputOtp {
|
||||||
self.blink_cursor.update(cx, |cursor, cx| {
|
self.blink_cursor.update(cx, |cursor, cx| {
|
||||||
cursor.start(cx);
|
cursor.start(cx);
|
||||||
});
|
});
|
||||||
|
cx.emit(InputEvent::Focus);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
|
fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
self.blink_cursor.update(cx, |cursor, cx| {
|
self.blink_cursor.update(cx, |cursor, cx| {
|
||||||
cursor.stop(cx);
|
cursor.stop(cx);
|
||||||
});
|
});
|
||||||
|
cx.emit(InputEvent::Blur);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pause_blink_cursor(&mut self, cx: &mut ViewContext<Self>) {
|
fn pause_blink_cursor(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
|
|
@ -139,6 +133,7 @@ impl FocusableView for InputOtp {
|
||||||
self.focus_handle.clone()
|
self.focus_handle.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl EventEmitter<InputEvent> for InputOtp {}
|
||||||
|
|
||||||
impl Render for InputOtp {
|
impl Render for InputOtp {
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use std::{cell::Cell, rc::Rc};
|
||||||
|
|
||||||
use gpui::prelude::FluentBuilder as _;
|
use gpui::prelude::FluentBuilder as _;
|
||||||
|
|
||||||
use crate::input::{TextEvent, TextInput};
|
use crate::input::{InputEvent, TextInput};
|
||||||
use crate::scroll::ScrollbarState;
|
use crate::scroll::ScrollbarState;
|
||||||
use crate::theme::{ActiveTheme, Colorize as _};
|
use crate::theme::{ActiveTheme, Colorize as _};
|
||||||
use crate::{scroll::Scrollbar, v_flex};
|
use crate::{scroll::Scrollbar, v_flex};
|
||||||
|
|
@ -157,15 +157,15 @@ where
|
||||||
fn on_query_input_event(
|
fn on_query_input_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: View<TextInput>,
|
_: View<TextInput>,
|
||||||
event: &TextEvent,
|
event: &InputEvent,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) {
|
) {
|
||||||
match event {
|
match event {
|
||||||
TextEvent::Input { text } => {
|
InputEvent::Change(text) => {
|
||||||
self.delegate.perform_search(&text.trim(), cx);
|
self.delegate.perform_search(&text.trim(), cx);
|
||||||
cx.notify()
|
cx.notify()
|
||||||
}
|
}
|
||||||
TextEvent::PressEnter => self.action_confirm(&Confirm, cx),
|
InputEvent::PressEnter => self.action_confirm(&Confirm, cx),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,18 @@ use crate::{
|
||||||
tooltip::Tooltip,
|
tooltip::Tooltip,
|
||||||
};
|
};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
canvas, div, px, relative, Axis, Bounds, DragMoveEvent, EntityId, InteractiveElement,
|
canvas, div, px, relative, Axis, Bounds, DragMoveEvent, EntityId, EventEmitter,
|
||||||
IntoElement, MouseButton, MouseDownEvent, ParentElement as _, Pixels, Point, Render,
|
InteractiveElement, IntoElement, MouseButton, MouseDownEvent, ParentElement as _, Pixels,
|
||||||
StatefulInteractiveElement as _, Styled, ViewContext, VisualContext as _, WindowContext,
|
Point, Render, StatefulInteractiveElement as _, Styled, ViewContext, VisualContext as _,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Render)]
|
#[derive(Clone, Render)]
|
||||||
pub struct DragThumb(EntityId);
|
pub struct DragThumb(EntityId);
|
||||||
|
|
||||||
|
pub enum SliderEvent {
|
||||||
|
Change(f32),
|
||||||
|
}
|
||||||
|
|
||||||
/// A slider component.
|
/// A slider component.
|
||||||
pub struct Slider {
|
pub struct Slider {
|
||||||
axis: Axis,
|
axis: Axis,
|
||||||
|
|
@ -18,7 +22,6 @@ pub struct Slider {
|
||||||
max: f32,
|
max: f32,
|
||||||
step: f32,
|
step: f32,
|
||||||
value: f32,
|
value: f32,
|
||||||
on_change: Option<Box<dyn Fn(&f32, &mut WindowContext) + 'static>>,
|
|
||||||
bounds: Bounds<Pixels>,
|
bounds: Bounds<Pixels>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -30,7 +33,6 @@ impl Slider {
|
||||||
max: 100.0,
|
max: 100.0,
|
||||||
step: 1.0,
|
step: 1.0,
|
||||||
value: 0.0,
|
value: 0.0,
|
||||||
on_change: None,
|
|
||||||
bounds: Bounds::default(),
|
bounds: Bounds::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -63,12 +65,6 @@ impl Slider {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the on_change callback of the slider.
|
|
||||||
pub fn on_change(mut self, on_change: impl Fn(&f32, &mut WindowContext) + 'static) -> Self {
|
|
||||||
self.on_change = Some(Box::new(on_change));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the value of the slider.
|
/// Set the value of the slider.
|
||||||
pub fn set_value(&mut self, value: f32, cx: &mut gpui::ViewContext<Self>) {
|
pub fn set_value(&mut self, value: f32, cx: &mut gpui::ViewContext<Self>) {
|
||||||
self.value = value;
|
self.value = value;
|
||||||
|
|
@ -114,9 +110,7 @@ impl Slider {
|
||||||
let value = (value / step).round() * step;
|
let value = (value / step).round() * step;
|
||||||
|
|
||||||
self.value = value.clamp(self.min, self.max);
|
self.value = value.clamp(self.min, self.max);
|
||||||
if let Some(on_change) = &self.on_change {
|
cx.emit(SliderEvent::Change(self.value));
|
||||||
on_change(&self.value, cx);
|
|
||||||
}
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -160,6 +154,8 @@ impl Slider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl EventEmitter<SliderEvent> for Slider {}
|
||||||
|
|
||||||
impl Render for Slider {
|
impl Render for Slider {
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||||
div()
|
div()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue