diff options
author | 2022-03-10 19:25:57 +0700 | |
---|---|---|
committer | 2022-03-14 17:44:25 +0700 | |
commit | 6dd187ff0822230f084e43636b1aabeb1baf06f6 (patch) | |
tree | 27426980b2882025a3c812ba2401d3bf8f6dca8d /native/src/widget/pane_grid | |
parent | 9f27969d14232355ad628431fb67aa07e42e768f (diff) | |
download | iced-6dd187ff0822230f084e43636b1aabeb1baf06f6.tar.gz iced-6dd187ff0822230f084e43636b1aabeb1baf06f6.tar.bz2 iced-6dd187ff0822230f084e43636b1aabeb1baf06f6.zip |
Implement `pure` version of `PaneGrid` widget
Diffstat (limited to 'native/src/widget/pane_grid')
-rw-r--r-- | native/src/widget/pane_grid/axis.rs | 7 | ||||
-rw-r--r-- | native/src/widget/pane_grid/content.rs | 39 | ||||
-rw-r--r-- | native/src/widget/pane_grid/draggable.rs | 12 | ||||
-rw-r--r-- | native/src/widget/pane_grid/state.rs | 114 |
4 files changed, 101 insertions, 71 deletions
diff --git a/native/src/widget/pane_grid/axis.rs b/native/src/widget/pane_grid/axis.rs index 2320cb7c..02bde064 100644 --- a/native/src/widget/pane_grid/axis.rs +++ b/native/src/widget/pane_grid/axis.rs @@ -10,7 +10,9 @@ pub enum Axis { } impl Axis { - pub(super) fn split( + /// Splits the provided [`Rectangle`] on the current [`Axis`] with the + /// given `ratio` and `spacing`. + pub fn split( &self, rectangle: &Rectangle, ratio: f32, @@ -54,7 +56,8 @@ impl Axis { } } - pub(super) fn split_line_bounds( + /// Calculates the bounds of the split line in a [`Rectangle`] region. + pub fn split_line_bounds( &self, rectangle: Rectangle, ratio: f32, diff --git a/native/src/widget/pane_grid/content.rs b/native/src/widget/pane_grid/content.rs index 8b0e8d2a..f0ed0426 100644 --- a/native/src/widget/pane_grid/content.rs +++ b/native/src/widget/pane_grid/content.rs @@ -4,7 +4,7 @@ use crate::mouse; use crate::overlay; use crate::renderer; use crate::widget::container; -use crate::widget::pane_grid::TitleBar; +use crate::widget::pane_grid::{Draggable, TitleBar}; use crate::{Clipboard, Element, Layout, Point, Rectangle, Shell, Size}; /// The content of a [`Pane`]. @@ -101,23 +101,6 @@ where } } - /// Returns whether the [`Content`] with the given [`Layout`] can be picked - /// at the provided cursor position. - pub fn can_be_picked_at( - &self, - layout: Layout<'_>, - cursor_position: Point, - ) -> bool { - if let Some(title_bar) = &self.title_bar { - let mut children = layout.children(); - let title_bar_layout = children.next().unwrap(); - - title_bar.is_over_pick_area(title_bar_layout, cursor_position) - } else { - false - } - } - pub(crate) fn layout( &self, renderer: &Renderer, @@ -253,6 +236,26 @@ where } } +impl<'a, Message, Renderer> Draggable for &Content<'a, Message, Renderer> +where + Renderer: crate::Renderer, +{ + fn can_be_dragged_at( + &self, + layout: Layout<'_>, + cursor_position: Point, + ) -> bool { + if let Some(title_bar) = &self.title_bar { + let mut children = layout.children(); + let title_bar_layout = children.next().unwrap(); + + title_bar.is_over_pick_area(title_bar_layout, cursor_position) + } else { + false + } + } +} + impl<'a, T, Message, Renderer> From<T> for Content<'a, Message, Renderer> where T: Into<Element<'a, Message, Renderer>>, diff --git a/native/src/widget/pane_grid/draggable.rs b/native/src/widget/pane_grid/draggable.rs new file mode 100644 index 00000000..6044871d --- /dev/null +++ b/native/src/widget/pane_grid/draggable.rs @@ -0,0 +1,12 @@ +use crate::{Layout, Point}; + +/// A pane that can be dragged. +pub trait Draggable { + /// Returns whether the [`Draggable`] with the given [`Layout`] can be picked + /// at the provided cursor position. + fn can_be_dragged_at( + &self, + layout: Layout<'_>, + cursor_position: Point, + ) -> bool; +} diff --git a/native/src/widget/pane_grid/state.rs b/native/src/widget/pane_grid/state.rs index feea0dec..f9ea21f4 100644 --- a/native/src/widget/pane_grid/state.rs +++ b/native/src/widget/pane_grid/state.rs @@ -1,3 +1,4 @@ +//! The state of a [`PaneGrid`]. use crate::widget::pane_grid::{ Axis, Configuration, Direction, Node, Pane, Split, }; @@ -19,8 +20,13 @@ use std::collections::{BTreeMap, HashMap}; /// [`PaneGrid::new`]: crate::widget::PaneGrid::new #[derive(Debug, Clone)] pub struct State<T> { - pub(super) panes: HashMap<Pane, T>, - pub(super) internal: Internal, + /// The panes of the [`PaneGrid`]. + pub panes: HashMap<Pane, T>, + + /// The internal state of the [`PaneGrid`]. + pub internal: Internal, + + pub(super) action: Action, } impl<T> State<T> { @@ -39,16 +45,13 @@ impl<T> State<T> { pub fn with_configuration(config: impl Into<Configuration<T>>) -> Self { let mut panes = HashMap::new(); - let (layout, last_id) = - Self::distribute_content(&mut panes, config.into(), 0); + let internal = + Internal::from_configuration(&mut panes, config.into(), 0); State { panes, - internal: Internal { - layout, - last_id, - action: Action::Idle, - }, + internal, + action: Action::Idle, } } @@ -192,16 +195,34 @@ impl<T> State<T> { None } } +} + +/// The internal state of a [`PaneGrid`]. +#[derive(Debug, Clone)] +pub struct Internal { + layout: Node, + last_id: usize, +} - fn distribute_content( +impl Internal { + /// Initializes the [`Internal`] state of a [`PaneGrid`] from a + /// [`Configuration`]. + pub fn from_configuration<T>( panes: &mut HashMap<Pane, T>, content: Configuration<T>, next_id: usize, - ) -> (Node, usize) { - match content { + ) -> Self { + let (layout, last_id) = match content { Configuration::Split { axis, ratio, a, b } => { - let (a, next_id) = Self::distribute_content(panes, *a, next_id); - let (b, next_id) = Self::distribute_content(panes, *b, next_id); + let Internal { + layout: a, + last_id: next_id, + } = Self::from_configuration(panes, *a, next_id); + + let Internal { + layout: b, + last_id: next_id, + } = Self::from_configuration(panes, *b, next_id); ( Node::Split { @@ -220,39 +241,53 @@ impl<T> State<T> { (Node::Pane(id), next_id + 1) } - } - } -} + }; -#[derive(Debug, Clone)] -pub struct Internal { - layout: Node, - last_id: usize, - action: Action, + Self { layout, last_id } + } } +/// The current action of a [`PaneGrid`]. #[derive(Debug, Clone, Copy, PartialEq)] pub enum Action { + /// The [`PaneGrid`] is idle. Idle, - Dragging { pane: Pane, origin: Point }, - Resizing { split: Split, axis: Axis }, + /// A [`Pane`] in the [`PaneGrid`] is being dragged. + Dragging { + /// The [`Pane`] being dragged. + pane: Pane, + /// The starting [`Point`] of the drag interaction. + origin: Point, + }, + /// A [`Split`] in the [`PaneGrid`] is being dragged. + Resizing { + /// The [`Split`] being dragged. + split: Split, + /// The [`Axis`] of the [`Split`]. + axis: Axis, + }, } -impl Internal { +impl Action { + /// Returns the current [`Pane`] that is being dragged, if any. pub fn picked_pane(&self) -> Option<(Pane, Point)> { - match self.action { + match *self { Action::Dragging { 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.action { + match *self { Action::Resizing { split, axis, .. } => Some((split, axis)), _ => None, } } +} +impl Internal { + /// Calculates the current [`Pane`] regions from the [`PaneGrid`] layout. pub fn pane_regions( &self, spacing: f32, @@ -261,6 +296,7 @@ impl Internal { self.layout.pane_regions(spacing, size) } + /// Calculates the current [`Split`] regions from the [`PaneGrid`] layout. pub fn split_regions( &self, spacing: f32, @@ -268,28 +304,4 @@ impl Internal { ) -> BTreeMap<Split, (Axis, Rectangle, f32)> { self.layout.split_regions(spacing, size) } - - pub fn pick_pane(&mut self, pane: &Pane, origin: Point) { - self.action = Action::Dragging { - pane: *pane, - origin, - }; - } - - pub fn pick_split(&mut self, split: &Split, axis: Axis) { - // TODO: Obtain `axis` from layout itself. Maybe we should implement - // `Node::find_split` - if self.picked_pane().is_some() { - return; - } - - self.action = Action::Resizing { - split: *split, - axis, - }; - } - - pub fn idle(&mut self) { - self.action = Action::Idle; - } } |