diff options
author | 2021-11-08 15:29:58 +0700 | |
---|---|---|
committer | 2021-11-29 15:04:13 +0700 | |
commit | 010b62b9ee20b03053ab538a5910795bc0618378 (patch) | |
tree | 6b75a4844239bd93e0a125e6f9d81a356f268f28 /examples | |
parent | bffa7203dfd333b699bc29a22c74fb602eea4ea1 (diff) | |
download | iced-010b62b9ee20b03053ab538a5910795bc0618378.tar.gz iced-010b62b9ee20b03053ab538a5910795bc0618378.tar.bz2 iced-010b62b9ee20b03053ab538a5910795bc0618378.zip |
Draft `component` example :tada:
Diffstat (limited to 'examples')
-rw-r--r-- | examples/component/Cargo.toml | 11 | ||||
-rw-r--r-- | examples/component/src/main.rs | 180 |
2 files changed, 191 insertions, 0 deletions
diff --git a/examples/component/Cargo.toml b/examples/component/Cargo.toml new file mode 100644 index 00000000..5761db9f --- /dev/null +++ b/examples/component/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "component" +version = "0.1.0" +authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"] +edition = "2018" +publish = false + +[dependencies] +iced = { path = "../..", features = ["debug"] } +iced_native = { path = "../../native" } +iced_lazy = { path = "../../lazy" } diff --git a/examples/component/src/main.rs b/examples/component/src/main.rs new file mode 100644 index 00000000..58d3f354 --- /dev/null +++ b/examples/component/src/main.rs @@ -0,0 +1,180 @@ +use iced::{Container, Element, Length, Sandbox, Settings}; +use numeric_input::NumericInput; + +pub fn main() -> iced::Result { + Component::run(Settings::default()) +} + +#[derive(Default)] +struct Component { + numeric_input: numeric_input::State, + value: Option<u32>, +} + +#[derive(Debug, Clone, Copy)] +enum Message { + NumericInputChanged(Option<u32>), +} + +impl Sandbox for Component { + type Message = Message; + + fn new() -> Self { + Self::default() + } + + fn title(&self) -> String { + String::from("Component - Iced") + } + + fn update(&mut self, message: Message) { + match message { + Message::NumericInputChanged(value) => { + self.value = value; + } + } + } + + fn view(&mut self) -> Element<Message> { + Container::new(NumericInput::new( + &mut self.numeric_input, + self.value, + Message::NumericInputChanged, + )) + .padding(20) + .height(Length::Fill) + .center_y() + .into() + } +} + +mod numeric_input { + use iced_lazy::component::{self, Component}; + use iced_native::alignment::{self, Alignment}; + use iced_native::text; + use iced_native::widget::button::{self, Button}; + use iced_native::widget::text_input::{self, TextInput}; + use iced_native::widget::{Row, Text}; + use iced_native::{Element, Length}; + + pub struct NumericInput<'a, Message> { + state: &'a mut State, + value: Option<u32>, + on_change: Box<dyn Fn(Option<u32>) -> Message>, + } + + #[derive(Default)] + pub struct State { + input: text_input::State, + decrement_button: button::State, + increment_button: button::State, + } + + #[derive(Debug, Clone)] + pub enum Event { + InputChanged(String), + IncrementPressed, + DecrementPressed, + } + + impl<'a, Message> NumericInput<'a, Message> { + pub fn new( + state: &'a mut State, + value: Option<u32>, + on_change: impl Fn(Option<u32>) -> Message + 'static, + ) -> Self { + Self { + state, + value, + on_change: Box::new(on_change), + } + } + } + + impl<'a, Message, Renderer> Component<Message, Renderer> + for NumericInput<'a, Message> + where + Renderer: 'a + text::Renderer, + { + type Event = Event; + + fn update(&mut self, event: Event) -> Option<Message> { + match event { + Event::IncrementPressed => Some((self.on_change)(Some( + self.value.unwrap_or_default().saturating_add(1), + ))), + Event::DecrementPressed => Some((self.on_change)(Some( + self.value.unwrap_or_default().saturating_sub(1), + ))), + Event::InputChanged(value) => { + if value.is_empty() { + Some((self.on_change)(None)) + } else { + value + .parse() + .ok() + .map(Some) + .map(self.on_change.as_ref()) + } + } + } + } + + fn view(&mut self) -> Element<Event, Renderer> { + let button = |state, label, on_press| { + Button::new( + state, + Text::new(label) + .width(Length::Fill) + .height(Length::Fill) + .horizontal_alignment(alignment::Horizontal::Center) + .vertical_alignment(alignment::Vertical::Center), + ) + .width(Length::Units(50)) + .on_press(on_press) + }; + + Row::with_children(vec![ + button( + &mut self.state.decrement_button, + "-", + Event::DecrementPressed, + ) + .into(), + TextInput::new( + &mut self.state.input, + "Type a number", + self.value + .as_ref() + .map(u32::to_string) + .as_ref() + .map(String::as_str) + .unwrap_or(""), + Event::InputChanged, + ) + .padding(10) + .into(), + button( + &mut self.state.increment_button, + "+", + Event::IncrementPressed, + ) + .into(), + ]) + .align_items(Alignment::Fill) + .spacing(10) + .into() + } + } + + impl<'a, Message, Renderer> From<NumericInput<'a, Message>> + for Element<'a, Message, Renderer> + where + Message: 'a, + Renderer: text::Renderer + 'a, + { + fn from(numeric_input: NumericInput<'a, Message>) -> Self { + component::view(Box::new(numeric_input)) + } + } +} |