Implement reactive-rendering for pick_list

This commit is contained in:
Héctor Ramón Jiménez 2024-10-23 19:49:19 +02:00
parent 7908b6eba9
commit fdf046daff
No known key found for this signature in database
GPG key ID: 4C07CEC81AFA161F

View file

@ -71,6 +71,7 @@ use crate::core::text::paragraph;
use crate::core::text::{self, Text}; use crate::core::text::{self, Text};
use crate::core::touch; use crate::core::touch;
use crate::core::widget::tree::{self, Tree}; use crate::core::widget::tree::{self, Tree};
use crate::core::window;
use crate::core::{ use crate::core::{
Background, Border, Clipboard, Color, Element, Layout, Length, Padding, Background, Border, Clipboard, Color, Element, Layout, Length, Padding,
Pixels, Point, Rectangle, Shell, Size, Theme, Vector, Widget, Pixels, Point, Rectangle, Shell, Size, Theme, Vector, Widget,
@ -173,6 +174,7 @@ pub struct PickList<
handle: Handle<Renderer::Font>, handle: Handle<Renderer::Font>,
class: <Theme as Catalog>::Class<'a>, class: <Theme as Catalog>::Class<'a>,
menu_class: <Theme as menu::Catalog>::Class<'a>, menu_class: <Theme as menu::Catalog>::Class<'a>,
last_status: Option<Status>,
} }
impl<'a, T, L, V, Message, Theme, Renderer> impl<'a, T, L, V, Message, Theme, Renderer>
@ -208,6 +210,7 @@ where
handle: Handle::default(), handle: Handle::default(),
class: <Theme as Catalog>::default(), class: <Theme as Catalog>::default(),
menu_class: <Theme as Catalog>::default_menu(), menu_class: <Theme as Catalog>::default_menu(),
last_status: None,
} }
} }
@ -436,12 +439,11 @@ where
shell: &mut Shell<'_, Message>, shell: &mut Shell<'_, Message>,
_viewport: &Rectangle, _viewport: &Rectangle,
) -> event::Status { ) -> event::Status {
match event { let state = tree.state.downcast_mut::<State<Renderer::Paragraph>>();
let event_status = match event {
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
| Event::Touch(touch::Event::FingerPressed { .. }) => { | Event::Touch(touch::Event::FingerPressed { .. }) => {
let state =
tree.state.downcast_mut::<State<Renderer::Paragraph>>();
if state.is_open { if state.is_open {
// Event wasn't processed by overlay, so cursor was clicked either outside its // 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. // bounds or on the drop-down, either way we close the overlay.
@ -474,9 +476,6 @@ where
Event::Mouse(mouse::Event::WheelScrolled { Event::Mouse(mouse::Event::WheelScrolled {
delta: mouse::ScrollDelta::Lines { y, .. }, delta: mouse::ScrollDelta::Lines { y, .. },
}) => { }) => {
let state =
tree.state.downcast_mut::<State<Renderer::Paragraph>>();
if state.keyboard_modifiers.command() if state.keyboard_modifiers.command()
&& cursor.is_over(layout.bounds()) && cursor.is_over(layout.bounds())
&& !state.is_open && !state.is_open
@ -519,15 +518,33 @@ where
} }
} }
Event::Keyboard(keyboard::Event::ModifiersChanged(modifiers)) => { Event::Keyboard(keyboard::Event::ModifiersChanged(modifiers)) => {
let state =
tree.state.downcast_mut::<State<Renderer::Paragraph>>();
state.keyboard_modifiers = modifiers; state.keyboard_modifiers = modifiers;
event::Status::Ignored event::Status::Ignored
} }
_ => 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( fn mouse_interaction(
@ -555,7 +572,7 @@ where
theme: &Theme, theme: &Theme,
_style: &renderer::Style, _style: &renderer::Style,
layout: Layout<'_>, layout: Layout<'_>,
cursor: mouse::Cursor, _cursor: mouse::Cursor,
viewport: &Rectangle, viewport: &Rectangle,
) { ) {
let font = self.font.unwrap_or_else(|| renderer.default_font()); let font = self.font.unwrap_or_else(|| renderer.default_font());
@ -563,18 +580,12 @@ where
let state = tree.state.downcast_ref::<State<Renderer::Paragraph>>(); let state = tree.state.downcast_ref::<State<Renderer::Paragraph>>();
let bounds = layout.bounds(); let bounds = layout.bounds();
let is_mouse_over = cursor.is_over(bounds);
let is_selected = selected.is_some();
let status = if state.is_open { let style = Catalog::style(
Status::Opened theme,
} else if is_mouse_over { &self.class,
Status::Hovered self.last_status.unwrap_or(Status::Active),
} else { );
Status::Active
};
let style = Catalog::style(theme, &self.class, status);
renderer.fill_quad( renderer.fill_quad(
renderer::Quad { renderer::Quad {
@ -671,7 +682,7 @@ where
wrapping: text::Wrapping::default(), wrapping: text::Wrapping::default(),
}, },
Point::new(bounds.x + self.padding.left, bounds.center_y()), Point::new(bounds.x + self.padding.left, bounds.center_y()),
if is_selected { if selected.is_some() {
style.text_color style.text_color
} else { } else {
style.placeholder_color style.placeholder_color