From e5c9dd54b3f51e913f39b38e8907c321c8bfd040 Mon Sep 17 00:00:00 2001 From: Joao Freitas <51237625+jhff@users.noreply.github.com> Date: Fri, 19 May 2023 11:24:52 +0100 Subject: [PATCH 1/6] Add ability to drag pane to the pane grid edges & optional style for dragged pane --- examples/pane_grid/src/main.rs | 13 +- style/src/pane_grid.rs | 2 +- widget/src/pane_grid.rs | 281 +++++++++++++++++++++++---------- widget/src/pane_grid/node.rs | 10 ++ widget/src/pane_grid/state.rs | 89 +++++++++-- 5 files changed, 291 insertions(+), 104 deletions(-) diff --git a/examples/pane_grid/src/main.rs b/examples/pane_grid/src/main.rs index 54c36d69a9..c5652e2d32 100644 --- a/examples/pane_grid/src/main.rs +++ b/examples/pane_grid/src/main.rs @@ -108,10 +108,15 @@ impl Application for Example { Message::Dragged(pane_grid::DragEvent::Dropped { pane, target, - region, - }) => { - self.panes.split_with(&target, &pane, region); - } + }) => match target { + pane_grid::Target::PaneGrid(edge) => { + self.panes.move_to_edge(&pane, edge) + } + pane_grid::Target::Pane { + pane: target, + region, + } => self.panes.split_with(&target, &pane, region), + }, Message::Dragged(_) => {} Message::TogglePin(pane) => { if let Some(Pane { is_pinned, .. }) = self.panes.get_mut(&pane) diff --git a/style/src/pane_grid.rs b/style/src/pane_grid.rs index b99af9554f..dfdc918666 100644 --- a/style/src/pane_grid.rs +++ b/style/src/pane_grid.rs @@ -31,7 +31,7 @@ pub trait StyleSheet { /// The supported style of the [`StyleSheet`]. type Style: Default; - /// The [`Region`] to draw when a pane is hovered. + /// The [`Appearance`] to draw when a pane is hovered. fn hovered_region(&self, style: &Self::Style) -> Appearance; /// The [`Line`] to draw when a split is picked. diff --git a/widget/src/pane_grid.rs b/widget/src/pane_grid.rs index 040d6bb3b4..0a8500dc5e 100644 --- a/widget/src/pane_grid.rs +++ b/widget/src/pane_grid.rs @@ -581,39 +581,49 @@ pub fn update<'a, Message, T: Draggable>( | Event::Touch(touch::Event::FingerLost { .. }) => { if let Some((pane, _)) = action.picked_pane() { if let Some(on_drag) = on_drag { - let dropped_region = - cursor.position().and_then(|cursor_position| { - contents + if let Some(cursor_position) = cursor.position() { + let event = if let Some(edge) = + in_edge(layout, cursor_position) + { + DragEvent::Dropped { + pane, + target: Target::PaneGrid(edge), + } + } else { + let dropped_region = contents .zip(layout.children()) .filter_map(|(target, layout)| { layout_region(layout, cursor_position) .map(|region| (target, region)) }) - .next() - }); - - let event = match dropped_region { - Some(((target, _), region)) if pane != target => { - DragEvent::Dropped { - pane, - target, - region, + .next(); + + match dropped_region { + Some(((target, _), region)) + if pane != target => + { + DragEvent::Dropped { + pane, + target: Target::Pane { + pane: target, + region, + }, + } + } + _ => DragEvent::Canceled { pane }, } - } - _ => DragEvent::Canceled { pane }, - }; + }; - shell.publish(on_drag(event)); + shell.publish(on_drag(event)); + } } - *action = state::Action::Idle; - event_status = event::Status::Captured; } else if action.picked_split().is_some() { - *action = state::Action::Idle; - event_status = event::Status::Captured; } + + *action = state::Action::Idle; } Event::Mouse(mouse::Event::CursorMoved { .. }) | Event::Touch(touch::Event::FingerMoved { .. }) => { @@ -671,13 +681,13 @@ fn layout_region(layout: Layout<'_>, cursor_position: Point) -> Option { } let region = if cursor_position.x < (bounds.x + bounds.width / 3.0) { - Region::Left + Region::Edge(Edge::Left) } else if cursor_position.x > (bounds.x + 2.0 * bounds.width / 3.0) { - Region::Right + Region::Edge(Edge::Right) } else if cursor_position.y < (bounds.y + bounds.height / 3.0) { - Region::Top + Region::Edge(Edge::Top) } else if cursor_position.y > (bounds.y + 2.0 * bounds.height / 3.0) { - Region::Bottom + Region::Edge(Edge::Bottom) } else { Region::Center }; @@ -833,28 +843,32 @@ pub fn draw( let mut render_picked_pane = None; - for ((id, pane), layout) in contents.zip(layout.children()) { + let cursor_in_edge = cursor + .position() + .and_then(|cursor_position| in_edge(layout, cursor_position)); + + for ((id, pane), pane_layout) in contents.zip(layout.children()) { match picked_pane { Some((dragging, origin)) if id == dragging => { - render_picked_pane = Some((pane, origin, layout)); + render_picked_pane = Some((pane, origin, pane_layout)); } Some((dragging, _)) if id != dragging => { draw_pane( pane, renderer, default_style, - layout, + pane_layout, pane_cursor, viewport, ); - if picked_pane.is_some() { + if picked_pane.is_some() && cursor_in_edge.is_none() { if let Some(region) = cursor.position().and_then(|cursor_position| { - layout_region(layout, cursor_position) + layout_region(pane_layout, cursor_position) }) { - let bounds = layout_region_bounds(layout, region); + let bounds = layout_region_bounds(pane_layout, region); let hovered_region_style = theme.hovered_region(style); renderer.fill_quad( @@ -875,7 +889,7 @@ pub fn draw( pane, renderer, default_style, - layout, + pane_layout, pane_cursor, viewport, ); @@ -883,6 +897,23 @@ pub fn draw( } } + if picked_pane.is_some() { + if let Some(edge) = cursor_in_edge { + let hovered_region_style = theme.hovered_region(style); + let bounds = edge_bounds(layout, edge); + + renderer.fill_quad( + renderer::Quad { + bounds, + border_radius: hovered_region_style.border_radius.into(), + border_width: hovered_region_style.border_width, + border_color: hovered_region_style.border_color, + }, + theme.hovered_region(style).background, + ); + } + } + // Render picked pane last if let Some((pane, origin, layout)) = render_picked_pane { if let Some(cursor_position) = cursor.position() { @@ -907,71 +938,131 @@ pub fn draw( } } - if let Some((axis, split_region, is_picked)) = picked_split { - let highlight = if is_picked { - theme.picked_split(style) - } else { - theme.hovered_split(style) - }; - - if let Some(highlight) = highlight { - renderer.fill_quad( - renderer::Quad { - bounds: match axis { - Axis::Horizontal => Rectangle { - x: split_region.x, - y: (split_region.y - + (split_region.height - highlight.width) - / 2.0) - .round(), - width: split_region.width, - height: highlight.width, - }, - Axis::Vertical => Rectangle { - x: (split_region.x - + (split_region.width - highlight.width) / 2.0) - .round(), - y: split_region.y, - width: highlight.width, - height: split_region.height, + if picked_pane.is_none() { + if let Some((axis, split_region, is_picked)) = picked_split { + let highlight = if is_picked { + theme.picked_split(style) + } else { + theme.hovered_split(style) + }; + + if let Some(highlight) = highlight { + renderer.fill_quad( + renderer::Quad { + bounds: match axis { + Axis::Horizontal => Rectangle { + x: split_region.x, + y: (split_region.y + + (split_region.height - highlight.width) + / 2.0) + .round(), + width: split_region.width, + height: highlight.width, + }, + Axis::Vertical => Rectangle { + x: (split_region.x + + (split_region.width - highlight.width) + / 2.0) + .round(), + y: split_region.y, + width: highlight.width, + height: split_region.height, + }, }, + border_radius: 0.0.into(), + border_width: 0.0, + border_color: Color::TRANSPARENT, }, - border_radius: 0.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, - }, - highlight.color, - ); + highlight.color, + ); + } } } } -fn layout_region_bounds(layout: Layout<'_>, region: Region) -> Rectangle { +const THICKNESS_RATIO: f32 = 25.0; + +fn in_edge(layout: Layout<'_>, cursor: Point) -> Option { let bounds = layout.bounds(); - match region { - Region::Center => bounds, - Region::Top => Rectangle { - height: bounds.height / 2.0, + let height_thickness = bounds.height / THICKNESS_RATIO; + let width_thickness = bounds.width / THICKNESS_RATIO; + let thickness = height_thickness.min(width_thickness); + + if cursor.x > bounds.x && cursor.x < bounds.x + thickness { + Some(Edge::Left) + } else if cursor.x > bounds.x + bounds.width - thickness + && cursor.x < bounds.x + bounds.width + { + Some(Edge::Right) + } else if cursor.y > bounds.y && cursor.y < bounds.y + thickness { + Some(Edge::Top) + } else if cursor.y > bounds.y + bounds.height - thickness + && cursor.y < bounds.y + bounds.height + { + Some(Edge::Bottom) + } else { + None + } +} + +fn edge_bounds(layout: Layout<'_>, edge: Edge) -> Rectangle { + let bounds = layout.bounds(); + + let height_thickness = bounds.height / THICKNESS_RATIO; + let width_thickness = bounds.width / THICKNESS_RATIO; + let thickness = height_thickness.min(width_thickness); + + match edge { + Edge::Top => Rectangle { + height: thickness, ..bounds }, - Region::Left => Rectangle { - width: bounds.width / 2.0, + Edge::Left => Rectangle { + width: thickness, ..bounds }, - Region::Right => Rectangle { - x: bounds.x + bounds.width / 2.0, - width: bounds.width / 2.0, + Edge::Right => Rectangle { + x: bounds.x + bounds.width - thickness, + width: thickness, ..bounds }, - Region::Bottom => Rectangle { - y: bounds.y + bounds.height / 2.0, - height: bounds.height / 2.0, + Edge::Bottom => Rectangle { + y: bounds.y + bounds.height - thickness, + height: thickness, ..bounds }, } } +fn layout_region_bounds(layout: Layout<'_>, region: Region) -> Rectangle { + let bounds = layout.bounds(); + + match region { + Region::Center => bounds, + Region::Edge(edge) => match edge { + Edge::Top => Rectangle { + height: bounds.height / 2.0, + ..bounds + }, + Edge::Left => Rectangle { + width: bounds.width / 2.0, + ..bounds + }, + Edge::Right => Rectangle { + x: bounds.x + bounds.width / 2.0, + width: bounds.width / 2.0, + ..bounds + }, + Edge::Bottom => Rectangle { + y: bounds.y + bounds.height / 2.0, + height: bounds.height / 2.0, + ..bounds + }, + }, + } +} + /// An event produced during a drag and drop interaction of a [`PaneGrid`]. #[derive(Debug, Clone, Copy)] pub enum DragEvent { @@ -986,11 +1077,8 @@ pub enum DragEvent { /// The picked [`Pane`]. pane: Pane, - /// The [`Pane`] where the picked one was dropped on. - target: Pane, - - /// The [`Region`] of the target [`Pane`] where the picked one was dropped on. - region: Region, + /// The [`Target`] where the picked [`Pane`] was dropped on. + target: Target, }, /// A [`Pane`] was picked and then dropped outside of other [`Pane`] @@ -1001,19 +1089,40 @@ pub enum DragEvent { }, } +/// The [`Target`] area a pane can be dropped on. +#[derive(Debug, Clone, Copy)] +pub enum Target { + /// The [`Edge`} of the full [`PaneGrid`]. + PaneGrid(Edge), + /// A single [`Pane`] of the [`PaneGrid`]. + Pane { + /// The targetted [`Pane`]. + pane: Pane, + /// The targetted area of the [`Pane`]. + region: Region, + }, +} + /// The region of a [`Pane`]. #[derive(Debug, Clone, Copy, Default)] pub enum Region { /// Center region. #[default] Center, - /// Top region. + /// Edge region. + Edge(Edge), +} + +/// The edges of an area. +#[derive(Debug, Clone, Copy)] +pub enum Edge { + /// Top edge. Top, - /// Left region. + /// Left edge. Left, - /// Right region. + /// Right edge. Right, - /// Bottom region. + /// Bottom edge. Bottom, } diff --git a/widget/src/pane_grid/node.rs b/widget/src/pane_grid/node.rs index 3976acd8b1..6de5920f5c 100644 --- a/widget/src/pane_grid/node.rs +++ b/widget/src/pane_grid/node.rs @@ -120,6 +120,16 @@ impl Node { }; } + pub(crate) fn split_inverse(&mut self, id: Split, axis: Axis, pane: Pane) { + *self = Node::Split { + id, + axis, + ratio: 0.5, + a: Box::new(Node::Pane(pane)), + b: Box::new(self.clone()), + }; + } + pub(crate) fn update(&mut self, f: &impl Fn(&mut Node)) { if let Node::Split { a, b, .. } = self { a.update(f); diff --git a/widget/src/pane_grid/state.rs b/widget/src/pane_grid/state.rs index 1f034ca336..34781a90e6 100644 --- a/widget/src/pane_grid/state.rs +++ b/widget/src/pane_grid/state.rs @@ -3,7 +3,7 @@ //! [`PaneGrid`]: crate::widget::PaneGrid use crate::core::{Point, Size}; use crate::pane_grid::{ - Axis, Configuration, Direction, Node, Pane, Region, Split, + Axis, Configuration, Direction, Edge, Node, Pane, Region, Split, }; use std::collections::HashMap; @@ -173,18 +173,20 @@ impl State { pub fn split_with(&mut self, target: &Pane, pane: &Pane, region: Region) { match region { Region::Center => self.swap(pane, target), - Region::Top => { - self.split_and_swap(Axis::Horizontal, target, pane, true) - } - Region::Bottom => { - self.split_and_swap(Axis::Horizontal, target, pane, false) - } - Region::Left => { - self.split_and_swap(Axis::Vertical, target, pane, true) - } - Region::Right => { - self.split_and_swap(Axis::Vertical, target, pane, false) - } + Region::Edge(edge) => match edge { + Edge::Top => { + self.split_and_swap(Axis::Horizontal, target, pane, true) + } + Edge::Bottom => { + self.split_and_swap(Axis::Horizontal, target, pane, false) + } + Edge::Left => { + self.split_and_swap(Axis::Vertical, target, pane, true) + } + Edge::Right => { + self.split_and_swap(Axis::Vertical, target, pane, false) + } + }, } } @@ -204,6 +206,67 @@ impl State { } } + /// Move [`Pane`] to an [`Edge`] of the [`PaneGrid`]. + pub fn move_to_edge(&mut self, pane: &Pane, edge: Edge) { + match edge { + Edge::Top => { + self.split_major_node_and_swap(Axis::Horizontal, pane, true) + } + Edge::Bottom => { + self.split_major_node_and_swap(Axis::Horizontal, pane, false) + } + Edge::Left => { + self.split_major_node_and_swap(Axis::Vertical, pane, true) + } + Edge::Right => { + self.split_major_node_and_swap(Axis::Vertical, pane, false) + } + } + } + + fn split_major_node_and_swap( + &mut self, + axis: Axis, + pane: &Pane, + swap: bool, + ) { + if let Some((state, _)) = self.close(pane) { + let _ = self.split_major_node(axis, state, swap); + } + } + + fn split_major_node( + &mut self, + axis: Axis, + state: T, + swap: bool, + ) -> Option<(Pane, Split)> { + let major_node = &mut self.internal.layout; + + let new_pane = { + self.internal.last_id = self.internal.last_id.checked_add(1)?; + + Pane(self.internal.last_id) + }; + + let new_split = { + self.internal.last_id = self.internal.last_id.checked_add(1)?; + + Split(self.internal.last_id) + }; + + if swap { + major_node.split_inverse(new_split, axis, new_pane) + } else { + major_node.split(new_split, axis, new_pane) + }; + + let _ = self.panes.insert(new_pane, state); + let _ = self.maximized.take(); + + Some((new_pane, new_split)) + } + /// Swaps the position of the provided panes in the [`State`]. /// /// If you want to swap panes on drag and drop in your [`PaneGrid`], you From 995c7c1ca9793536ad9b9d1cac94ae7b5b9a8f0a Mon Sep 17 00:00:00 2001 From: Joao Freitas <51237625+jhff@users.noreply.github.com> Date: Mon, 22 May 2023 13:24:48 +0100 Subject: [PATCH 2/6] Reuse code --- widget/src/pane_grid/state.rs | 57 ++++++++++++++--------------------- 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/widget/src/pane_grid/state.rs b/widget/src/pane_grid/state.rs index 34781a90e6..332b6837be 100644 --- a/widget/src/pane_grid/state.rs +++ b/widget/src/pane_grid/state.rs @@ -145,7 +145,22 @@ impl State { pane: &Pane, state: T, ) -> Option<(Pane, Split)> { - let node = self.internal.layout.find(pane)?; + self.split_node(axis, Some(pane), state, false) + } + + fn split_node( + &mut self, + axis: Axis, + pane: Option<&Pane>, + state: T, + inverse: bool, + ) -> Option<(Pane, Split)> { + let node = if let Some(pane) = pane { + self.internal.layout.find(pane)? + } else { + // Major node + &mut self.internal.layout + }; let new_pane = { self.internal.last_id = self.internal.last_id.checked_add(1)?; @@ -159,7 +174,11 @@ impl State { Split(self.internal.last_id) }; - node.split(new_split, axis, new_pane); + if inverse { + node.split_inverse(new_split, axis, new_pane); + } else { + node.split(new_split, axis, new_pane); + } let _ = self.panes.insert(new_pane, state); let _ = self.maximized.take(); @@ -231,42 +250,10 @@ impl State { swap: bool, ) { if let Some((state, _)) = self.close(pane) { - let _ = self.split_major_node(axis, state, swap); + let _ = self.split_node(axis, None, state, swap); } } - fn split_major_node( - &mut self, - axis: Axis, - state: T, - swap: bool, - ) -> Option<(Pane, Split)> { - let major_node = &mut self.internal.layout; - - let new_pane = { - self.internal.last_id = self.internal.last_id.checked_add(1)?; - - Pane(self.internal.last_id) - }; - - let new_split = { - self.internal.last_id = self.internal.last_id.checked_add(1)?; - - Split(self.internal.last_id) - }; - - if swap { - major_node.split_inverse(new_split, axis, new_pane) - } else { - major_node.split(new_split, axis, new_pane) - }; - - let _ = self.panes.insert(new_pane, state); - let _ = self.maximized.take(); - - Some((new_pane, new_split)) - } - /// Swaps the position of the provided panes in the [`State`]. /// /// If you want to swap panes on drag and drop in your [`PaneGrid`], you From f83ee1e9f99d1ec5621b4dba35ce0d0fced95442 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Thu, 6 Jul 2023 07:37:25 +0200 Subject: [PATCH 3/6] Call `in_edge` only when `picked_pane.is_some()` --- widget/src/pane_grid.rs | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/widget/src/pane_grid.rs b/widget/src/pane_grid.rs index 0a8500dc5e..213460a543 100644 --- a/widget/src/pane_grid.rs +++ b/widget/src/pane_grid.rs @@ -843,9 +843,13 @@ pub fn draw( let mut render_picked_pane = None; - let cursor_in_edge = cursor - .position() - .and_then(|cursor_position| in_edge(layout, cursor_position)); + let pane_in_edge = if picked_pane.is_some() { + cursor + .position() + .and_then(|cursor_position| in_edge(layout, cursor_position)) + } else { + None + }; for ((id, pane), pane_layout) in contents.zip(layout.children()) { match picked_pane { @@ -862,7 +866,7 @@ pub fn draw( viewport, ); - if picked_pane.is_some() && cursor_in_edge.is_none() { + if picked_pane.is_some() && pane_in_edge.is_none() { if let Some(region) = cursor.position().and_then(|cursor_position| { layout_region(pane_layout, cursor_position) @@ -897,21 +901,19 @@ pub fn draw( } } - if picked_pane.is_some() { - if let Some(edge) = cursor_in_edge { - let hovered_region_style = theme.hovered_region(style); - let bounds = edge_bounds(layout, edge); - - renderer.fill_quad( - renderer::Quad { - bounds, - border_radius: hovered_region_style.border_radius.into(), - border_width: hovered_region_style.border_width, - border_color: hovered_region_style.border_color, - }, - theme.hovered_region(style).background, - ); - } + if let Some(edge) = pane_in_edge { + let hovered_region_style = theme.hovered_region(style); + let bounds = edge_bounds(layout, edge); + + renderer.fill_quad( + renderer::Quad { + bounds, + border_radius: hovered_region_style.border_radius.into(), + border_width: hovered_region_style.border_width, + border_color: hovered_region_style.border_color, + }, + theme.hovered_region(style).background, + ); } // Render picked pane last From ecce8bbcee45dddedef8a33bf3dc086d76c27b39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Thu, 6 Jul 2023 07:37:51 +0200 Subject: [PATCH 4/6] Simplify `Target` enum in `widget::pane_grid` --- examples/pane_grid/src/main.rs | 9 ++++----- widget/src/pane_grid.rs | 18 +++++------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/examples/pane_grid/src/main.rs b/examples/pane_grid/src/main.rs index c5652e2d32..1361eeb960 100644 --- a/examples/pane_grid/src/main.rs +++ b/examples/pane_grid/src/main.rs @@ -109,13 +109,12 @@ impl Application for Example { pane, target, }) => match target { - pane_grid::Target::PaneGrid(edge) => { + pane_grid::Target::Edge(edge) => { self.panes.move_to_edge(&pane, edge) } - pane_grid::Target::Pane { - pane: target, - region, - } => self.panes.split_with(&target, &pane, region), + pane_grid::Target::Pane(target, region) => { + self.panes.split_with(&target, &pane, region) + } }, Message::Dragged(_) => {} Message::TogglePin(pane) => { diff --git a/widget/src/pane_grid.rs b/widget/src/pane_grid.rs index 213460a543..23ab4181e3 100644 --- a/widget/src/pane_grid.rs +++ b/widget/src/pane_grid.rs @@ -587,7 +587,7 @@ pub fn update<'a, Message, T: Draggable>( { DragEvent::Dropped { pane, - target: Target::PaneGrid(edge), + target: Target::Edge(edge), } } else { let dropped_region = contents @@ -604,10 +604,7 @@ pub fn update<'a, Message, T: Draggable>( { DragEvent::Dropped { pane, - target: Target::Pane { - pane: target, - region, - }, + target: Target::Pane(target, region), } } _ => DragEvent::Canceled { pane }, @@ -1094,15 +1091,10 @@ pub enum DragEvent { /// The [`Target`] area a pane can be dropped on. #[derive(Debug, Clone, Copy)] pub enum Target { - /// The [`Edge`} of the full [`PaneGrid`]. - PaneGrid(Edge), + /// An [`Edge`] of the full [`PaneGrid`]. + Edge(Edge), /// A single [`Pane`] of the [`PaneGrid`]. - Pane { - /// The targetted [`Pane`]. - pane: Pane, - /// The targetted area of the [`Pane`]. - region: Region, - }, + Pane(Pane, Region), } /// The region of a [`Pane`]. From c5a623f32b3d972501bb02d87d296381b66f9481 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Thu, 6 Jul 2023 07:45:47 +0200 Subject: [PATCH 5/6] Introduce `drop` helper to `pane_grid::State` --- examples/pane_grid/src/main.rs | 11 ++----- widget/src/pane_grid/state.rs | 58 ++++++++++++++++++++-------------- 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/examples/pane_grid/src/main.rs b/examples/pane_grid/src/main.rs index 1361eeb960..04896e2063 100644 --- a/examples/pane_grid/src/main.rs +++ b/examples/pane_grid/src/main.rs @@ -108,14 +108,9 @@ impl Application for Example { Message::Dragged(pane_grid::DragEvent::Dropped { pane, target, - }) => match target { - pane_grid::Target::Edge(edge) => { - self.panes.move_to_edge(&pane, edge) - } - pane_grid::Target::Pane(target, region) => { - self.panes.split_with(&target, &pane, region) - } - }, + }) => { + self.panes.drop(&pane, target); + } Message::Dragged(_) => {} Message::TogglePin(pane) => { if let Some(Pane { is_pinned, .. }) = self.panes.get_mut(&pane) diff --git a/widget/src/pane_grid/state.rs b/widget/src/pane_grid/state.rs index 332b6837be..6fd1589039 100644 --- a/widget/src/pane_grid/state.rs +++ b/widget/src/pane_grid/state.rs @@ -3,7 +3,7 @@ //! [`PaneGrid`]: crate::widget::PaneGrid use crate::core::{Point, Size}; use crate::pane_grid::{ - Axis, Configuration, Direction, Edge, Node, Pane, Region, Split, + Axis, Configuration, Direction, Edge, Node, Pane, Region, Split, Target, }; use std::collections::HashMap; @@ -148,6 +148,39 @@ impl State { self.split_node(axis, Some(pane), state, false) } + /// Split a target [`Pane`] with a given [`Pane`] on a given [`Region`]. + /// + /// Panes will be swapped by default for [`Region::Center`]. + pub fn split_with(&mut self, target: &Pane, pane: &Pane, region: Region) { + match region { + Region::Center => self.swap(pane, target), + Region::Edge(edge) => match edge { + Edge::Top => { + self.split_and_swap(Axis::Horizontal, target, pane, true) + } + Edge::Bottom => { + self.split_and_swap(Axis::Horizontal, target, pane, false) + } + Edge::Left => { + self.split_and_swap(Axis::Vertical, target, pane, true) + } + Edge::Right => { + self.split_and_swap(Axis::Vertical, target, pane, false) + } + }, + } + } + + /// Drops the given [`Pane`] into the provided [`Target`]. + pub fn drop(&mut self, pane: &Pane, target: Target) { + match target { + Target::Edge(edge) => self.move_to_edge(pane, edge), + Target::Pane(target, region) => { + self.split_with(&target, pane, region) + } + } + } + fn split_node( &mut self, axis: Axis, @@ -186,29 +219,6 @@ impl State { Some((new_pane, new_split)) } - /// Split a target [`Pane`] with a given [`Pane`] on a given [`Region`]. - /// - /// Panes will be swapped by default for [`Region::Center`]. - pub fn split_with(&mut self, target: &Pane, pane: &Pane, region: Region) { - match region { - Region::Center => self.swap(pane, target), - Region::Edge(edge) => match edge { - Edge::Top => { - self.split_and_swap(Axis::Horizontal, target, pane, true) - } - Edge::Bottom => { - self.split_and_swap(Axis::Horizontal, target, pane, false) - } - Edge::Left => { - self.split_and_swap(Axis::Vertical, target, pane, true) - } - Edge::Right => { - self.split_and_swap(Axis::Vertical, target, pane, false) - } - }, - } - } - fn split_and_swap( &mut self, axis: Axis, From 0964f12db7002f535f8eeda1791ea8962be6e71a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Thu, 6 Jul 2023 08:26:46 +0200 Subject: [PATCH 6/6] Remove useless conversion in `widget::pane_grid` --- widget/src/pane_grid.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widget/src/pane_grid.rs b/widget/src/pane_grid.rs index 23ab4181e3..31bb0e867a 100644 --- a/widget/src/pane_grid.rs +++ b/widget/src/pane_grid.rs @@ -905,7 +905,7 @@ pub fn draw( renderer.fill_quad( renderer::Quad { bounds, - border_radius: hovered_region_style.border_radius.into(), + border_radius: hovered_region_style.border_radius, border_width: hovered_region_style.border_width, border_color: hovered_region_style.border_color, },