diff options
Diffstat (limited to 'native/src/widget/pane_grid')
-rw-r--r-- | native/src/widget/pane_grid/node.rs | 67 | ||||
-rw-r--r-- | native/src/widget/pane_grid/state.rs | 65 |
2 files changed, 127 insertions, 5 deletions
diff --git a/native/src/widget/pane_grid/node.rs b/native/src/widget/pane_grid/node.rs index 08046956..4d5970b8 100644 --- a/native/src/widget/pane_grid/node.rs +++ b/native/src/widget/pane_grid/node.rs @@ -55,6 +55,25 @@ impl Node { f(self); } + pub fn resize(&mut self, split: &Split, percentage: f32) -> bool { + match self { + Node::Split { + id, ratio, a, b, .. + } => { + if id == split { + *ratio = (percentage * 1_000_000.0).round() as u32; + + true + } else if a.resize(split, percentage) { + true + } else { + b.resize(split, percentage) + } + } + Node::Pane(_) => false, + } + } + pub fn remove(&mut self, pane: &Pane) -> Option<Pane> { match self { Node::Split { a, b, .. } => { @@ -93,6 +112,27 @@ impl Node { regions } + pub fn splits( + &self, + spacing: f32, + size: Size, + ) -> HashMap<Split, (Axis, Rectangle, f32)> { + let mut splits = HashMap::new(); + + self.compute_splits( + spacing / 2.0, + &Rectangle { + x: 0.0, + y: 0.0, + width: size.width, + height: size.height, + }, + &mut splits, + ); + + splits + } + pub fn pane(&self) -> Option<Pane> { match self { Node::Split { .. } => None, @@ -129,4 +169,31 @@ impl Node { } } } + + fn compute_splits( + &self, + halved_spacing: f32, + current: &Rectangle, + splits: &mut HashMap<Split, (Axis, Rectangle, f32)>, + ) { + match self { + Node::Split { + axis, + ratio, + a, + b, + id, + } => { + let ratio = *ratio as f32 / 1_000_000.0; + let (region_a, region_b) = + axis.split(current, ratio, halved_spacing); + + let _ = splits.insert(*id, (*axis, *current, ratio)); + + a.compute_splits(halved_spacing, ®ion_a, splits); + b.compute_splits(halved_spacing, ®ion_b, splits); + } + Node::Pane(_) => {} + } + } } diff --git a/native/src/widget/pane_grid/state.rs b/native/src/widget/pane_grid/state.rs index b0e571f0..456ad78a 100644 --- a/native/src/widget/pane_grid/state.rs +++ b/native/src/widget/pane_grid/state.rs @@ -134,6 +134,10 @@ impl<T> State<T> { }); } + pub fn resize(&mut self, split: &Split, percentage: f32) { + let _ = self.internal.layout.resize(split, percentage); + } + pub fn close(&mut self, pane: &Pane) -> Option<T> { if let Some(sibling) = self.internal.layout.remove(pane) { self.focus(&sibling); @@ -153,14 +157,25 @@ pub struct Internal { #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Action { - Idle { focus: Option<Pane> }, - Dragging { pane: Pane }, + Idle { + focus: Option<Pane>, + }, + Dragging { + pane: Pane, + }, + Resizing { + split: Split, + axis: Axis, + focus: Option<Pane>, + }, } impl Action { pub fn focus(&self) -> Option<(Pane, Focus)> { match self { - Action::Idle { focus } => focus.map(|pane| (pane, Focus::Idle)), + Action::Idle { focus } | Action::Resizing { focus, .. } => { + focus.map(|pane| (pane, Focus::Idle)) + } Action::Dragging { pane } => Some((*pane, Focus::Dragging)), } } @@ -171,13 +186,20 @@ impl Internal { self.action } - pub fn dragged(&self) -> Option<Pane> { + pub fn picked_pane(&self) -> Option<Pane> { match self.action { Action::Dragging { pane } => Some(pane), _ => None, } } + pub fn picked_split(&self) -> Option<(Split, Axis)> { + match self.action { + Action::Resizing { split, axis, .. } => Some((split, axis)), + _ => None, + } + } + pub fn regions( &self, spacing: f32, @@ -186,14 +208,47 @@ impl Internal { self.layout.regions(spacing, size) } + pub fn splits( + &self, + spacing: f32, + size: Size, + ) -> HashMap<Split, (Axis, Rectangle, f32)> { + self.layout.splits(spacing, size) + } + pub fn focus(&mut self, pane: &Pane) { self.action = Action::Idle { focus: Some(*pane) }; } - pub fn drag(&mut self, pane: &Pane) { + pub fn pick_pane(&mut self, pane: &Pane) { self.action = Action::Dragging { pane: *pane }; } + 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; + } + + let focus = self.action.focus().map(|(pane, _)| pane); + + self.action = Action::Resizing { + split: *split, + axis, + focus, + }; + } + + pub fn drop_split(&mut self) { + match self.action { + Action::Resizing { focus, .. } => { + self.action = Action::Idle { focus }; + } + _ => {} + } + } + pub fn unfocus(&mut self) { self.action = Action::Idle { focus: None }; } |