diff options
| author | 2020-03-14 08:10:50 +0100 | |
|---|---|---|
| committer | 2020-03-14 08:10:50 +0100 | |
| commit | f08cb4ad565799689d07bacc190fbe0436a63648 (patch) | |
| tree | 1640c49cae49661d1c205755aa09592821698190 /native/src/widget/pane_grid | |
| parent | db441a64b18487f3f64bb4f99192548d7fac6893 (diff) | |
| download | iced-f08cb4ad565799689d07bacc190fbe0436a63648.tar.gz iced-f08cb4ad565799689d07bacc190fbe0436a63648.tar.bz2 iced-f08cb4ad565799689d07bacc190fbe0436a63648.zip | |
Implement mouse-based pane resizing for `PaneGrid`
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 };      } | 
