diff options
| author | 2022-11-02 16:49:18 -0700 | |
|---|---|---|
| committer | 2022-11-02 17:05:40 -0700 | |
| commit | b761ab5e1d4ceaae6ac12c28f45dfcd84c76c329 (patch) | |
| tree | 78341388255434e41d4071d4940939343f471877 /native/src/widget | |
| parent | 1c00adad615f7c2909d175c696765dbe081bde33 (diff) | |
| download | iced-b761ab5e1d4ceaae6ac12c28f45dfcd84c76c329.tar.gz iced-b761ab5e1d4ceaae6ac12c28f45dfcd84c76c329.tar.bz2 iced-b761ab5e1d4ceaae6ac12c28f45dfcd84c76c329.zip | |
Add maximize / restore to PaneGrid
Diffstat (limited to '')
| -rw-r--r-- | native/src/widget/pane_grid.rs | 129 | ||||
| -rw-r--r-- | native/src/widget/pane_grid/state.rs | 54 | 
2 files changed, 128 insertions, 55 deletions
| diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index 96cf78ef..1b55537f 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -101,7 +101,7 @@ where      Renderer::Theme: StyleSheet + container::StyleSheet,  {      state: &'a state::Internal, -    elements: Vec<(Pane, Content<'a, Message, Renderer>)>, +    elements: Elements<Content<'a, Message, Renderer>>,      width: Length,      height: Length,      spacing: u16, @@ -119,17 +119,30 @@ where      /// Creates a [`PaneGrid`] with the given [`State`] and view function.      ///      /// The view function will be called to display each [`Pane`] present in the -    /// [`State`]. +    /// [`State`]. [`bool`] is set if the pane is maximized.      pub fn new<T>(          state: &'a State<T>, -        view: impl Fn(Pane, &'a T) -> Content<'a, Message, Renderer>, +        view: impl Fn(Pane, &'a T, bool) -> Content<'a, Message, Renderer>,      ) -> Self { -        let elements = { -            state -                .panes -                .iter() -                .map(|(pane, pane_state)| (*pane, view(*pane, pane_state))) -                .collect() +        let elements = if let Some((pane, pane_state)) = +            state.maximized.and_then(|pane| { +                state.panes.get(&pane).map(|pane_state| (pane, pane_state)) +            }) { +            Elements::Maximized( +                pane, +                view(pane, pane_state, true), +                Node::Pane(pane), +            ) +        } else { +            Elements::Normal( +                state +                    .panes +                    .iter() +                    .map(|(pane, pane_state)| { +                        (*pane, view(*pane, pane_state, false)) +                    }) +                    .collect(), +            )          };          Self { @@ -232,11 +245,18 @@ where      }      fn diff(&self, tree: &mut Tree) { -        tree.diff_children_custom( -            &self.elements, -            |state, (_, content)| content.diff(state), -            |(_, content)| content.state(), -        ) +        match &self.elements { +            Elements::Normal(elements) => tree.diff_children_custom( +                elements, +                |state, (_, content)| content.diff(state), +                |(_, content)| content.state(), +            ), +            Elements::Maximized(_, content, _) => tree.diff_children_custom( +                &[content], +                |state, content| content.diff(state), +                |content| content.state(), +            ), +        }      }      fn width(&self) -> Length { @@ -255,11 +275,11 @@ where          layout(              renderer,              limits, -            self.state, +            self.elements.node(self.state),              self.width,              self.height,              self.spacing, -            self.elements.iter().map(|(pane, content)| (*pane, content)), +            self.elements.iter(),              |element, renderer, limits| element.layout(renderer, limits),          )      } @@ -278,13 +298,13 @@ where          let event_status = update(              action, -            self.state, +            self.elements.node(self.state),              &event,              layout,              cursor_position,              shell,              self.spacing, -            self.elements.iter().map(|(pane, content)| (*pane, content)), +            self.elements.iter(),              &self.on_click,              &self.on_drag,              &self.on_resize, @@ -297,7 +317,7 @@ where              .zip(&mut tree.children)              .zip(layout.children())              .map(|(((pane, content), tree), layout)| { -                let is_picked = picked_pane == Some(*pane); +                let is_picked = picked_pane == Some(pane);                  content.on_event(                      tree, @@ -323,7 +343,7 @@ where      ) -> mouse::Interaction {          mouse_interaction(              tree.state.downcast_ref(), -            self.state, +            self.elements.node(self.state),              layout,              cursor_position,              self.spacing, @@ -361,7 +381,7 @@ where      ) {          draw(              tree.state.downcast_ref(), -            self.state, +            self.elements.node(self.state),              layout,              cursor_position,              renderer, @@ -374,7 +394,7 @@ where              self.elements                  .iter()                  .zip(&tree.children) -                .map(|((pane, content), tree)| (*pane, (content, tree))), +                .map(|((pane, content), tree)| (pane, (content, tree))),              |(content, tree),               renderer,               style, @@ -429,7 +449,7 @@ where  pub fn layout<Renderer, T>(      renderer: &Renderer,      limits: &layout::Limits, -    state: &state::Internal, +    node: &Node,      width: Length,      height: Length,      spacing: u16, @@ -439,7 +459,7 @@ pub fn layout<Renderer, T>(      let limits = limits.width(width).height(height);      let size = limits.resolve(Size::ZERO); -    let regions = state.pane_regions(f32::from(spacing), size); +    let regions = node.pane_regions(f32::from(spacing), size);      let children = elements          .filter_map(|(pane, element)| {              let region = regions.get(&pane)?; @@ -464,7 +484,7 @@ pub fn layout<Renderer, T>(  /// accordingly.  pub fn update<'a, Message, T: Draggable>(      action: &mut state::Action, -    state: &state::Internal, +    node: &Node,      event: &Event,      layout: Layout<'_>,      cursor_position: Point, @@ -492,7 +512,7 @@ pub fn update<'a, Message, T: Draggable>(                              cursor_position.y - bounds.y,                          ); -                        let splits = state.split_regions( +                        let splits = node.split_regions(                              f32::from(spacing),                              Size::new(bounds.width, bounds.height),                          ); @@ -570,7 +590,7 @@ pub fn update<'a, Message, T: Draggable>(                  if let Some((split, _)) = action.picked_split() {                      let bounds = layout.bounds(); -                    let splits = state.split_regions( +                    let splits = node.split_regions(                          f32::from(spacing),                          Size::new(bounds.width, bounds.height),                      ); @@ -642,7 +662,7 @@ fn click_pane<'a, Message, T>(  /// Returns the current [`mouse::Interaction`] of a [`PaneGrid`].  pub fn mouse_interaction(      action: &state::Action, -    state: &state::Internal, +    node: &Node,      layout: Layout<'_>,      cursor_position: Point,      spacing: u16, @@ -658,7 +678,7 @@ pub fn mouse_interaction(                  let bounds = layout.bounds();                  let splits = -                    state.split_regions(f32::from(spacing), bounds.size()); +                    node.split_regions(f32::from(spacing), bounds.size());                  let relative_cursor = Point::new(                      cursor_position.x - bounds.x, @@ -687,7 +707,7 @@ pub fn mouse_interaction(  /// Draws a [`PaneGrid`].  pub fn draw<Renderer, T>(      action: &state::Action, -    state: &state::Internal, +    node: &Node,      layout: Layout<'_>,      cursor_position: Point,      renderer: &mut Renderer, @@ -717,7 +737,7 @@ pub fn draw<Renderer, T>(          .and_then(|(split, axis)| {              let bounds = layout.bounds(); -            let splits = state.split_regions(f32::from(spacing), bounds.size()); +            let splits = node.split_regions(f32::from(spacing), bounds.size());              let (_axis, region, ratio) = splits.get(&split)?; @@ -736,7 +756,7 @@ pub fn draw<Renderer, T>(                  );                  let splits = -                    state.split_regions(f32::from(spacing), bounds.size()); +                    node.split_regions(f32::from(spacing), bounds.size());                  let (_split, axis, region) = hovered_split(                      splits.iter(), @@ -897,3 +917,48 @@ fn hovered_split<'a>(          })          .next()  } + +/// TODO +#[derive(Debug)] +pub enum Elements<T> { +    /// TODO +    Normal(Vec<(Pane, T)>), +    /// TODO +    Maximized(Pane, T, Node), +} + +impl<T> Elements<T> { +    /// TODO +    pub fn iter(&self) -> Box<dyn Iterator<Item = (Pane, &T)> + '_> { +        match self { +            Elements::Normal(elements) => Box::new( +                elements.iter().map(|(pane, content)| (*pane, content)), +            ), +            Elements::Maximized(pane, content, _) => { +                Box::new(std::iter::once((*pane, content))) +            } +        } +    } + +    /// TODO +    pub fn iter_mut( +        &mut self, +    ) -> Box<dyn Iterator<Item = (Pane, &mut T)> + '_> { +        match self { +            Elements::Normal(elements) => Box::new( +                elements.iter_mut().map(|(pane, content)| (*pane, content)), +            ), +            Elements::Maximized(pane, content, _) => { +                Box::new(std::iter::once((*pane, content))) +            } +        } +    } + +    /// TODO +    pub fn node<'a>(&'a self, state: &'a state::Internal) -> &'a Node { +        match self { +            Elements::Normal(_) => state.layout(), +            Elements::Maximized(_, _, node) => node, +        } +    } +} diff --git a/native/src/widget/pane_grid/state.rs b/native/src/widget/pane_grid/state.rs index cdca6267..92d26f5a 100644 --- a/native/src/widget/pane_grid/state.rs +++ b/native/src/widget/pane_grid/state.rs @@ -4,9 +4,9 @@  use crate::widget::pane_grid::{      Axis, Configuration, Direction, Node, Pane, Split,  }; -use crate::{Point, Rectangle, Size}; +use crate::{Point, Size}; -use std::collections::{BTreeMap, HashMap}; +use std::collections::HashMap;  /// The state of a [`PaneGrid`].  /// @@ -31,6 +31,9 @@ pub struct State<T> {      ///      /// [`PaneGrid`]: crate::widget::PaneGrid      pub internal: Internal, + +    /// The maximized [`Pane`] of the [`PaneGrid`] +    pub(super) maximized: Option<Pane>,  }  impl<T> State<T> { @@ -52,7 +55,11 @@ impl<T> State<T> {          let internal =              Internal::from_configuration(&mut panes, config.into(), 0); -        State { panes, internal } +        State { +            panes, +            internal, +            maximized: None, +        }      }      /// Returns the total amount of panes in the [`State`]. @@ -194,12 +201,28 @@ impl<T> State<T> {      /// Closes the given [`Pane`] and returns its internal state and its closest      /// sibling, if it exists.      pub fn close(&mut self, pane: &Pane) -> Option<(T, Pane)> { +        if self.maximized == Some(*pane) { +            let _ = self.maximized.take(); +        } +          if let Some(sibling) = self.internal.layout.remove(pane) {              self.panes.remove(pane).map(|state| (state, sibling))          } else {              None          }      } + +    /// Maximize the given [`Pane`]. Only this pane will be rendered by the +    /// [`PaneGrid`] until [`Self::restore()`] is called. +    pub fn maximize(&mut self, pane: &Pane) { +        self.maximized = Some(*pane); +    } + +    /// Restore the currently maximized [`Pane`] to it's normal size. All panes +    /// will be rendered by the [`PaneGrid`] +    pub fn restore(&mut self) { +        let _ = self.maximized.take(); +    }  }  /// The internal state of a [`PaneGrid`]. @@ -226,11 +249,13 @@ impl Internal {                  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);                  ( @@ -304,25 +329,8 @@ impl Action {  }  impl Internal { -    /// Calculates the current [`Pane`] regions from the [`PaneGrid`] layout. -    /// -    /// [`PaneGrid`]: crate::widget::PaneGrid -    pub fn pane_regions( -        &self, -        spacing: f32, -        size: Size, -    ) -> BTreeMap<Pane, Rectangle> { -        self.layout.pane_regions(spacing, size) -    } - -    /// Calculates the current [`Split`] regions from the [`PaneGrid`] layout. -    /// -    /// [`PaneGrid`]: crate::widget::PaneGrid -    pub fn split_regions( -        &self, -        spacing: f32, -        size: Size, -    ) -> BTreeMap<Split, (Axis, Rectangle, f32)> { -        self.layout.split_regions(spacing, size) +    /// The layout [`Node`] of the [`Internal`] state +    pub fn layout(&self) -> &Node { +        &self.layout      }  } | 
