summaryrefslogtreecommitdiffstats
path: root/native/src/widget/pane_grid
diff options
context:
space:
mode:
Diffstat (limited to 'native/src/widget/pane_grid')
-rw-r--r--native/src/widget/pane_grid/node.rs67
-rw-r--r--native/src/widget/pane_grid/state.rs65
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, &region_a, splits);
+ b.compute_splits(halved_spacing, &region_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 };
}