From fdf046daff5e9196713d2513cd1b654cfc122d80 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 23 Oct 2024 19:49:19 +0200 Subject: Implement `reactive-rendering` for `pick_list` --- widget/src/pick_list.rs | 57 +++++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 23 deletions(-) (limited to 'widget/src/pick_list.rs') diff --git a/widget/src/pick_list.rs b/widget/src/pick_list.rs index 4f1e9da9..ec1c054f 100644 --- a/widget/src/pick_list.rs +++ b/widget/src/pick_list.rs @@ -71,6 +71,7 @@ use crate::core::text::paragraph; use crate::core::text::{self, Text}; use crate::core::touch; use crate::core::widget::tree::{self, Tree}; +use crate::core::window; use crate::core::{ Background, Border, Clipboard, Color, Element, Layout, Length, Padding, Pixels, Point, Rectangle, Shell, Size, Theme, Vector, Widget, @@ -173,6 +174,7 @@ pub struct PickList< handle: Handle, class: ::Class<'a>, menu_class: ::Class<'a>, + last_status: Option, } impl<'a, T, L, V, Message, Theme, Renderer> @@ -208,6 +210,7 @@ where handle: Handle::default(), class: ::default(), menu_class: ::default_menu(), + last_status: None, } } @@ -436,12 +439,11 @@ where shell: &mut Shell<'_, Message>, _viewport: &Rectangle, ) -> event::Status { - match event { + let state = tree.state.downcast_mut::>(); + + let event_status = match event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) | Event::Touch(touch::Event::FingerPressed { .. }) => { - let state = - tree.state.downcast_mut::>(); - if state.is_open { // Event wasn't processed by overlay, so cursor was clicked either outside its // bounds or on the drop-down, either way we close the overlay. @@ -474,9 +476,6 @@ where Event::Mouse(mouse::Event::WheelScrolled { delta: mouse::ScrollDelta::Lines { y, .. }, }) => { - let state = - tree.state.downcast_mut::>(); - if state.keyboard_modifiers.command() && cursor.is_over(layout.bounds()) && !state.is_open @@ -519,15 +518,33 @@ where } } Event::Keyboard(keyboard::Event::ModifiersChanged(modifiers)) => { - let state = - tree.state.downcast_mut::>(); - state.keyboard_modifiers = modifiers; event::Status::Ignored } _ => event::Status::Ignored, + }; + + let status = if state.is_open { + Status::Opened + } else if cursor.is_over(layout.bounds()) { + Status::Hovered + } else { + Status::Active + }; + + if let Event::Window(window::Event::RedrawRequested(_now)) = event { + self.last_status = Some(status); + } else { + match self.last_status { + Some(last_status) if last_status != status => { + shell.request_redraw(window::RedrawRequest::NextFrame); + } + _ => {} + } } + + event_status } fn mouse_interaction( @@ -555,7 +572,7 @@ where theme: &Theme, _style: &renderer::Style, layout: Layout<'_>, - cursor: mouse::Cursor, + _cursor: mouse::Cursor, viewport: &Rectangle, ) { let font = self.font.unwrap_or_else(|| renderer.default_font()); @@ -563,18 +580,12 @@ where let state = tree.state.downcast_ref::>(); let bounds = layout.bounds(); - let is_mouse_over = cursor.is_over(bounds); - let is_selected = selected.is_some(); - - let status = if state.is_open { - Status::Opened - } else if is_mouse_over { - Status::Hovered - } else { - Status::Active - }; - let style = Catalog::style(theme, &self.class, status); + let style = Catalog::style( + theme, + &self.class, + self.last_status.unwrap_or(Status::Active), + ); renderer.fill_quad( renderer::Quad { @@ -671,7 +682,7 @@ where wrapping: text::Wrapping::default(), }, Point::new(bounds.x + self.padding.left, bounds.center_y()), - if is_selected { + if selected.is_some() { style.text_color } else { style.placeholder_color -- 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/pick_list.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'widget/src/pick_list.rs') diff --git a/widget/src/pick_list.rs b/widget/src/pick_list.rs index ec1c054f..9c9ba9e9 100644 --- a/widget/src/pick_list.rs +++ b/widget/src/pick_list.rs @@ -535,13 +535,11 @@ where if let Event::Window(window::Event::RedrawRequested(_now)) = event { self.last_status = Some(status); - } else { - match self.last_status { - Some(last_status) if last_status != status => { - shell.request_redraw(window::RedrawRequest::NextFrame); - } - _ => {} - } + } else if self + .last_status + .is_some_and(|last_status| last_status != status) + { + shell.request_redraw(); } event_status -- 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/pick_list.rs | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) (limited to 'widget/src/pick_list.rs') diff --git a/widget/src/pick_list.rs b/widget/src/pick_list.rs index 9c9ba9e9..9eb43e72 100644 --- a/widget/src/pick_list.rs +++ b/widget/src/pick_list.rs @@ -61,7 +61,6 @@ //! } //! ``` use crate::core::alignment; -use crate::core::event::{self, Event}; use crate::core::keyboard; use crate::core::layout; use crate::core::mouse; @@ -73,8 +72,8 @@ use crate::core::touch; use crate::core::widget::tree::{self, Tree}; use crate::core::window; use crate::core::{ - Background, Border, Clipboard, Color, Element, Layout, Length, Padding, - Pixels, Point, Rectangle, Shell, Size, Theme, Vector, Widget, + Background, Border, Clipboard, Color, Element, Event, Layout, Length, + Padding, Pixels, Point, Rectangle, Shell, Size, Theme, Vector, Widget, }; use crate::overlay::menu::{self, Menu}; @@ -438,10 +437,10 @@ where _clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, _viewport: &Rectangle, - ) -> event::Status { + ) { let state = tree.state.downcast_mut::>(); - let event_status = match event { + match event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) | Event::Touch(touch::Event::FingerPressed { .. }) => { if state.is_open { @@ -453,7 +452,7 @@ where shell.publish(on_close.clone()); } - event::Status::Captured + shell.capture_event(); } else if cursor.is_over(layout.bounds()) { let selected = self.selected.as_ref().map(Borrow::borrow); @@ -468,9 +467,7 @@ where shell.publish(on_open.clone()); } - event::Status::Captured - } else { - event::Status::Ignored + shell.capture_event(); } } Event::Mouse(mouse::Event::WheelScrolled { @@ -512,17 +509,13 @@ where shell.publish((self.on_select)(next_option.clone())); } - event::Status::Captured - } else { - event::Status::Ignored + shell.capture_event(); } } Event::Keyboard(keyboard::Event::ModifiersChanged(modifiers)) => { state.keyboard_modifiers = modifiers; - - event::Status::Ignored } - _ => event::Status::Ignored, + _ => {} }; let status = if state.is_open { @@ -541,8 +534,6 @@ where { shell.request_redraw(); } - - event_status } 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/pick_list.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'widget/src/pick_list.rs') diff --git a/widget/src/pick_list.rs b/widget/src/pick_list.rs index 9eb43e72..32f859da 100644 --- a/widget/src/pick_list.rs +++ b/widget/src/pick_list.rs @@ -427,7 +427,7 @@ where layout::Node::new(size) } - fn on_event( + fn update( &mut self, tree: &mut Tree, event: Event, -- cgit From 03bffe3db61b51d9e28f42c5bfea421b5612c484 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 4 Nov 2024 23:29:37 +0100 Subject: Fix `pick_list` not requesting a redraw when open --- widget/src/pick_list.rs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'widget/src/pick_list.rs') diff --git a/widget/src/pick_list.rs b/widget/src/pick_list.rs index 32f859da..6708e7cd 100644 --- a/widget/src/pick_list.rs +++ b/widget/src/pick_list.rs @@ -518,12 +518,16 @@ where _ => {} }; - let status = if state.is_open { - Status::Opened - } else if cursor.is_over(layout.bounds()) { - Status::Hovered - } else { - Status::Active + let status = { + let is_hovered = cursor.is_over(layout.bounds()); + + if state.is_open { + Status::Opened { is_hovered } + } else if is_hovered { + Status::Hovered + } else { + Status::Active + } }; if let Event::Window(window::Event::RedrawRequested(_now)) = event { @@ -824,7 +828,10 @@ pub enum Status { /// The [`PickList`] is being hovered. Hovered, /// The [`PickList`] is open. - Opened, + Opened { + /// Whether the [`PickList`] is hovered, while open. + is_hovered: bool, + }, } /// The appearance of a pick list. @@ -898,7 +905,7 @@ pub fn default(theme: &Theme, status: Status) -> Style { match status { Status::Active => active, - Status::Hovered | Status::Opened => Style { + Status::Hovered | Status::Opened { .. } => Style { border: Border { color: palette.primary.strong.color, ..active.border -- cgit