summaryrefslogtreecommitdiffstats
path: root/widget/src/pick_list.rs
diff options
context:
space:
mode:
Diffstat (limited to 'widget/src/pick_list.rs')
-rw-r--r--widget/src/pick_list.rs83
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