diff options
Diffstat (limited to 'widget/src/pane_grid.rs')
-rw-r--r-- | widget/src/pane_grid.rs | 197 |
1 files changed, 121 insertions, 76 deletions
diff --git a/widget/src/pane_grid.rs b/widget/src/pane_grid.rs index b4ed4b64..7b2956f3 100644 --- a/widget/src/pane_grid.rs +++ b/widget/src/pane_grid.rs @@ -79,7 +79,6 @@ pub use state::State; pub use title_bar::TitleBar; use crate::container; -use crate::core::event::{self, Event}; use crate::core::layout; use crate::core::mouse; use crate::core::overlay::{self, Group}; @@ -87,8 +86,9 @@ 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, Layout, Length, + self, Background, Border, Clipboard, Color, Element, Event, Layout, Length, Pixels, Point, Rectangle, Shell, Size, Theme, Vector, Widget, }; @@ -167,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> @@ -203,6 +204,7 @@ where on_drag: None, on_resize: None, class: <Theme as Catalog>::default(), + last_mouse_interaction: None, } } @@ -293,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)] @@ -423,7 +471,7 @@ where }); } - fn on_event( + fn update( &mut self, tree: &mut Tree, event: Event, @@ -433,9 +481,7 @@ where clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, viewport: &Rectangle, - ) -> event::Status { - let mut event_status = event::Status::Ignored; - + ) { let Memory { action, .. } = tree.state.downcast_mut(); let node = self.internal.layout(); @@ -445,13 +491,43 @@ where &None }; + let picked_pane = action.picked_pane().map(|(pane, _)| pane); + + for (((pane, content), tree), layout) in self + .panes + .iter() + .copied() + .zip(&mut self.contents) + .zip(&mut tree.children) + .zip(layout.children()) + .filter(|(((pane, _), _), _)| { + self.internal + .maximized() + .map_or(true, |maximized| *pane == maximized) + }) + { + let is_picked = picked_pane == Some(pane); + + content.update( + tree, + event.clone(), + layout, + cursor, + renderer, + clipboard, + shell, + viewport, + is_picked, + ); + } + match event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) | Event::Touch(touch::Event::FingerPressed { .. }) => { let bounds = layout.bounds(); if let Some(cursor_position) = cursor.position_over(bounds) { - event_status = event::Status::Captured; + shell.capture_event(); match &self.on_resize { Some((leeway, _)) => { @@ -555,10 +631,6 @@ where } } } - - event_status = event::Status::Captured; - } else if action.picked_split().is_some() { - event_status = event::Status::Captured; } *action = state::Action::Idle; @@ -600,44 +672,48 @@ where ratio, })); - event_status = event::Status::Captured; + shell.capture_event(); } } + } else if action.picked_pane().is_some() { + shell.request_redraw(); } } } _ => {} } - let picked_pane = action.picked_pane().map(|(pane, _)| pane); - - self.panes - .iter() - .copied() - .zip(&mut self.contents) - .zip(&mut tree.children) - .zip(layout.children()) - .filter(|(((pane, _), _), _)| { - self.internal - .maximized() - .map_or(true, |maximized| *pane == maximized) - }) - .map(|(((pane, content), tree), layout)| { - let is_picked = picked_pane == Some(pane); - - content.on_event( - tree, - event.clone(), - layout, - cursor, - renderer, - clipboard, - shell, - viewport, - is_picked, - ) - }) - .fold(event_status, event::Status::merge) + if shell.redraw_request() != Some(window::RedrawRequest::NextFrame) { + let interaction = self + .grid_interaction(action, layout, cursor) + .or_else(|| { + self.panes + .iter() + .zip(&self.contents) + .zip(layout.children()) + .filter(|((&pane, _content), _layout)| { + self.internal + .maximized() + .map_or(true, |maximized| pane == maximized) + }) + .find_map(|((_pane, 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( @@ -650,41 +726,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 |