From 5c33ce18ed8b12db9a6ba138112804761d26fddb Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 22 Oct 2024 00:13:42 +0200 Subject: Draft `reactive-rendering` feature for `button` --- widget/src/button.rs | 112 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 68 insertions(+), 44 deletions(-) (limited to 'widget/src/button.rs') diff --git a/widget/src/button.rs b/widget/src/button.rs index a3394a01..5850cea0 100644 --- a/widget/src/button.rs +++ b/widget/src/button.rs @@ -26,6 +26,7 @@ use crate::core::theme::palette; use crate::core::touch; use crate::core::widget::tree::{self, Tree}; use crate::core::widget::Operation; +use crate::core::window; use crate::core::{ Background, Clipboard, Color, Element, Layout, Length, Padding, Rectangle, Shadow, Shell, Size, Theme, Vector, Widget, @@ -81,6 +82,7 @@ where padding: Padding, clip: bool, class: Theme::Class<'a>, + status: Option, } enum OnPress<'a, Message> { @@ -117,6 +119,7 @@ where padding: DEFAULT_PADDING, clip: false, class: Theme::default(), + status: None, } } @@ -294,49 +297,85 @@ where return event::Status::Captured; } - match event { - Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) - | Event::Touch(touch::Event::FingerPressed { .. }) => { - if self.on_press.is_some() { - let bounds = layout.bounds(); + let mut update = || { + match event { + Event::Mouse(mouse::Event::ButtonPressed( + mouse::Button::Left, + )) + | Event::Touch(touch::Event::FingerPressed { .. }) => { + if self.on_press.is_some() { + let bounds = layout.bounds(); - if cursor.is_over(bounds) { - let state = tree.state.downcast_mut::(); + if cursor.is_over(bounds) { + let state = tree.state.downcast_mut::(); - state.is_pressed = true; + state.is_pressed = true; - return event::Status::Captured; + return event::Status::Captured; + } } } - } - Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) - | Event::Touch(touch::Event::FingerLifted { .. }) => { - if let Some(on_press) = self.on_press.as_ref().map(OnPress::get) - { - let state = tree.state.downcast_mut::(); + Event::Mouse(mouse::Event::ButtonReleased( + mouse::Button::Left, + )) + | Event::Touch(touch::Event::FingerLifted { .. }) => { + if let Some(on_press) = + self.on_press.as_ref().map(OnPress::get) + { + let state = tree.state.downcast_mut::(); - if state.is_pressed { - state.is_pressed = false; + if state.is_pressed { + state.is_pressed = false; - let bounds = layout.bounds(); + let bounds = layout.bounds(); - if cursor.is_over(bounds) { - shell.publish(on_press); - } + if cursor.is_over(bounds) { + shell.publish(on_press); + } - return event::Status::Captured; + return event::Status::Captured; + } } } + Event::Touch(touch::Event::FingerLost { .. }) => { + let state = tree.state.downcast_mut::(); + + state.is_pressed = false; + } + _ => {} + } + + event::Status::Ignored + }; + + let update_status = update(); + + let current_status = if self.on_press.is_none() { + Status::Disabled + } else if cursor.is_over(layout.bounds()) { + let state = tree.state.downcast_ref::(); + + if state.is_pressed { + Status::Pressed + } else { + Status::Hovered } - Event::Touch(touch::Event::FingerLost { .. }) => { - let state = tree.state.downcast_mut::(); + } else { + Status::Active + }; - state.is_pressed = false; + if let Event::Window(window::Event::RedrawRequested(_now)) = event { + self.status = Some(current_status); + } else { + match self.status { + Some(status) if status != current_status => { + shell.request_redraw(window::RedrawRequest::NextFrame); + } + _ => {} } - _ => {} } - event::Status::Ignored + update_status } fn draw( @@ -351,23 +390,8 @@ where ) { let bounds = layout.bounds(); let content_layout = layout.children().next().unwrap(); - let is_mouse_over = cursor.is_over(bounds); - - let status = if self.on_press.is_none() { - Status::Disabled - } else if is_mouse_over { - let state = tree.state.downcast_ref::(); - - if state.is_pressed { - Status::Pressed - } else { - Status::Hovered - } - } else { - Status::Active - }; - - let style = theme.style(&self.class, status); + let style = + theme.style(&self.class, self.status.unwrap_or(Status::Disabled)); if style.background.is_some() || style.border.width > 0.0 -- 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/button.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'widget/src/button.rs') diff --git a/widget/src/button.rs b/widget/src/button.rs index 5850cea0..46fd0e17 100644 --- a/widget/src/button.rs +++ b/widget/src/button.rs @@ -366,13 +366,8 @@ where if let Event::Window(window::Event::RedrawRequested(_now)) = event { self.status = Some(current_status); - } else { - match self.status { - Some(status) if status != current_status => { - shell.request_redraw(window::RedrawRequest::NextFrame); - } - _ => {} - } + } else if self.status.is_some_and(|status| status != current_status) { + shell.request_redraw(); } update_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/button.rs | 79 ++++++++++++++++++++++------------------------------ 1 file changed, 34 insertions(+), 45 deletions(-) (limited to 'widget/src/button.rs') diff --git a/widget/src/button.rs b/widget/src/button.rs index 46fd0e17..6be17f59 100644 --- a/widget/src/button.rs +++ b/widget/src/button.rs @@ -283,8 +283,8 @@ where clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, viewport: &Rectangle, - ) -> event::Status { - if let event::Status::Captured = self.content.as_widget_mut().on_event( + ) { + self.content.as_widget_mut().on_event( &mut tree.children[0], event.clone(), layout.children().next().unwrap(), @@ -293,62 +293,53 @@ where clipboard, shell, viewport, - ) { - return event::Status::Captured; + ); + + if shell.event_status() == event::Status::Captured { + return; } - let mut update = || { - match event { - Event::Mouse(mouse::Event::ButtonPressed( - mouse::Button::Left, - )) - | Event::Touch(touch::Event::FingerPressed { .. }) => { - if self.on_press.is_some() { - let bounds = layout.bounds(); + match event { + Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) + | Event::Touch(touch::Event::FingerPressed { .. }) => { + if self.on_press.is_some() { + let bounds = layout.bounds(); - if cursor.is_over(bounds) { - let state = tree.state.downcast_mut::(); + if cursor.is_over(bounds) { + let state = tree.state.downcast_mut::(); - state.is_pressed = true; + state.is_pressed = true; - return event::Status::Captured; - } + shell.capture_event(); } } - Event::Mouse(mouse::Event::ButtonReleased( - mouse::Button::Left, - )) - | Event::Touch(touch::Event::FingerLifted { .. }) => { - if let Some(on_press) = - self.on_press.as_ref().map(OnPress::get) - { - let state = tree.state.downcast_mut::(); - - if state.is_pressed { - state.is_pressed = false; + } + Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) + | Event::Touch(touch::Event::FingerLifted { .. }) => { + if let Some(on_press) = self.on_press.as_ref().map(OnPress::get) + { + let state = tree.state.downcast_mut::(); - let bounds = layout.bounds(); + if state.is_pressed { + state.is_pressed = false; - if cursor.is_over(bounds) { - shell.publish(on_press); - } + let bounds = layout.bounds(); - return event::Status::Captured; + if cursor.is_over(bounds) { + shell.publish(on_press); } - } - } - Event::Touch(touch::Event::FingerLost { .. }) => { - let state = tree.state.downcast_mut::(); - state.is_pressed = false; + shell.capture_event(); + } } - _ => {} } + Event::Touch(touch::Event::FingerLost { .. }) => { + let state = tree.state.downcast_mut::(); - event::Status::Ignored - }; - - let update_status = update(); + state.is_pressed = false; + } + _ => {} + } let current_status = if self.on_press.is_none() { Status::Disabled @@ -369,8 +360,6 @@ where } else if self.status.is_some_and(|status| status != current_status) { shell.request_redraw(); } - - update_status } fn draw( -- 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/button.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'widget/src/button.rs') diff --git a/widget/src/button.rs b/widget/src/button.rs index 6be17f59..64f2b793 100644 --- a/widget/src/button.rs +++ b/widget/src/button.rs @@ -273,7 +273,7 @@ where }); } - fn on_event( + fn update( &mut self, tree: &mut Tree, event: Event, @@ -284,7 +284,7 @@ where shell: &mut Shell<'_, Message>, viewport: &Rectangle, ) { - self.content.as_widget_mut().on_event( + self.content.as_widget_mut().update( &mut tree.children[0], event.clone(), layout.children().next().unwrap(), -- cgit From c6af79a1d06013343f9caf2de80597d627254084 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 29 Oct 2024 20:53:29 +0100 Subject: Fix deferred layout on resize after drawing --- widget/src/button.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'widget/src/button.rs') diff --git a/widget/src/button.rs b/widget/src/button.rs index 64f2b793..9eac2e4c 100644 --- a/widget/src/button.rs +++ b/widget/src/button.rs @@ -17,7 +17,6 @@ //! } //! ``` use crate::core::border::{self, Border}; -use crate::core::event::{self, Event}; use crate::core::layout; use crate::core::mouse; use crate::core::overlay; @@ -28,8 +27,8 @@ use crate::core::widget::tree::{self, Tree}; use crate::core::widget::Operation; use crate::core::window; use crate::core::{ - Background, Clipboard, Color, Element, Layout, Length, Padding, Rectangle, - Shadow, Shell, Size, Theme, Vector, Widget, + Background, Clipboard, Color, Element, Event, Layout, Length, Padding, + Rectangle, Shadow, Shell, Size, Theme, Vector, Widget, }; /// A generic widget that produces a message when pressed. @@ -295,7 +294,7 @@ where viewport, ); - if shell.event_status() == event::Status::Captured { + if shell.is_event_captured() { return; } -- cgit