From 908af3fed72131d21d7c7ffbc503c9b1e8a65144 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 23 Oct 2024 20:04:13 +0200 Subject: Implement `reactive-rendering` for `menu` --- widget/src/overlay/menu.rs | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) (limited to 'widget/src/overlay/menu.rs') diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs index b641e8f5..e79bd3da 100644 --- a/widget/src/overlay/menu.rs +++ b/widget/src/overlay/menu.rs @@ -8,7 +8,8 @@ use crate::core::overlay; use crate::core::renderer; use crate::core::text::{self, Text}; use crate::core::touch; -use crate::core::widget::Tree; +use crate::core::widget::tree::{self, Tree}; +use crate::core::window; use crate::core::{ Background, Clipboard, Color, Length, Padding, Pixels, Point, Rectangle, Size, Theme, Vector, @@ -334,6 +335,10 @@ where class: &'a ::Class<'b>, } +struct ListState { + is_hovered: Option, +} + impl<'a, 'b, T, Message, Theme, Renderer> Widget for List<'a, 'b, T, Message, Theme, Renderer> where @@ -341,6 +346,14 @@ where Theme: Catalog, Renderer: text::Renderer, { + fn tag(&self) -> tree::Tag { + tree::Tag::of::>() + } + + fn state(&self) -> tree::State { + tree::State::new(ListState { is_hovered: None }) + } + fn size(&self) -> Size { Size { width: Length::Fill, @@ -376,7 +389,7 @@ where fn on_event( &mut self, - _state: &mut Tree, + tree: &mut Tree, event: Event, layout: Layout<'_>, cursor: mouse::Cursor, @@ -411,14 +424,20 @@ where let new_hovered_option = (cursor_position.y / option_height) as usize; - if let Some(on_option_hovered) = self.on_option_hovered { - if *self.hovered_option != Some(new_hovered_option) { - if let Some(option) = - self.options.get(new_hovered_option) + if *self.hovered_option != Some(new_hovered_option) { + if let Some(option) = + self.options.get(new_hovered_option) + { + if let Some(on_option_hovered) = + self.on_option_hovered { shell .publish(on_option_hovered(option.clone())); } + + shell.request_redraw( + window::RedrawRequest::NextFrame, + ); } } @@ -451,6 +470,18 @@ where _ => {} } + let state = tree.state.downcast_mut::(); + + if state.is_hovered.is_some_and(|is_hovered| { + is_hovered != cursor.is_over(layout.bounds()) + }) { + shell.request_redraw(window::RedrawRequest::NextFrame); + } + + if let Event::Window(window::Event::RedrawRequested(_now)) = event { + state.is_hovered = Some(cursor.is_over(layout.bounds())); + } + event::Status::Ignored } -- cgit From 752403d70c851ece620c4007710062b158e8dec3 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 25 Oct 2024 15:40:05 +0200 Subject: Split `Shell::request_redraw` into two different methods --- widget/src/overlay/menu.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'widget/src/overlay/menu.rs') diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs index e79bd3da..c1a0a5d8 100644 --- a/widget/src/overlay/menu.rs +++ b/widget/src/overlay/menu.rs @@ -435,9 +435,7 @@ where .publish(on_option_hovered(option.clone())); } - shell.request_redraw( - window::RedrawRequest::NextFrame, - ); + shell.request_redraw(); } } @@ -472,14 +470,12 @@ where let state = tree.state.downcast_mut::(); - if state.is_hovered.is_some_and(|is_hovered| { - is_hovered != cursor.is_over(layout.bounds()) - }) { - shell.request_redraw(window::RedrawRequest::NextFrame); - } - if let Event::Window(window::Event::RedrawRequested(_now)) = event { state.is_hovered = Some(cursor.is_over(layout.bounds())); + } else if state.is_hovered.is_some_and(|is_hovered| { + is_hovered != cursor.is_over(layout.bounds()) + }) { + shell.request_redraw(); } event::Status::Ignored -- cgit From dcc184b01b753dbecb500205391f6eaaa21c8683 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 25 Oct 2024 19:28:18 +0200 Subject: Replace `event::Status` in `Widget::on_event` with `Shell::capture_event` --- widget/src/overlay/menu.rs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'widget/src/overlay/menu.rs') diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs index c1a0a5d8..78ee3da6 100644 --- a/widget/src/overlay/menu.rs +++ b/widget/src/overlay/menu.rs @@ -1,7 +1,6 @@ //! Build and show dropdown menus. use crate::core::alignment; use crate::core::border::{self, Border}; -use crate::core::event::{self, Event}; use crate::core::layout::{self, Layout}; use crate::core::mouse; use crate::core::overlay; @@ -11,8 +10,8 @@ use crate::core::touch; use crate::core::widget::tree::{self, Tree}; use crate::core::window; use crate::core::{ - Background, Clipboard, Color, Length, Padding, Pixels, Point, Rectangle, - Size, Theme, Vector, + Background, Clipboard, Color, Event, Length, Padding, Pixels, Point, + Rectangle, Size, Theme, Vector, }; use crate::core::{Element, Shell, Widget}; use crate::scrollable::{self, Scrollable}; @@ -271,13 +270,13 @@ where renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, - ) -> event::Status { + ) { let bounds = layout.bounds(); self.list.on_event( self.state, event, layout, cursor, renderer, clipboard, shell, &bounds, - ) + ); } fn mouse_interaction( @@ -397,14 +396,14 @@ where _clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, _viewport: &Rectangle, - ) -> event::Status { + ) { match event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => { if cursor.is_over(layout.bounds()) { if let Some(index) = *self.hovered_option { if let Some(option) = self.options.get(index) { shell.publish((self.on_selected)(option.clone())); - return event::Status::Captured; + shell.capture_event(); } } } @@ -460,7 +459,7 @@ where if let Some(index) = *self.hovered_option { if let Some(option) = self.options.get(index) { shell.publish((self.on_selected)(option.clone())); - return event::Status::Captured; + shell.capture_event(); } } } @@ -477,8 +476,6 @@ where }) { shell.request_redraw(); } - - event::Status::Ignored } fn mouse_interaction( -- cgit From f02bfc3f68322bea0c56283d76888714be401ec2 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 25 Oct 2024 22:06:06 +0200 Subject: Rename `Widget::on_event` to `update` --- widget/src/overlay/menu.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'widget/src/overlay/menu.rs') diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs index 78ee3da6..b0c0bbad 100644 --- a/widget/src/overlay/menu.rs +++ b/widget/src/overlay/menu.rs @@ -273,7 +273,7 @@ where ) { let bounds = layout.bounds(); - self.list.on_event( + self.list.update( self.state, event, layout, cursor, renderer, clipboard, shell, &bounds, ); @@ -386,7 +386,7 @@ where layout::Node::new(size) } - fn on_event( + fn update( &mut self, tree: &mut Tree, event: Event, -- cgit From e5f1e31a5c068fe992cab076661cb6e2d120bdf1 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 6 Nov 2024 00:02:46 +0100 Subject: Rename `Overlay::on_event` to `update` --- widget/src/overlay/menu.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'widget/src/overlay/menu.rs') diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs index b0c0bbad..7907ef01 100644 --- a/widget/src/overlay/menu.rs +++ b/widget/src/overlay/menu.rs @@ -262,7 +262,7 @@ where }) } - fn on_event( + fn update( &mut self, event: Event, layout: Layout<'_>, -- cgit