Skip to content
Snippets Groups Projects
Unverified Commit dc1ab6b6 authored by Ygg01's avatar Ygg01
Browse files

Finish horizontal and vertical SpinBox

parent c3d30ca9
No related branches found
No related tags found
No related merge requests found
...@@ -11,7 +11,7 @@ use kayak_ui::core::{ ...@@ -11,7 +11,7 @@ use kayak_ui::core::{
styles::{Style, StyleProp, Units}, styles::{Style, StyleProp, Units},
widget, Index, widget, Index,
}; };
use kayak_ui::widgets::{App, Inspector, OnChange, SpinBox, TextBox, Window}; use kayak_ui::widgets::{App, Inspector, OnChange, SpinBox, SpinBoxStyle, TextBox, Window};
#[widget] #[widget]
fn TextBoxExample() { fn TextBoxExample() {
...@@ -46,6 +46,8 @@ fn TextBoxExample() { ...@@ -46,6 +46,8 @@ fn TextBoxExample() {
set_spin_value(event.value); set_spin_value(event.value);
}); });
let vert = SpinBoxStyle::Vertical;
rsx! { rsx! {
<Window position={(50.0, 50.0)} size={(500.0, 300.0)} title={"TextBox Example".to_string()}> <Window position={(50.0, 50.0)} size={(500.0, 300.0)} title={"TextBox Example".to_string()}>
<TextBox styles={Some(input_styles)} value={value} on_change={Some(on_change)} /> <TextBox styles={Some(input_styles)} value={value} on_change={Some(on_change)} />
...@@ -56,7 +58,21 @@ fn TextBoxExample() { ...@@ -56,7 +58,21 @@ fn TextBoxExample() {
placeholder={Some("This is a placeholder".to_string())} placeholder={Some("This is a placeholder".to_string())}
/> />
<TextBox styles={Some(red_text_styles)} value={red_value} on_change={Some(on_change_red)} /> <TextBox styles={Some(red_text_styles)} value={red_value} on_change={Some(on_change_red)} />
<SpinBox 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)}
min_val={0.0}
max_val={10.0}
/>
<SpinBox
spin_button_style={vert}
styles={Some(input_styles)}
value={spin_value}
on_change={Some(on_change_spin)}
min_val={0.0}
max_val={10.0}
/>
</Window> </Window>
} }
} }
...@@ -74,7 +90,6 @@ fn startup( ...@@ -74,7 +90,6 @@ fn startup(
render! { render! {
<App> <App>
<TextBoxExample /> <TextBoxExample />
<Inspector />
</App> </App>
} }
}); });
......
use std::{fmt::Debug, fmt::Formatter, sync::Arc};
use crate::{ use crate::{
core::{ core::{
render_command::RenderCommand, render_command::RenderCommand,
...@@ -11,9 +13,22 @@ use kayak_core::{ ...@@ -11,9 +13,22 @@ use kayak_core::{
styles::{LayoutType, StyleProp}, styles::{LayoutType, StyleProp},
CursorIcon, OnLayout, CursorIcon, OnLayout,
}; };
use kayak_render_macros::use_state;
use crate::widgets::{Background, Clip, OnChange, Text}; use crate::widgets::{Background, Clip, OnChange, Text};
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum SpinBoxStyle {
Horizontal,
Vertical,
}
impl Default for SpinBoxStyle {
fn default() -> Self {
SpinBoxStyle::Horizontal
}
}
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct SpinBoxProps { pub struct SpinBoxProps {
/// If true, prevents the widget from being focused (and consequently edited) /// If true, prevents the widget from being focused (and consequently edited)
...@@ -22,6 +37,8 @@ pub struct SpinBoxProps { ...@@ -22,6 +37,8 @@ pub struct SpinBoxProps {
pub on_change: Option<OnChange>, pub on_change: Option<OnChange>,
/// The text to display when the user input is empty /// The text to display when the user input is empty
pub placeholder: Option<String>, pub placeholder: Option<String>,
/// Whether spinbox is horizontally or vertically aligned.
pub spin_button_style: SpinBoxStyle,
/// The user input /// The user input
/// ///
/// This is a controlled state. You _must_ set this to the value to you wish to be displayed. /// This is a controlled state. You _must_ set this to the value to you wish to be displayed.
...@@ -32,25 +49,55 @@ pub struct SpinBoxProps { ...@@ -32,25 +49,55 @@ pub struct SpinBoxProps {
pub incr_str: String, pub incr_str: String,
/// Text on decrement button defaults to `<` /// Text on decrement button defaults to `<`
pub decr_str: String, pub decr_str: String,
pub children: Option<Children>, /// Events on increment button press
pub on_incr_event: Option<OnEvent>,
/// Events on decrement button press
pub on_decr_event: Option<OnEvent>,
/// Events for text edit
pub on_event: Option<OnEvent>, pub on_event: Option<OnEvent>,
/// Minimal value
pub min_val: f32,
/// Maximal value
pub max_val: f32,
pub children: Option<Children>,
pub on_layout: Option<OnLayout>, pub on_layout: Option<OnLayout>,
pub focusable: Option<bool>, pub focusable: Option<bool>,
} }
impl SpinBoxProps {
pub fn get_float(&self) -> f32 {
self.value.parse::<f32>().unwrap_or_default()
}
pub fn get_int(&self) -> i16 {
let temp_float = self.get_float();
if temp_float > f32::from(i16::MAX) {
i16::MAX
} else if temp_float < f32::from(i16::MIN) {
i16::MIN
} else {
temp_float.round() as i16
}
}
}
impl Default for SpinBoxProps { impl Default for SpinBoxProps {
fn default() -> SpinBoxProps { fn default() -> SpinBoxProps {
SpinBoxProps { SpinBoxProps {
incr_str: ">".into(), incr_str: "+".into(),
decr_str: "<".into(), decr_str: "-".into(),
disabled: Default::default(), disabled: Default::default(),
on_change: Default::default(), on_change: Default::default(),
placeholder: Default::default(), placeholder: Default::default(),
value: Default::default(), value: Default::default(),
styles: Default::default(), styles: Default::default(),
spin_button_style: Default::default(),
children: Default::default(), children: Default::default(),
on_incr_event: Default::default(),
on_decr_event: Default::default(),
on_event: Default::default(), on_event: Default::default(),
min_val: f32::MIN,
max_val: f32::MAX,
on_layout: Default::default(), on_layout: Default::default(),
focusable: Default::default(), focusable: Default::default(),
} }
...@@ -106,6 +153,9 @@ pub fn SpinBox(props: SpinBoxProps) { ...@@ -106,6 +153,9 @@ pub fn SpinBox(props: SpinBoxProps) {
on_change, on_change,
placeholder, placeholder,
value, value,
max_val,
min_val,
spin_button_style,
.. ..
} = props.clone(); } = props.clone();
...@@ -180,11 +230,19 @@ pub fn SpinBox(props: SpinBoxProps) { ...@@ -180,11 +230,19 @@ pub fn SpinBox(props: SpinBoxProps) {
} }
}; };
let button_style = Some(Style { let button_style = match spin_button_style {
height: Units::Pixels(24.0).into(), SpinBoxStyle::Horizontal => Some(Style {
width: Units::Pixels(24.0).into(), height: Units::Pixels(24.0).into(),
..Default::default() width: Units::Pixels(24.0).into(),
}); ..Default::default()
}),
SpinBoxStyle::Vertical => Some(Style {
height: Units::Pixels(12.0).into(),
width: Units::Pixels(24.0).into(),
..Default::default()
}),
};
let value = if value.is_empty() { let value = if value.is_empty() {
placeholder.unwrap_or_else(|| value.clone()) placeholder.unwrap_or_else(|| value.clone())
...@@ -192,30 +250,97 @@ pub fn SpinBox(props: SpinBoxProps) { ...@@ -192,30 +250,97 @@ pub fn SpinBox(props: SpinBoxProps) {
value value
}; };
let inline_style = Style { let row = Style {
layout_type: StyleProp::Value(LayoutType::Row), layout_type: StyleProp::Value(LayoutType::Row),
..Style::default() ..Style::default()
}; };
let col = Style {
layout_type: StyleProp::Value(LayoutType::Column),
height: Units::Stretch(100.0).into(),
width: Units::Pixels(26.0).into(),
..Style::default()
};
let incr_str = props.clone().incr_str; let incr_str = props.clone().incr_str;
let decr_str = props.clone().decr_str; let decr_str = props.clone().decr_str;
rsx! { let (spin_value, set_val, _) = use_state!(value);
<Background styles={Some(background_styles)}> let x = spin_value.parse::<f32>().unwrap_or_default();
<Clip styles={Some(inline_style)}> let decr_fn = set_val.clone();
<Button styles={button_style}> let incr_fn = set_val.clone();
<Text content={decr_str} />
</Button> let incr_event = if let Some(event) = props.clone().on_incr_event {
<Text event
content={value} } else {
size={14.0} OnEvent::new(move |_, event| match event.event_type {
styles={Some(text_styles)} EventType::Click(_) => {
/> if x >= max_val {
<Button styles={button_style}> return;
<Text content={incr_str} /> }
</Button> incr_fn((x + 1.0f32).to_string());
</Clip> }
</Background> _ => {}
})
};
let decr_event = if let Some(event) = props.clone().on_decr_event {
event
} else {
OnEvent::new(move |_, event| match event.event_type {
EventType::Click(_) => {
if x <= min_val {
return;
}
decr_fn((x - 1.0f32).to_string());
}
_ => {}
})
};
match spin_button_style {
SpinBoxStyle::Horizontal => {
rsx! {
<Background styles={Some(background_styles)}>
<Clip styles={Some(row)}>
<Button styles={button_style} on_event={Some(decr_event)}>
<Text content={decr_str} />
</Button>
<Text
content={spin_value}
size={14.0}
styles={Some(text_styles)}
/>
<Button styles={button_style} on_event={Some(incr_event)}>
<Text content={incr_str} />
</Button>
</Clip>
</Background>
}
}
SpinBoxStyle::Vertical => {
rsx! {
<Background styles={Some(background_styles)}>
<Clip styles={Some(row)}>
<Text
content={spin_value}
size={14.0}
styles={Some(text_styles)}
/>
<Clip styles={Some(col)}>
<Button styles={button_style} on_event={Some(incr_event)}>
<Text content={incr_str} size={11.0} />
</Button>
<Button styles={button_style} on_event={Some(decr_event)}>
<Text content={decr_str} size={11.0}/>
</Button>
</Clip>
</Clip>
</Background>
}
}
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment