diff options
Diffstat (limited to 'widget/src/pick_list.rs')
-rw-r--r-- | widget/src/pick_list.rs | 83 |
1 files changed, 45 insertions, 38 deletions
diff --git a/widget/src/pick_list.rs b/widget/src/pick_list.rs index 4f1e9da9..6708e7cd 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; @@ -71,9 +70,10 @@ 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, + Background, Border, Clipboard, Color, Element, Event, Layout, Length, + Padding, Pixels, Point, Rectangle, Shell, Size, Theme, Vector, Widget, }; use crate::overlay::menu::{self, Menu}; @@ -173,6 +173,7 @@ pub struct PickList< handle: Handle<Renderer::Font>, class: <Theme as Catalog>::Class<'a>, menu_class: <Theme as menu::Catalog>::Class<'a>, + last_status: Option<Status>, } impl<'a, T, L, V, Message, Theme, Renderer> @@ -208,6 +209,7 @@ where handle: Handle::default(), class: <Theme as Catalog>::default(), menu_class: <Theme as Catalog>::default_menu(), + last_status: None, } } @@ -425,7 +427,7 @@ where layout::Node::new(size) } - fn on_event( + fn update( &mut self, tree: &mut Tree, event: Event, @@ -435,13 +437,12 @@ where _clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, _viewport: &Rectangle, - ) -> event::Status { + ) { + let state = tree.state.downcast_mut::<State<Renderer::Paragraph>>(); + match event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) | Event::Touch(touch::Event::FingerPressed { .. }) => { - let state = - tree.state.downcast_mut::<State<Renderer::Paragraph>>(); - 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. @@ -451,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); @@ -466,17 +467,12 @@ where shell.publish(on_open.clone()); } - event::Status::Captured - } else { - event::Status::Ignored + shell.capture_event(); } } Event::Mouse(mouse::Event::WheelScrolled { delta: mouse::ScrollDelta::Lines { y, .. }, }) => { - let state = - tree.state.downcast_mut::<State<Renderer::Paragraph>>(); - if state.keyboard_modifiers.command() && cursor.is_over(layout.bounds()) && !state.is_open @@ -513,20 +509,34 @@ 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)) => { - let state = - tree.state.downcast_mut::<State<Renderer::Paragraph>>(); - state.keyboard_modifiers = modifiers; + } + _ => {} + }; + + let status = { + let is_hovered = cursor.is_over(layout.bounds()); - event::Status::Ignored + if state.is_open { + Status::Opened { is_hovered } + } else if is_hovered { + Status::Hovered + } else { + Status::Active } - _ => event::Status::Ignored, + }; + + if let Event::Window(window::Event::RedrawRequested(_now)) = event { + self.last_status = Some(status); + } else if self + .last_status + .is_some_and(|last_status| last_status != status) + { + shell.request_redraw(); } } @@ -555,7 +565,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 +573,12 @@ where let state = tree.state.downcast_ref::<State<Renderer::Paragraph>>(); 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 +675,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 @@ -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 |