diff options
Diffstat (limited to 'widget/src/overlay')
-rw-r--r-- | widget/src/overlay/menu.rs | 60 |
1 files changed, 42 insertions, 18 deletions
diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs index b641e8f5..7907ef01 100644 --- a/widget/src/overlay/menu.rs +++ b/widget/src/overlay/menu.rs @@ -1,17 +1,17 @@ //! 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; 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, + Background, Clipboard, Color, Event, Length, Padding, Pixels, Point, + Rectangle, Size, Theme, Vector, }; use crate::core::{Element, Shell, Widget}; use crate::scrollable::{self, Scrollable}; @@ -262,7 +262,7 @@ where }) } - fn on_event( + fn update( &mut self, event: Event, layout: Layout<'_>, @@ -270,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.list.update( self.state, event, layout, cursor, renderer, clipboard, shell, &bounds, - ) + ); } fn mouse_interaction( @@ -334,6 +334,10 @@ where class: &'a <Theme as Catalog>::Class<'b>, } +struct ListState { + is_hovered: Option<bool>, +} + impl<'a, 'b, T, Message, Theme, Renderer> Widget<Message, Theme, Renderer> for List<'a, 'b, T, Message, Theme, Renderer> where @@ -341,6 +345,14 @@ where Theme: Catalog, Renderer: text::Renderer, { + fn tag(&self) -> tree::Tag { + tree::Tag::of::<Option<bool>>() + } + + fn state(&self) -> tree::State { + tree::State::new(ListState { is_hovered: None }) + } + fn size(&self) -> Size<Length> { Size { width: Length::Fill, @@ -374,9 +386,9 @@ where layout::Node::new(size) } - fn on_event( + fn update( &mut self, - _state: &mut Tree, + tree: &mut Tree, event: Event, layout: Layout<'_>, cursor: mouse::Cursor, @@ -384,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(); } } } @@ -411,14 +423,18 @@ 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(); } } @@ -443,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(); } } } @@ -451,7 +467,15 @@ where _ => {} } - event::Status::Ignored + let state = tree.state.downcast_mut::<ListState>(); + + 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(); + } } fn mouse_interaction( |