From 5cc1aa31c774894d9a48ee005e857913c9720908 Mon Sep 17 00:00:00 2001 From: Nick Senger Date: Wed, 6 Apr 2022 10:27:45 -0700 Subject: add example --- Cargo.toml | 1 + examples/pure/nested_component/Cargo.toml | 12 +++ examples/pure/nested_component/src/main.rs | 166 +++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 examples/pure/nested_component/Cargo.toml create mode 100644 examples/pure/nested_component/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index c6ccc5df..d9d0c135 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -89,6 +89,7 @@ members = [ "examples/pure/component", "examples/pure/counter", "examples/pure/game_of_life", + "examples/pure/nested_component", "examples/pure/pane_grid", "examples/pure/pick_list", "examples/pure/todos", diff --git a/examples/pure/nested_component/Cargo.toml b/examples/pure/nested_component/Cargo.toml new file mode 100644 index 00000000..6b1b3570 --- /dev/null +++ b/examples/pure/nested_component/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "pure_nested_component" +version = "0.1.0" +authors = ["Héctor Ramón Jiménez "] +edition = "2021" +publish = false + +[dependencies] +iced = { path = "../../..", features = ["debug", "pure"] } +iced_native = { path = "../../../native" } +iced_lazy = { path = "../../../lazy", features = ["pure"] } +iced_pure = { path = "../../../pure" } diff --git a/examples/pure/nested_component/src/main.rs b/examples/pure/nested_component/src/main.rs new file mode 100644 index 00000000..d2f0ac37 --- /dev/null +++ b/examples/pure/nested_component/src/main.rs @@ -0,0 +1,166 @@ +use iced::pure::container; +use iced::pure::{Element, Sandbox}; +use iced::{Length, Settings}; + +use counter::counter; + +pub fn main() -> iced::Result { + Component::run(Settings::default()) +} + +#[derive(Default)] +struct Component; + +#[derive(Debug, Clone, Copy)] +enum Message {} + +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) {} + + fn view(&self) -> Element { + container(counter()) + .padding(20) + .height(Length::Fill) + .center_y() + .into() + } +} + +mod counter { + use iced::pure::{column, text}; + use iced_lazy::pure::{self, Component}; + use iced_native::text; + use iced_pure::Element; + + use custom_button::custom_button; + + pub struct Counter; + + pub fn counter() -> Counter { + Counter::new() + } + + #[derive(Debug, Clone)] + pub enum Event { + IncrementPressed, + } + + impl Counter { + pub fn new() -> Self { + Self {} + } + } + + #[derive(Default)] + pub struct State { + count: u32, + } + + impl Component for Counter + where + Renderer: text::Renderer + 'static, + { + type State = State; + type Event = Event; + + fn update( + &mut self, + state: &mut Self::State, + event: Event, + ) -> Option { + match event { + Event::IncrementPressed => { + state.count += 1; + + None + } + } + } + + fn view(&self, state: &Self::State) -> Element { + column() + .push(text(&state.count.to_string())) + .push(custom_button("Increment", Event::IncrementPressed)) + .into() + } + } + + impl<'a, Message, Renderer> From for Element<'a, Message, Renderer> + where + Message: 'a, + Renderer: 'static + text::Renderer, + { + fn from(counter: Counter) -> Self { + pure::component(counter) + } + } + + mod custom_button { + use iced::pure::{button, text}; + use iced_lazy::pure::{self, Component}; + use iced_native::text; + use iced_pure::Element; + + pub struct CustomButton<'a, Message> { + text: &'a str, + on_press: Message, + } + + pub fn custom_button<'a, Message>( + text: &'a str, + on_press: Message, + ) -> CustomButton<'a, Message> { + CustomButton { text, on_press } + } + + #[derive(Clone)] + pub enum Event { + Press, + } + + impl<'a, Message, Renderer> Component + for CustomButton<'a, Message> + where + Message: Clone, + Renderer: iced_native::Renderer + text::Renderer + 'static, + { + type State = (); + type Event = Event; + + fn update( + &mut self, + _state: &mut Self::State, + event: Event, + ) -> Option { + match event { + Event::Press => Some(self.on_press.clone()), + } + } + + fn view(&self, _state: &Self::State) -> Element { + button(text(self.text)).on_press(Event::Press).into() + } + } + + impl<'a, Message, Renderer> From> + for Element<'a, Message, Renderer> + where + Message: Clone + 'a, + Renderer: 'static + text::Renderer, + { + fn from(custom_button: CustomButton<'a, Message>) -> Self { + pure::component(custom_button) + } + } + } +} -- cgit From e4178c8e4f0fb98d7b939b25a74982fa7f717fba Mon Sep 17 00:00:00 2001 From: Nick Senger Date: Wed, 6 Apr 2022 11:50:22 -0700 Subject: fix: nested components --- lazy/src/pure/component.rs | 52 ++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/lazy/src/pure/component.rs b/lazy/src/pure/component.rs index 4d952f69..bd98aa8c 100644 --- a/lazy/src/pure/component.rs +++ b/lazy/src/pure/component.rs @@ -130,23 +130,24 @@ where Renderer: iced_native::Renderer, { fn tag(&self) -> tree::Tag { - tree::Tag::of::() + tree::Tag::of::<(S, Tree)>() } fn state(&self) -> tree::State { - tree::State::new(S::default()) - } + let state = S::default(); + self.rebuild_element(&state); - fn children(&self) -> Vec { - self.rebuild_element(&S::default()); - self.with_element(|element| vec![Tree::new(element)]) + tree::State::new(( + state, + self.with_element(|element| Tree::new(element)), + )) } fn diff(&self, tree: &mut Tree) { - self.rebuild_element(tree.state.downcast_ref()); - self.with_element(|element| { - tree.diff_children(std::slice::from_ref(&element)) - }) + let (state, tree) = tree.state.downcast_mut::<(S, Tree)>(); + self.rebuild_element(&state); + + self.with_element(|element| tree.diff(element)); } fn width(&self) -> Length { @@ -180,9 +181,11 @@ where let mut local_messages = Vec::new(); let mut local_shell = Shell::new(&mut local_messages); + let (s, tree) = tree.state.downcast_mut::<(S, Tree)>(); + let event_status = self.with_element_mut(|element| { element.as_widget_mut().on_event( - &mut tree.children[0], + tree, event, layout, cursor_position, @@ -197,11 +200,10 @@ where if !local_messages.is_empty() { let mut heads = self.state.take().unwrap().into_heads(); - for message in local_messages.into_iter().filter_map(|message| { - heads - .component - .update(tree.state.downcast_mut::(), message) - }) { + for message in local_messages + .into_iter() + .filter_map(|message| heads.component.update(s, message)) + { shell.publish(message); } @@ -210,13 +212,13 @@ where component: heads.component, message: PhantomData, state: PhantomData, - element_builder: |state| { - Some(state.view(tree.state.downcast_ref::())) - }, + element_builder: |state| Some(state.view(s)), } .build(), )); + self.with_element(|element| tree.diff(element)); + shell.invalidate_layout(); } @@ -232,9 +234,11 @@ where cursor_position: Point, viewport: &Rectangle, ) { + let (_, tree) = tree.state.downcast_ref::<(S, Tree)>(); + self.with_element(|element| { element.as_widget().draw( - &tree.children[0], + tree, renderer, style, layout, @@ -252,9 +256,11 @@ where viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { + let (_, tree) = tree.state.downcast_ref::<(S, Tree)>(); + self.with_element(|element| { element.as_widget().mouse_interaction( - &tree.children[0], + tree, layout, cursor_position, viewport, @@ -269,6 +275,8 @@ where layout: Layout<'_>, renderer: &Renderer, ) -> Option> { + let (_, tree) = tree.state.downcast_mut::<(S, Tree)>(); + let overlay = OverlayBuilder { instance: self, instance_ref_builder: |instance| instance.state.borrow(), @@ -282,7 +290,7 @@ where .as_ref() .unwrap() .as_widget() - .overlay(&mut tree.children[0], layout, renderer) + .overlay(tree, layout, renderer) }, } .build(); -- cgit From c663a8d85cd90805de65b2d90226dbb7cbfac364 Mon Sep 17 00:00:00 2001 From: Nick Senger Date: Wed, 6 Apr 2022 13:15:51 -0700 Subject: remove example --- Cargo.toml | 1 - examples/pure/nested_component/Cargo.toml | 12 --- examples/pure/nested_component/src/main.rs | 166 ----------------------------- 3 files changed, 179 deletions(-) delete mode 100644 examples/pure/nested_component/Cargo.toml delete mode 100644 examples/pure/nested_component/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index d9d0c135..c6ccc5df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -89,7 +89,6 @@ members = [ "examples/pure/component", "examples/pure/counter", "examples/pure/game_of_life", - "examples/pure/nested_component", "examples/pure/pane_grid", "examples/pure/pick_list", "examples/pure/todos", diff --git a/examples/pure/nested_component/Cargo.toml b/examples/pure/nested_component/Cargo.toml deleted file mode 100644 index 6b1b3570..00000000 --- a/examples/pure/nested_component/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "pure_nested_component" -version = "0.1.0" -authors = ["Héctor Ramón Jiménez "] -edition = "2021" -publish = false - -[dependencies] -iced = { path = "../../..", features = ["debug", "pure"] } -iced_native = { path = "../../../native" } -iced_lazy = { path = "../../../lazy", features = ["pure"] } -iced_pure = { path = "../../../pure" } diff --git a/examples/pure/nested_component/src/main.rs b/examples/pure/nested_component/src/main.rs deleted file mode 100644 index d2f0ac37..00000000 --- a/examples/pure/nested_component/src/main.rs +++ /dev/null @@ -1,166 +0,0 @@ -use iced::pure::container; -use iced::pure::{Element, Sandbox}; -use iced::{Length, Settings}; - -use counter::counter; - -pub fn main() -> iced::Result { - Component::run(Settings::default()) -} - -#[derive(Default)] -struct Component; - -#[derive(Debug, Clone, Copy)] -enum Message {} - -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) {} - - fn view(&self) -> Element { - container(counter()) - .padding(20) - .height(Length::Fill) - .center_y() - .into() - } -} - -mod counter { - use iced::pure::{column, text}; - use iced_lazy::pure::{self, Component}; - use iced_native::text; - use iced_pure::Element; - - use custom_button::custom_button; - - pub struct Counter; - - pub fn counter() -> Counter { - Counter::new() - } - - #[derive(Debug, Clone)] - pub enum Event { - IncrementPressed, - } - - impl Counter { - pub fn new() -> Self { - Self {} - } - } - - #[derive(Default)] - pub struct State { - count: u32, - } - - impl Component for Counter - where - Renderer: text::Renderer + 'static, - { - type State = State; - type Event = Event; - - fn update( - &mut self, - state: &mut Self::State, - event: Event, - ) -> Option { - match event { - Event::IncrementPressed => { - state.count += 1; - - None - } - } - } - - fn view(&self, state: &Self::State) -> Element { - column() - .push(text(&state.count.to_string())) - .push(custom_button("Increment", Event::IncrementPressed)) - .into() - } - } - - impl<'a, Message, Renderer> From for Element<'a, Message, Renderer> - where - Message: 'a, - Renderer: 'static + text::Renderer, - { - fn from(counter: Counter) -> Self { - pure::component(counter) - } - } - - mod custom_button { - use iced::pure::{button, text}; - use iced_lazy::pure::{self, Component}; - use iced_native::text; - use iced_pure::Element; - - pub struct CustomButton<'a, Message> { - text: &'a str, - on_press: Message, - } - - pub fn custom_button<'a, Message>( - text: &'a str, - on_press: Message, - ) -> CustomButton<'a, Message> { - CustomButton { text, on_press } - } - - #[derive(Clone)] - pub enum Event { - Press, - } - - impl<'a, Message, Renderer> Component - for CustomButton<'a, Message> - where - Message: Clone, - Renderer: iced_native::Renderer + text::Renderer + 'static, - { - type State = (); - type Event = Event; - - fn update( - &mut self, - _state: &mut Self::State, - event: Event, - ) -> Option { - match event { - Event::Press => Some(self.on_press.clone()), - } - } - - fn view(&self, _state: &Self::State) -> Element { - button(text(self.text)).on_press(Event::Press).into() - } - } - - impl<'a, Message, Renderer> From> - for Element<'a, Message, Renderer> - where - Message: Clone + 'a, - Renderer: 'static + text::Renderer, - { - fn from(custom_button: CustomButton<'a, Message>) -> Self { - pure::component(custom_button) - } - } - } -} -- cgit From d23ed0c4e8296687292d3e7f97fdc8707205cefe Mon Sep 17 00:00:00 2001 From: Nick Senger Date: Wed, 6 Apr 2022 17:18:43 -0700 Subject: fix: overlay --- lazy/src/pure/component.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lazy/src/pure/component.rs b/lazy/src/pure/component.rs index bd98aa8c..21458c4d 100644 --- a/lazy/src/pure/component.rs +++ b/lazy/src/pure/component.rs @@ -137,10 +137,7 @@ where let state = S::default(); self.rebuild_element(&state); - tree::State::new(( - state, - self.with_element(|element| Tree::new(element)), - )) + tree::State::new((state, self.with_element(Tree::new))) } fn diff(&self, tree: &mut Tree) { @@ -275,14 +272,14 @@ where layout: Layout<'_>, renderer: &Renderer, ) -> Option> { - let (_, tree) = tree.state.downcast_mut::<(S, Tree)>(); - let overlay = OverlayBuilder { instance: self, instance_ref_builder: |instance| instance.state.borrow(), tree, types: PhantomData, overlay_builder: |instance, tree| { + let (_, tree) = tree.state.downcast_mut::<(S, Tree)>(); + instance .as_ref() .unwrap() @@ -436,11 +433,12 @@ where let overlay = self.overlay.take().unwrap().into_heads(); let mut heads = overlay.instance.state.take().unwrap().into_heads(); - for message in local_messages.into_iter().filter_map(|message| { - heads - .component - .update(overlay.tree.state.downcast_mut::(), message) - }) { + let (s, tree) = overlay.tree.state.downcast_mut::<(S, Tree)>(); + + for message in local_messages + .into_iter() + .filter_map(|message| heads.component.update(s, message)) + { shell.publish(message); } @@ -449,13 +447,13 @@ where component: heads.component, message: PhantomData, state: PhantomData, - element_builder: |state| { - Some(state.view(overlay.tree.state.downcast_ref::())) - }, + element_builder: |state| Some(state.view(s)), } .build(), ); + overlay.instance.with_element(|element| tree.diff(element)); + self.overlay = Some( OverlayBuilder { instance: overlay.instance, @@ -463,6 +461,8 @@ where tree: overlay.tree, types: PhantomData, overlay_builder: |instance, tree| { + let (_, tree) = tree.state.downcast_mut::<(S, Tree)>(); + instance .as_ref() .unwrap() -- cgit From 572dcaff81c16e3b5b06fb361ea1eed8d963b005 Mon Sep 17 00:00:00 2001 From: Nick Senger Date: Sun, 17 Apr 2022 11:53:59 -0700 Subject: fix: diff widget tree after local event processing in `Component` --- lazy/src/pure/component.rs | 72 +++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/lazy/src/pure/component.rs b/lazy/src/pure/component.rs index 21458c4d..1c8237fc 100644 --- a/lazy/src/pure/component.rs +++ b/lazy/src/pure/component.rs @@ -130,21 +130,23 @@ where Renderer: iced_native::Renderer, { fn tag(&self) -> tree::Tag { - tree::Tag::of::<(S, Tree)>() + tree::Tag::of::() } fn state(&self) -> tree::State { - let state = S::default(); - self.rebuild_element(&state); + tree::State::new(S::default()) + } - tree::State::new((state, self.with_element(Tree::new))) + fn children(&self) -> Vec { + self.rebuild_element(&S::default()); + self.with_element(|element| vec![Tree::new(element)]) } fn diff(&self, tree: &mut Tree) { - let (state, tree) = tree.state.downcast_mut::<(S, Tree)>(); - self.rebuild_element(&state); - - self.with_element(|element| tree.diff(element)); + self.rebuild_element(tree.state.downcast_ref()); + self.with_element(|element| { + tree.diff_children(std::slice::from_ref(&element)) + }) } fn width(&self) -> Length { @@ -178,11 +180,9 @@ where let mut local_messages = Vec::new(); let mut local_shell = Shell::new(&mut local_messages); - let (s, tree) = tree.state.downcast_mut::<(S, Tree)>(); - let event_status = self.with_element_mut(|element| { element.as_widget_mut().on_event( - tree, + &mut tree.children[0], event, layout, cursor_position, @@ -197,10 +197,11 @@ where if !local_messages.is_empty() { let mut heads = self.state.take().unwrap().into_heads(); - for message in local_messages - .into_iter() - .filter_map(|message| heads.component.update(s, message)) - { + for message in local_messages.into_iter().filter_map(|message| { + heads + .component + .update(tree.state.downcast_mut::(), message) + }) { shell.publish(message); } @@ -209,12 +210,16 @@ where component: heads.component, message: PhantomData, state: PhantomData, - element_builder: |state| Some(state.view(s)), + element_builder: |state| { + Some(state.view(tree.state.downcast_ref::())) + }, } .build(), )); - self.with_element(|element| tree.diff(element)); + self.with_element(|element| { + tree.diff_children(std::slice::from_ref(&element)) + }); shell.invalidate_layout(); } @@ -231,11 +236,9 @@ where cursor_position: Point, viewport: &Rectangle, ) { - let (_, tree) = tree.state.downcast_ref::<(S, Tree)>(); - self.with_element(|element| { element.as_widget().draw( - tree, + &tree.children[0], renderer, style, layout, @@ -253,11 +256,9 @@ where viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { - let (_, tree) = tree.state.downcast_ref::<(S, Tree)>(); - self.with_element(|element| { element.as_widget().mouse_interaction( - tree, + &tree.children[0], layout, cursor_position, viewport, @@ -278,8 +279,6 @@ where tree, types: PhantomData, overlay_builder: |instance, tree| { - let (_, tree) = tree.state.downcast_mut::<(S, Tree)>(); - instance .as_ref() .unwrap() @@ -287,7 +286,7 @@ where .as_ref() .unwrap() .as_widget() - .overlay(tree, layout, renderer) + .overlay(&mut tree.children[0], layout, renderer) }, } .build(); @@ -433,12 +432,11 @@ where let overlay = self.overlay.take().unwrap().into_heads(); let mut heads = overlay.instance.state.take().unwrap().into_heads(); - let (s, tree) = overlay.tree.state.downcast_mut::<(S, Tree)>(); - - for message in local_messages - .into_iter() - .filter_map(|message| heads.component.update(s, message)) - { + for message in local_messages.into_iter().filter_map(|message| { + heads + .component + .update(overlay.tree.state.downcast_mut::(), message) + }) { shell.publish(message); } @@ -447,12 +445,16 @@ where component: heads.component, message: PhantomData, state: PhantomData, - element_builder: |state| Some(state.view(s)), + element_builder: |state| { + Some(state.view(overlay.tree.state.downcast_ref::())) + }, } .build(), ); - overlay.instance.with_element(|element| tree.diff(element)); + overlay.instance.with_element(|element| { + overlay.tree.diff_children(std::slice::from_ref(&element)) + }); self.overlay = Some( OverlayBuilder { @@ -461,8 +463,6 @@ where tree: overlay.tree, types: PhantomData, overlay_builder: |instance, tree| { - let (_, tree) = tree.state.downcast_mut::<(S, Tree)>(); - instance .as_ref() .unwrap() -- cgit