diff options
author | 2022-02-17 19:09:26 +0700 | |
---|---|---|
committer | 2022-02-17 19:09:26 +0700 | |
commit | 9b23ea698e98f5731a1253410e23697329083c78 (patch) | |
tree | 9e02612d7a1afd9a07e5585523e3138027b0dc24 | |
parent | da45b6c1627935bff5334d213096c4e78972af46 (diff) | |
download | iced-9b23ea698e98f5731a1253410e23697329083c78.tar.gz iced-9b23ea698e98f5731a1253410e23697329083c78.tar.bz2 iced-9b23ea698e98f5731a1253410e23697329083c78.zip |
Implement `pure` version of `component` example
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | examples/pure/component/Cargo.toml | 11 | ||||
-rw-r--r-- | examples/pure/component/src/main.rs | 168 |
3 files changed, 180 insertions, 0 deletions
@@ -90,6 +90,7 @@ members = [ "examples/tooltip", "examples/tour", "examples/url_handler", + "examples/pure/component", "examples/pure/counter", "examples/pure/pick_list", "examples/pure/todos", diff --git a/examples/pure/component/Cargo.toml b/examples/pure/component/Cargo.toml new file mode 100644 index 00000000..a15f134f --- /dev/null +++ b/examples/pure/component/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "pure_component" +version = "0.1.0" +authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"] +edition = "2021" +publish = false + +[dependencies] +iced = { path = "../../..", features = ["debug", "pure"] } +iced_native = { path = "../../../native" } +iced_lazy = { path = "../../../lazy", features = ["pure"] } diff --git a/examples/pure/component/src/main.rs b/examples/pure/component/src/main.rs new file mode 100644 index 00000000..0de7bdd9 --- /dev/null +++ b/examples/pure/component/src/main.rs @@ -0,0 +1,168 @@ +use iced::pure::widget::container; +use iced::pure::{Element, Sandbox}; +use iced::{Length, Settings}; + +use numeric_input::numeric_input; + +pub fn main() -> iced::Result { + Component::run(Settings::default()) +} + +#[derive(Default)] +struct Component { + 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(&self) -> Element<Message> { + container(numeric_input(self.value, Message::NumericInputChanged)) + .padding(20) + .height(Length::Fill) + .center_y() + .into() + } +} + +mod numeric_input { + use iced::pure::widget::Element; + use iced::pure::widget::{row, text, text_input}; + use iced_lazy::pure::component::{self, Component}; + use iced_native::alignment::{self, Alignment}; + use iced_native::text; + use iced_native::Length; + + pub struct NumericInput<Message> { + value: Option<u32>, + on_change: Box<dyn Fn(Option<u32>) -> Message>, + } + + pub fn numeric_input<Message>( + value: Option<u32>, + on_change: impl Fn(Option<u32>) -> Message + 'static, + ) -> NumericInput<Message> { + NumericInput::new(value, on_change) + } + + #[derive(Debug, Clone)] + pub enum Event { + InputChanged(String), + IncrementPressed, + DecrementPressed, + } + + impl<Message> NumericInput<Message> { + pub fn new( + value: Option<u32>, + on_change: impl Fn(Option<u32>) -> Message + 'static, + ) -> Self { + Self { + value, + on_change: Box::new(on_change), + } + } + } + + impl<Message, Renderer> Component<Message, Renderer> for NumericInput<Message> + where + Renderer: text::Renderer + 'static, + { + type State = (); + type Event = Event; + + fn update( + &mut self, + _state: &mut Self::State, + 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(&self, _state: &Self::State) -> Element<Event, Renderer> { + let button = |label, on_press| { + use iced::pure::widget::button; + + button( + text(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() + .push(button("-", Event::DecrementPressed)) + .push( + text_input( + "Type a number", + self.value + .as_ref() + .map(u32::to_string) + .as_ref() + .map(String::as_str) + .unwrap_or(""), + Event::InputChanged, + ) + .padding(10), + ) + .push(button("+", Event::IncrementPressed)) + .align_items(Alignment::Fill) + .spacing(10) + .into() + } + } + + impl<'a, Message, Renderer> From<NumericInput<Message>> + for Element<'a, Message, Renderer> + where + Message: 'a, + Renderer: 'static + text::Renderer, + { + fn from(numeric_input: NumericInput<Message>) -> Self { + component::view(numeric_input) + } + } +} |