diff options
Diffstat (limited to '')
-rw-r--r-- | widget/src/pane_grid.rs | 89 | ||||
-rw-r--r-- | widget/src/pane_grid/content.rs | 9 | ||||
-rw-r--r-- | widget/src/pane_grid/state.rs | 17 | ||||
-rw-r--r-- | widget/src/pane_grid/title_bar.rs | 18 |
4 files changed, 90 insertions, 43 deletions
diff --git a/widget/src/pane_grid.rs b/widget/src/pane_grid.rs index 2d25a543..cf1f0455 100644 --- a/widget/src/pane_grid.rs +++ b/widget/src/pane_grid.rs @@ -265,12 +265,11 @@ where } } - fn width(&self) -> Length { - self.width - } - - fn height(&self) -> Length { - self.height + fn size(&self) -> Size<Length> { + Size { + width: self.width, + height: self.height, + } } fn layout( @@ -490,8 +489,7 @@ pub fn layout<Renderer, T>( &layout::Limits, ) -> layout::Node, ) -> layout::Node { - let limits = limits.width(width).height(height); - let size = limits.resolve(Size::ZERO); + let size = limits.resolve(width, height, Size::ZERO); let regions = node.pane_regions(spacing, size); let children = contents @@ -500,16 +498,14 @@ pub fn layout<Renderer, T>( let region = regions.get(&pane)?; let size = Size::new(region.width, region.height); - let mut node = layout_content( + let node = layout_content( content, tree, renderer, &layout::Limits::new(size, size), ); - node.move_to(Point::new(region.x, region.y)); - - Some(node) + Some(node.move_to(Point::new(region.x, region.y))) }) .collect(); @@ -531,6 +527,8 @@ pub fn update<'a, Message, T: Draggable>( on_drag: &Option<Box<dyn Fn(DragEvent) -> Message + 'a>>, on_resize: &Option<(f32, Box<dyn Fn(ResizeEvent) -> Message + 'a>)>, ) -> event::Status { + const DRAG_DEADBAND_DISTANCE: f32 = 10.0; + let mut event_status = event::Status::Ignored; match event { @@ -572,7 +570,6 @@ pub fn update<'a, Message, T: Draggable>( shell, contents, on_click, - on_drag, ); } } @@ -584,7 +581,6 @@ pub fn update<'a, Message, T: Draggable>( shell, contents, on_click, - on_drag, ); } } @@ -637,7 +633,49 @@ pub fn update<'a, Message, T: Draggable>( } Event::Mouse(mouse::Event::CursorMoved { .. }) | Event::Touch(touch::Event::FingerMoved { .. }) => { - if let Some((_, on_resize)) = on_resize { + if let Some((_, origin)) = action.clicked_pane() { + if let Some(on_drag) = &on_drag { + let bounds = layout.bounds(); + + if let Some(cursor_position) = cursor.position_over(bounds) + { + let mut clicked_region = contents + .zip(layout.children()) + .filter(|(_, layout)| { + layout.bounds().contains(cursor_position) + }); + + if let Some(((pane, content), layout)) = + clicked_region.next() + { + if content + .can_be_dragged_at(layout, cursor_position) + { + let pane_position = layout.position(); + + let new_origin = cursor_position + - Vector::new( + pane_position.x, + pane_position.y, + ); + + if new_origin.distance(origin) + > DRAG_DEADBAND_DISTANCE + { + *action = state::Action::Dragging { + pane, + origin, + }; + + shell.publish(on_drag(DragEvent::Picked { + pane, + })); + } + } + } + } + } + } else if let Some((_, on_resize)) = on_resize { if let Some((split, _)) = action.picked_split() { let bounds = layout.bounds(); @@ -712,7 +750,6 @@ fn click_pane<'a, Message, T>( shell: &mut Shell<'_, Message>, contents: impl Iterator<Item = (Pane, T)>, on_click: &Option<Box<dyn Fn(Pane) -> Message + 'a>>, - on_drag: &Option<Box<dyn Fn(DragEvent) -> Message + 'a>>, ) where T: Draggable, { @@ -720,23 +757,15 @@ fn click_pane<'a, Message, T>( .zip(layout.children()) .filter(|(_, layout)| layout.bounds().contains(cursor_position)); - if let Some(((pane, content), layout)) = clicked_region.next() { + if let Some(((pane, _), layout)) = clicked_region.next() { if let Some(on_click) = &on_click { shell.publish(on_click(pane)); } - if let Some(on_drag) = &on_drag { - if content.can_be_dragged_at(layout, cursor_position) { - let pane_position = layout.position(); - - let origin = cursor_position - - Vector::new(pane_position.x, pane_position.y); - - *action = state::Action::Dragging { pane, origin }; - - shell.publish(on_drag(DragEvent::Picked { pane })); - } - } + let pane_position = layout.position(); + let origin = + cursor_position - Vector::new(pane_position.x, pane_position.y); + *action = state::Action::Clicking { pane, origin }; } } @@ -749,7 +778,7 @@ pub fn mouse_interaction( spacing: f32, resize_leeway: Option<f32>, ) -> Option<mouse::Interaction> { - if action.picked_pane().is_some() { + if action.clicked_pane().is_some() || action.picked_pane().is_some() { return Some(mouse::Interaction::Grabbing); } diff --git a/widget/src/pane_grid/content.rs b/widget/src/pane_grid/content.rs index 826ea663..ee00f186 100644 --- a/widget/src/pane_grid/content.rs +++ b/widget/src/pane_grid/content.rs @@ -165,7 +165,7 @@ where let title_bar_size = title_bar_layout.size(); - let mut body_layout = self.body.as_widget().layout( + let body_layout = self.body.as_widget().layout( &mut tree.children[0], renderer, &layout::Limits::new( @@ -177,11 +177,12 @@ where ), ); - body_layout.move_to(Point::new(0.0, title_bar_size.height)); - layout::Node::with_children( max_size, - vec![title_bar_layout, body_layout], + vec![ + title_bar_layout, + body_layout.move_to(Point::new(0.0, title_bar_size.height)), + ], ) } else { self.body.as_widget().layout( diff --git a/widget/src/pane_grid/state.rs b/widget/src/pane_grid/state.rs index 481cd770..5d1fe254 100644 --- a/widget/src/pane_grid/state.rs +++ b/widget/src/pane_grid/state.rs @@ -403,6 +403,15 @@ pub enum Action { /// /// [`PaneGrid`]: super::PaneGrid Idle, + /// A [`Pane`] in the [`PaneGrid`] is being clicked. + /// + /// [`PaneGrid`]: super::PaneGrid + Clicking { + /// The [`Pane`] being clicked. + pane: Pane, + /// The starting [`Point`] of the click interaction. + origin: Point, + }, /// A [`Pane`] in the [`PaneGrid`] is being dragged. /// /// [`PaneGrid`]: super::PaneGrid @@ -432,6 +441,14 @@ impl Action { } } + /// Returns the current [`Pane`] that is being clicked, if any. + pub fn clicked_pane(&self) -> Option<(Pane, Point)> { + match *self { + Action::Clicking { pane, origin, .. } => Some((pane, origin)), + _ => None, + } + } + /// Returns the current [`Split`] that is being dragged, if any. pub fn picked_split(&self) -> Option<(Split, Axis)> { match *self { diff --git a/widget/src/pane_grid/title_bar.rs b/widget/src/pane_grid/title_bar.rs index f4dbb6b1..eb21b743 100644 --- a/widget/src/pane_grid/title_bar.rs +++ b/widget/src/pane_grid/title_bar.rs @@ -217,7 +217,7 @@ where renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { - let limits = limits.pad(self.padding); + let limits = limits.shrink(self.padding); let max_size = limits.max(); let title_layout = self.content.as_widget().layout( @@ -228,8 +228,8 @@ where let title_size = title_layout.size(); - let mut node = if let Some(controls) = &self.controls { - let mut controls_layout = controls.as_widget().layout( + let node = if let Some(controls) = &self.controls { + let controls_layout = controls.as_widget().layout( &mut tree.children[1], renderer, &layout::Limits::new(Size::ZERO, max_size), @@ -240,11 +240,13 @@ where let height = title_size.height.max(controls_size.height); - controls_layout.move_to(Point::new(space_before_controls, 0.0)); - layout::Node::with_children( Size::new(max_size.width, height), - vec![title_layout, controls_layout], + vec![ + title_layout, + controls_layout + .move_to(Point::new(space_before_controls, 0.0)), + ], ) } else { layout::Node::with_children( @@ -253,9 +255,7 @@ where ) }; - node.move_to(Point::new(self.padding.left, self.padding.top)); - - layout::Node::with_children(node.size().pad(self.padding), vec![node]) + layout::Node::container(node, self.padding) } pub(crate) fn operate( |