From 5c8ec4504b6541cdc588b91a6b2c7100b4a7cc77 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 14 Mar 2020 05:26:59 +0100 Subject: Create module boundaries for `pane_grid` logic --- native/src/widget/pane_grid/node.rs | 128 ++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 native/src/widget/pane_grid/node.rs (limited to 'native/src/widget/pane_grid/node.rs') diff --git a/native/src/widget/pane_grid/node.rs b/native/src/widget/pane_grid/node.rs new file mode 100644 index 00000000..a9aa7fdc --- /dev/null +++ b/native/src/widget/pane_grid/node.rs @@ -0,0 +1,128 @@ +use crate::{ + pane_grid::{Pane, Split}, + Rectangle, Size, +}; + +use std::collections::HashMap; + +#[derive(Debug, Clone, Hash)] +pub enum Node { + Split { + kind: Split, + ratio: u32, + a: Box, + b: Box, + }, + Pane(Pane), +} + +impl Node { + pub fn find(&mut self, pane: &Pane) -> Option<&mut Node> { + match self { + Node::Split { a, b, .. } => { + a.find(pane).or_else(move || b.find(pane)) + } + Node::Pane(p) => { + if p == pane { + Some(self) + } else { + None + } + } + } + } + + pub fn split(&mut self, kind: Split, new_pane: Pane) { + *self = Node::Split { + kind, + ratio: 500_000, + a: Box::new(self.clone()), + b: Box::new(Node::Pane(new_pane)), + }; + } + + pub fn update(&mut self, f: &impl Fn(&mut Node)) { + match self { + Node::Split { a, b, .. } => { + a.update(f); + b.update(f); + } + _ => {} + } + + f(self); + } + + pub fn remove(&mut self, pane: &Pane) -> Option { + match self { + Node::Split { a, b, .. } => { + if a.pane() == Some(*pane) { + *self = *b.clone(); + Some(self.first_pane()) + } else if b.pane() == Some(*pane) { + *self = *a.clone(); + Some(self.first_pane()) + } else { + a.remove(pane).or_else(|| b.remove(pane)) + } + } + Node::Pane(_) => None, + } + } + + pub fn regions( + &self, + spacing: f32, + size: Size, + ) -> HashMap { + let mut regions = HashMap::new(); + + self.compute_regions( + spacing / 2.0, + &Rectangle { + x: 0.0, + y: 0.0, + width: size.width, + height: size.height, + }, + &mut regions, + ); + + regions + } + + pub fn pane(&self) -> Option { + match self { + Node::Split { .. } => None, + Node::Pane(pane) => Some(*pane), + } + } + + pub fn first_pane(&self) -> Pane { + match self { + Node::Split { a, .. } => a.first_pane(), + Node::Pane(pane) => *pane, + } + } + + fn compute_regions( + &self, + halved_spacing: f32, + current: &Rectangle, + regions: &mut HashMap, + ) { + match self { + Node::Split { kind, ratio, a, b } => { + let ratio = *ratio as f32 / 1_000_000.0; + let (region_a, region_b) = + kind.apply(current, ratio, halved_spacing); + + a.compute_regions(halved_spacing, ®ion_a, regions); + b.compute_regions(halved_spacing, ®ion_b, regions); + } + Node::Pane(pane) => { + let _ = regions.insert(*pane, *current); + } + } + } +} -- cgit From 00c2b55b569ea2ff2fc9de9bbf02475c6ede7e42 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 14 Mar 2020 06:26:09 +0100 Subject: Replace `FocusedPane` with `Action` in `pane_grid` --- native/src/widget/pane_grid/node.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'native/src/widget/pane_grid/node.rs') diff --git a/native/src/widget/pane_grid/node.rs b/native/src/widget/pane_grid/node.rs index a9aa7fdc..744e3e17 100644 --- a/native/src/widget/pane_grid/node.rs +++ b/native/src/widget/pane_grid/node.rs @@ -8,6 +8,7 @@ use std::collections::HashMap; #[derive(Debug, Clone, Hash)] pub enum Node { Split { + id: usize, kind: Split, ratio: u32, a: Box, @@ -32,8 +33,9 @@ impl Node { } } - pub fn split(&mut self, kind: Split, new_pane: Pane) { + pub fn split(&mut self, id: usize, kind: Split, new_pane: Pane) { *self = Node::Split { + id, kind, ratio: 500_000, a: Box::new(self.clone()), @@ -112,7 +114,9 @@ impl Node { regions: &mut HashMap, ) { match self { - Node::Split { kind, ratio, a, b } => { + Node::Split { + kind, ratio, a, b, .. + } => { let ratio = *ratio as f32 / 1_000_000.0; let (region_a, region_b) = kind.apply(current, ratio, halved_spacing); -- cgit From a79603e4ca5e0cee46a737ef0b1af5c69ddb49b6 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 14 Mar 2020 06:32:56 +0100 Subject: Rename `Split` to `Axis` --- native/src/widget/pane_grid/node.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'native/src/widget/pane_grid/node.rs') diff --git a/native/src/widget/pane_grid/node.rs b/native/src/widget/pane_grid/node.rs index 744e3e17..aaf775d8 100644 --- a/native/src/widget/pane_grid/node.rs +++ b/native/src/widget/pane_grid/node.rs @@ -1,5 +1,5 @@ use crate::{ - pane_grid::{Pane, Split}, + pane_grid::{Axis, Pane}, Rectangle, Size, }; @@ -9,7 +9,7 @@ use std::collections::HashMap; pub enum Node { Split { id: usize, - kind: Split, + axis: Axis, ratio: u32, a: Box, b: Box, @@ -33,10 +33,10 @@ impl Node { } } - pub fn split(&mut self, id: usize, kind: Split, new_pane: Pane) { + pub fn split(&mut self, id: usize, axis: Axis, new_pane: Pane) { *self = Node::Split { id, - kind, + axis, ratio: 500_000, a: Box::new(self.clone()), b: Box::new(Node::Pane(new_pane)), @@ -115,11 +115,11 @@ impl Node { ) { match self { Node::Split { - kind, ratio, a, b, .. + axis, ratio, a, b, .. } => { let ratio = *ratio as f32 / 1_000_000.0; let (region_a, region_b) = - kind.apply(current, ratio, halved_spacing); + axis.split(current, ratio, halved_spacing); a.compute_regions(halved_spacing, ®ion_a, regions); b.compute_regions(halved_spacing, ®ion_b, regions); -- cgit From db441a64b18487f3f64bb4f99192548d7fac6893 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 14 Mar 2020 06:35:43 +0100 Subject: Reintroduce `pane_grid::Split` as an identifier --- native/src/widget/pane_grid/node.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'native/src/widget/pane_grid/node.rs') diff --git a/native/src/widget/pane_grid/node.rs b/native/src/widget/pane_grid/node.rs index aaf775d8..08046956 100644 --- a/native/src/widget/pane_grid/node.rs +++ b/native/src/widget/pane_grid/node.rs @@ -1,5 +1,5 @@ use crate::{ - pane_grid::{Axis, Pane}, + pane_grid::{Axis, Pane, Split}, Rectangle, Size, }; @@ -8,7 +8,7 @@ use std::collections::HashMap; #[derive(Debug, Clone, Hash)] pub enum Node { Split { - id: usize, + id: Split, axis: Axis, ratio: u32, a: Box, @@ -33,7 +33,7 @@ impl Node { } } - pub fn split(&mut self, id: usize, axis: Axis, new_pane: Pane) { + pub fn split(&mut self, id: Split, axis: Axis, new_pane: Pane) { *self = Node::Split { id, axis, -- cgit From f08cb4ad565799689d07bacc190fbe0436a63648 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 14 Mar 2020 08:10:50 +0100 Subject: Implement mouse-based pane resizing for `PaneGrid` --- native/src/widget/pane_grid/node.rs | 67 +++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'native/src/widget/pane_grid/node.rs') 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 { match self { Node::Split { a, b, .. } => { @@ -93,6 +112,27 @@ impl Node { regions } + pub fn splits( + &self, + spacing: f32, + size: Size, + ) -> HashMap { + 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 { match self { Node::Split { .. } => None, @@ -129,4 +169,31 @@ impl Node { } } } + + fn compute_splits( + &self, + halved_spacing: f32, + current: &Rectangle, + splits: &mut HashMap, + ) { + 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(_) => {} + } + } } -- cgit