diff options
author | 2024-10-29 15:55:47 +0100 | |
---|---|---|
committer | 2024-11-05 23:52:58 +0100 | |
commit | 4e47450c336a235fe26090665aca1cc7b4d23384 (patch) | |
tree | 25c22890b86fb3765a69ad59d015ced508e0611e | |
parent | 920596ed6f44acf8d87d2135c1b8967bab23d5b9 (diff) | |
download | iced-4e47450c336a235fe26090665aca1cc7b4d23384.tar.gz iced-4e47450c336a235fe26090665aca1cc7b4d23384.tar.bz2 iced-4e47450c336a235fe26090665aca1cc7b4d23384.zip |
Implement `reactive-rendering` for `pane_grid`
-rw-r--r-- | widget/src/pane_grid.rs | 115 | ||||
-rw-r--r-- | widget/src/pane_grid/content.rs | 25 |
2 files changed, 105 insertions, 35 deletions
diff --git a/widget/src/pane_grid.rs b/widget/src/pane_grid.rs index a966627a..691b0a93 100644 --- a/widget/src/pane_grid.rs +++ b/widget/src/pane_grid.rs @@ -86,6 +86,7 @@ use crate::core::renderer; use crate::core::touch; use crate::core::widget; use crate::core::widget::tree::{self, Tree}; +use crate::core::window; use crate::core::{ self, Background, Border, Clipboard, Color, Element, Event, Layout, Length, Pixels, Point, Rectangle, Shell, Size, Theme, Vector, Widget, @@ -166,6 +167,7 @@ pub struct PaneGrid< on_drag: Option<Box<dyn Fn(DragEvent) -> Message + 'a>>, on_resize: Option<(f32, Box<dyn Fn(ResizeEvent) -> Message + 'a>)>, class: <Theme as Catalog>::Class<'a>, + last_mouse_interaction: Option<mouse::Interaction>, } impl<'a, Message, Theme, Renderer> PaneGrid<'a, Message, Theme, Renderer> @@ -202,6 +204,7 @@ where on_drag: None, on_resize: None, class: <Theme as Catalog>::default(), + last_mouse_interaction: None, } } @@ -292,6 +295,52 @@ where .then(|| self.on_drag.is_some()) .unwrap_or_default() } + + fn grid_interaction( + &self, + action: &state::Action, + layout: Layout<'_>, + cursor: mouse::Cursor, + ) -> Option<mouse::Interaction> { + if action.picked_pane().is_some() { + return Some(mouse::Interaction::Grabbing); + } + + let resize_leeway = self.on_resize.as_ref().map(|(leeway, _)| *leeway); + let node = self.internal.layout(); + + let resize_axis = + action.picked_split().map(|(_, axis)| axis).or_else(|| { + resize_leeway.and_then(|leeway| { + let cursor_position = cursor.position()?; + let bounds = layout.bounds(); + + let splits = + node.split_regions(self.spacing, bounds.size()); + + let relative_cursor = Point::new( + cursor_position.x - bounds.x, + cursor_position.y - bounds.y, + ); + + hovered_split( + splits.iter(), + self.spacing + leeway, + relative_cursor, + ) + .map(|(_, axis, _)| axis) + }) + }); + + if let Some(resize_axis) = resize_axis { + return Some(match resize_axis { + Axis::Horizontal => mouse::Interaction::ResizingVertically, + Axis::Vertical => mouse::Interaction::ResizingHorizontally, + }); + } + + None + } } #[derive(Default)] @@ -600,6 +649,8 @@ where shell.capture_event(); } } + } else if action.picked_pane().is_some() { + shell.request_redraw(); } } } @@ -635,6 +686,31 @@ where is_picked, ); } + + if shell.redraw_request() != Some(window::RedrawRequest::NextFrame) { + let interaction = self + .grid_interaction(action, layout, cursor) + .or_else(|| { + self.contents.iter().zip(layout.children()).find_map( + |(content, layout)| { + content.grid_interaction( + layout, + cursor, + on_drag.is_some(), + ) + }, + ) + }) + .unwrap_or(mouse::Interaction::None); + + if let Event::Window(window::Event::RedrawRequested(_now)) = event { + self.last_mouse_interaction = Some(interaction); + } else if self.last_mouse_interaction.is_some_and( + |last_mouse_interaction| last_mouse_interaction != interaction, + ) { + shell.request_redraw(); + } + } } fn mouse_interaction( @@ -647,41 +723,10 @@ where ) -> mouse::Interaction { let Memory { action, .. } = tree.state.downcast_ref(); - if action.picked_pane().is_some() { - return mouse::Interaction::Grabbing; - } - - let resize_leeway = self.on_resize.as_ref().map(|(leeway, _)| *leeway); - let node = self.internal.layout(); - - let resize_axis = - action.picked_split().map(|(_, axis)| axis).or_else(|| { - resize_leeway.and_then(|leeway| { - let cursor_position = cursor.position()?; - let bounds = layout.bounds(); - - let splits = - node.split_regions(self.spacing, bounds.size()); - - let relative_cursor = Point::new( - cursor_position.x - bounds.x, - cursor_position.y - bounds.y, - ); - - hovered_split( - splits.iter(), - self.spacing + leeway, - relative_cursor, - ) - .map(|(_, axis, _)| axis) - }) - }); - - if let Some(resize_axis) = resize_axis { - return match resize_axis { - Axis::Horizontal => mouse::Interaction::ResizingVertically, - Axis::Vertical => mouse::Interaction::ResizingHorizontally, - }; + if let Some(grid_interaction) = + self.grid_interaction(action, layout, cursor) + { + return grid_interaction; } self.panes diff --git a/widget/src/pane_grid/content.rs b/widget/src/pane_grid/content.rs index e0199f0a..f1f67023 100644 --- a/widget/src/pane_grid/content.rs +++ b/widget/src/pane_grid/content.rs @@ -284,6 +284,31 @@ where } } + pub(crate) fn grid_interaction( + &self, + layout: Layout<'_>, + cursor: mouse::Cursor, + drag_enabled: bool, + ) -> Option<mouse::Interaction> { + let title_bar = self.title_bar.as_ref()?; + + let mut children = layout.children(); + let title_bar_layout = children.next().unwrap(); + + let is_over_pick_area = cursor + .position() + .map(|cursor_position| { + title_bar.is_over_pick_area(title_bar_layout, cursor_position) + }) + .unwrap_or_default(); + + if is_over_pick_area && drag_enabled { + return Some(mouse::Interaction::Grab); + } + + None + } + pub(crate) fn mouse_interaction( &self, tree: &Tree, |