From c3d30ca92c55b1b7677c547b71d0aebeea5f9188 Mon Sep 17 00:00:00 2001 From: Ygg01 <y.laughing.man.y@gmail.com> Date: Sat, 11 Jun 2022 15:46:19 +0200 Subject: [PATCH] Revert "Tried generic spinbox" This reverts commit 99431431ecd0844925b0b5d9a3b2f666b839f242. --- examples/text_box.rs | 6 +- src/widgets/spin_box.rs | 289 +++++++++++++++++----------------------- 2 files changed, 123 insertions(+), 172 deletions(-) diff --git a/examples/text_box.rs b/examples/text_box.rs index 26e1366..5a51d02 100644 --- a/examples/text_box.rs +++ b/examples/text_box.rs @@ -18,7 +18,7 @@ fn TextBoxExample() { let (value, set_value, _) = use_state!("I started with a value!".to_string()); let (empty_value, set_empty_value, _) = use_state!("".to_string()); let (red_value, set_red_value, _) = use_state!("This text is red".to_string()); - let (spin_value, set_spin_value, _) = use_state!(3.0f32); + let (spin_value, set_spin_value, _) = use_state!("3".to_string()); let input_styles = Style { top: StyleProp::Value(Units::Pixels(10.0)), @@ -43,7 +43,7 @@ fn TextBoxExample() { }); let on_change_spin = OnChange::new(move |event| { - set_spin_value(32.0); + set_spin_value(event.value); }); rsx! { @@ -56,7 +56,7 @@ fn TextBoxExample() { placeholder={Some("This is a placeholder".to_string())} /> <TextBox styles={Some(red_text_styles)} value={red_value} on_change={Some(on_change_red)} /> - <SpinBox<f32> styles={Some(input_styles)} value={spin_value} on_change={Some(on_change_spin)} /> + <SpinBox styles={Some(input_styles)} value={spin_value} on_change={Some(on_change_spin)} /> </Window> } } diff --git a/src/widgets/spin_box.rs b/src/widgets/spin_box.rs index b43aa4d..fa160c1 100644 --- a/src/widgets/spin_box.rs +++ b/src/widgets/spin_box.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use crate::{ core::{ render_command::RenderCommand, @@ -11,19 +9,13 @@ use crate::{ }; use kayak_core::{ styles::{LayoutType, StyleProp}, - CursorIcon, Index, OnLayout, Widget, + CursorIcon, OnLayout, }; use crate::widgets::{Background, Clip, OnChange, Text}; -#[derive(Debug, PartialEq, Clone, Default)] -pub struct SpinBox<T> { - pub id: Index, - pub props: SpinBoxProps<T>, -} - #[derive(Debug, PartialEq, Clone)] -pub struct SpinBoxProps<T> { +pub struct SpinBoxProps { /// If true, prevents the widget from being focused (and consequently edited) pub disabled: bool, /// A callback for when the text value was changed @@ -34,7 +26,7 @@ pub struct SpinBoxProps<T> { /// /// This is a controlled state. You _must_ set this to the value to you wish to be displayed. /// You can use the [`on_change`] callback to update this prop as the user types. - pub value: Option<T>, + pub value: String, pub styles: Option<Style>, /// Text on increment button defaults to `>` pub incr_str: String, @@ -46,13 +38,14 @@ pub struct SpinBoxProps<T> { pub focusable: Option<bool>, } -impl<T> Default for SpinBoxProps<T> { - fn default() -> SpinBoxProps<T> { - Self { + +impl Default for SpinBoxProps { + fn default() -> SpinBoxProps { + SpinBoxProps { incr_str: ">".into(), decr_str: "<".into(), disabled: Default::default(), - on_change: Default::default(), + on_change: Default::default(), placeholder: Default::default(), value: Default::default(), styles: Default::default(), @@ -64,10 +57,7 @@ impl<T> Default for SpinBoxProps<T> { } } -impl<T> WidgetProps for SpinBoxProps<T> -where - T: Widget, -{ +impl WidgetProps for SpinBoxProps { fn get_children(&self) -> Option<Children> { self.children.clone() } @@ -96,6 +86,7 @@ where #[derive(Debug, Clone, Copy, PartialEq)] pub struct FocusSpinbox(pub bool); +#[widget] /// A widget that displays a spinnable text field /// /// # Props @@ -110,161 +101,121 @@ pub struct FocusSpinbox(pub bool); /// | `on_layout` | ✅ | /// | `focusable` | ✅ | /// -impl<T> Widget for SpinBox<T> -where - T: Widget + ToString + FromStr + Default, -{ - type Props = SpinBoxProps<T>; - - fn constructor(props: Self::Props) -> Self - where - Self: Sized, - { - Self { - id: Index::default(), - props, - } - } - - fn get_id(&self) -> Index { - self.id - } - - fn set_id(&mut self, id: Index) { - self.id = id; - } - - fn get_props(&self) -> &Self::Props { - &self.props - } - - fn get_props_mut(&mut self) -> &mut Self::Props { - &mut self.props - } - - fn render(&mut self, context: &mut kayak_core::KayakContextRef) { - let children = self.props.get_children(); - let mut props = self.props.clone(); - let SpinBoxProps { - on_change, - placeholder, - value, - .. - } = props.clone(); - - props.styles = Some( - Style::default() - // Required styles - .with_style(Style { - render_command: RenderCommand::Layout.into(), - ..Default::default() - }) - // Apply any prop-given styles - .with_style(&props.styles) - // If not set by props, apply these styles - .with_style(Style { - top: Units::Pixels(0.0).into(), - bottom: Units::Pixels(0.0).into(), - height: Units::Pixels(26.0).into(), - cursor: CursorIcon::Text.into(), - ..Default::default() - }), - ); - - let background_styles = Style { - background_color: Color::new(0.176, 0.196, 0.215, 1.0).into(), - border_radius: Corner::all(5.0).into(), - height: Units::Pixels(26.0).into(), - padding_left: Units::Pixels(5.0).into(), - padding_right: Units::Pixels(5.0).into(), - ..Default::default() - }; - - let has_focus = context.create_state(FocusSpinbox(false)).unwrap(); - let mut current_value = value.clone().map_or(String::new(), |f| { f.to_string()}); - let cloned_on_change = on_change.clone(); - let cloned_has_focus = has_focus.clone(); - - props.on_event = Some(OnEvent::new(move |_, event| match event.event_type { - EventType::CharInput { c } => { - if !cloned_has_focus.get().0 { - return; - } - if is_backspace(c) { - if !current_value.is_empty() { - current_value.truncate(current_value.len() - 1); - } - } else if !c.is_control() { - current_value.push(c); - } - if let Some(on_change) = cloned_on_change.as_ref() { - if let Ok(mut on_change) = on_change.0.write() { - on_change(ChangeEvent { - value: current_value.clone(), - }); - } - } +pub fn SpinBox(props: SpinBoxProps) { + let SpinBoxProps { + on_change, + placeholder, + value, + .. + } = props.clone(); + + props.styles = Some( + Style::default() + // Required styles + .with_style(Style { + render_command: RenderCommand::Layout.into(), + ..Default::default() + }) + // Apply any prop-given styles + .with_style(&props.styles) + // If not set by props, apply these styles + .with_style(Style { + top: Units::Pixels(0.0).into(), + bottom: Units::Pixels(0.0).into(), + height: Units::Pixels(26.0).into(), + cursor: CursorIcon::Text.into(), + ..Default::default() + }), + ); + + let background_styles = Style { + background_color: Color::new(0.176, 0.196, 0.215, 1.0).into(), + border_radius: Corner::all(5.0).into(), + height: Units::Pixels(26.0).into(), + padding_left: Units::Pixels(5.0).into(), + padding_right: Units::Pixels(5.0).into(), + ..Default::default() + }; + + let has_focus = context.create_state(FocusSpinbox(false)).unwrap(); + + let mut current_value = value.clone(); + let cloned_on_change = on_change.clone(); + let cloned_has_focus = has_focus.clone(); + + props.on_event = Some(OnEvent::new(move |_, event| match event.event_type { + EventType::CharInput { c } => { + if !cloned_has_focus.get().0 { + return; } - EventType::Focus => cloned_has_focus.set(FocusSpinbox(true)), - EventType::Blur => cloned_has_focus.set(FocusSpinbox(false)), - _ => {} - })); - - let text_styles = if value.is_none() || (has_focus.get().0 && value.is_none()) { - Style { - color: Color::new(0.5, 0.5, 0.5, 1.0).into(), - ..Style::default() + if is_backspace(c) { + if !current_value.is_empty() { + current_value.truncate(current_value.len() - 1); + } + } else if !c.is_control() { + current_value.push(c); } - } else { - Style { - width: Units::Stretch(100.0).into(), - ..Style::default() + if let Some(on_change) = cloned_on_change.as_ref() { + if let Ok(mut on_change) = on_change.0.write() { + on_change(ChangeEvent { + value: current_value.clone(), + }); + } } - }; - - let button_style = Some(Style { - height: Units::Pixels(24.0).into(), - width: Units::Pixels(24.0).into(), - ..Default::default() - }); - - // if current_value.is_empty() { - // current_value = placeholder.unwrap_or(current_value); - // }; - - // let value = if current_value.is_empty() { - // None - // } else { - // T::from_str(¤t_value).ok() - // }; - - let inline_style = Style { - layout_type: StyleProp::Value(LayoutType::Row), + } + EventType::Focus => cloned_has_focus.set(FocusSpinbox(true)), + EventType::Blur => cloned_has_focus.set(FocusSpinbox(false)), + _ => {} + })); + + let text_styles = if value.is_empty() || (has_focus.get().0 && value.is_empty()) { + Style { + color: Color::new(0.5, 0.5, 0.5, 1.0).into(), + ..Style::default() + } + } else { + Style { + width: Units::Stretch(100.0).into(), ..Style::default() - }; - - let incr_str = props.clone().incr_str; - let decr_str = props.clone().decr_str; - let content = value.clone().map_or(String::new(), |f| { f.to_string()}); - - - rsx! { - <Background styles={Some(background_styles)}> - <Clip styles={Some(inline_style)}> - <Button styles={button_style}> - <Text content={decr_str} /> - </Button> - <Text - content={content} - size={14.0} - styles={Some(text_styles)} - /> - <Button styles={button_style}> - <Text content={incr_str} /> - </Button> - </Clip> - </Background> } + }; + + let button_style = Some(Style { + height: Units::Pixels(24.0).into(), + width: Units::Pixels(24.0).into(), + ..Default::default() + }); + + let value = if value.is_empty() { + placeholder.unwrap_or_else(|| value.clone()) + } else { + value + }; + + let inline_style = Style { + layout_type: StyleProp::Value(LayoutType::Row), + ..Style::default() + }; + + let incr_str = props.clone().incr_str; + let decr_str = props.clone().decr_str; + + rsx! { + <Background styles={Some(background_styles)}> + <Clip styles={Some(inline_style)}> + <Button styles={button_style}> + <Text content={decr_str} /> + </Button> + <Text + content={value} + size={14.0} + styles={Some(text_styles)} + /> + <Button styles={button_style}> + <Text content={incr_str} /> + </Button> + </Clip> + </Background> } } -- GitLab