summaryrefslogtreecommitdiffstats
path: root/native/src/widget/pane_grid.rs
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2022-07-27 06:49:20 +0200
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2022-07-27 06:49:20 +0200
commitff2519b1d43d481987351a83b6dd7237524c21f0 (patch)
tree5731eeb7eb1247d4a8951de0d5bc5d8102640559 /native/src/widget/pane_grid.rs
parentc44267b85f7aaa2997e3caf1323b837d95818c22 (diff)
downloadiced-ff2519b1d43d481987351a83b6dd7237524c21f0.tar.gz
iced-ff2519b1d43d481987351a83b6dd7237524c21f0.tar.bz2
iced-ff2519b1d43d481987351a83b6dd7237524c21f0.zip
Replace stateful widgets with new `iced_pure` API
Diffstat (limited to 'native/src/widget/pane_grid.rs')
-rw-r--r--native/src/widget/pane_grid.rs408
1 files changed, 226 insertions, 182 deletions
diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs
index 70ca772c..d84fb7a0 100644
--- a/native/src/widget/pane_grid.rs
+++ b/native/src/widget/pane_grid.rs
@@ -30,6 +30,8 @@ pub use split::Split;
pub use state::State;
pub use title_bar::TitleBar;
+pub use iced_style::pane_grid::{Line, StyleSheet};
+
use crate::event::{self, Event};
use crate::layout;
use crate::mouse;
@@ -37,13 +39,12 @@ use crate::overlay;
use crate::renderer;
use crate::touch;
use crate::widget::container;
+use crate::widget::tree::{self, Tree};
use crate::{
Clipboard, Color, Element, Layout, Length, Point, Rectangle, Shell, Size,
Vector, Widget,
};
-pub use iced_style::pane_grid::{Line, StyleSheet};
-
/// A collection of panes distributed using either vertical or horizontal splits
/// to completely fill the space available.
///
@@ -66,7 +67,7 @@ pub use iced_style::pane_grid::{Line, StyleSheet};
/// ## Example
///
/// ```
-/// # use iced_native::widget::{pane_grid, Text};
+/// # use iced_native::widget::{pane_grid, text};
/// #
/// # type PaneGrid<'a, Message> =
/// # iced_native::widget::PaneGrid<'a, Message, iced_native::renderer::Null>;
@@ -84,10 +85,10 @@ pub use iced_style::pane_grid::{Line, StyleSheet};
/// let (mut state, _) = pane_grid::State::new(PaneState::SomePane);
///
/// let pane_grid =
-/// PaneGrid::new(&mut state, |pane, state| {
+/// PaneGrid::new(&state, |pane, state| {
/// pane_grid::Content::new(match state {
-/// PaneState::SomePane => Text::new("This is some pane"),
-/// PaneState::AnotherKindOfPane => Text::new("This is another kind of pane"),
+/// PaneState::SomePane => text("This is some pane"),
+/// PaneState::AnotherKindOfPane => text("This is another kind of pane"),
/// })
/// })
/// .on_drag(Message::PaneDragged)
@@ -99,8 +100,7 @@ where
Renderer: crate::Renderer,
Renderer::Theme: StyleSheet + container::StyleSheet,
{
- state: &'a mut state::Internal,
- action: &'a mut state::Action,
+ state: &'a state::Internal,
elements: Vec<(Pane, Content<'a, Message, Renderer>)>,
width: Length,
height: Length,
@@ -121,21 +121,20 @@ where
/// The view function will be called to display each [`Pane`] present in the
/// [`State`].
pub fn new<T>(
- state: &'a mut State<T>,
- view: impl Fn(Pane, &'a mut T) -> Content<'a, Message, Renderer>,
+ state: &'a State<T>,
+ view: impl Fn(Pane, &'a T) -> Content<'a, Message, Renderer>,
) -> Self {
let elements = {
state
.panes
- .iter_mut()
+ .iter()
.map(|(pane, pane_state)| (*pane, view(*pane, pane_state)))
.collect()
};
Self {
- state: &mut state.internal,
- action: &mut state.action,
elements,
+ state: &state.internal,
width: Length::Fill,
height: Length::Fill,
spacing: 0,
@@ -211,6 +210,220 @@ where
}
}
+impl<'a, Message, Renderer> Widget<Message, Renderer>
+ for PaneGrid<'a, Message, Renderer>
+where
+ Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet + container::StyleSheet,
+{
+ fn tag(&self) -> tree::Tag {
+ tree::Tag::of::<state::Action>()
+ }
+
+ fn state(&self) -> tree::State {
+ tree::State::new(state::Action::Idle)
+ }
+
+ fn children(&self) -> Vec<Tree> {
+ self.elements
+ .iter()
+ .map(|(_, content)| content.state())
+ .collect()
+ }
+
+ fn diff(&self, tree: &mut Tree) {
+ tree.diff_children_custom(
+ &self.elements,
+ |state, (_, content)| content.diff(state),
+ |(_, content)| content.state(),
+ )
+ }
+
+ fn width(&self) -> Length {
+ self.width
+ }
+
+ fn height(&self) -> Length {
+ self.height
+ }
+
+ fn layout(
+ &self,
+ renderer: &Renderer,
+ limits: &layout::Limits,
+ ) -> layout::Node {
+ layout(
+ renderer,
+ limits,
+ self.state,
+ self.width,
+ self.height,
+ self.spacing,
+ self.elements.iter().map(|(pane, content)| (*pane, content)),
+ |element, renderer, limits| element.layout(renderer, limits),
+ )
+ }
+
+ fn on_event(
+ &mut self,
+ tree: &mut Tree,
+ event: Event,
+ layout: Layout<'_>,
+ cursor_position: Point,
+ renderer: &Renderer,
+ clipboard: &mut dyn Clipboard,
+ shell: &mut Shell<'_, Message>,
+ ) -> event::Status {
+ let action = tree.state.downcast_mut::<state::Action>();
+
+ let event_status = update(
+ action,
+ self.state,
+ &event,
+ layout,
+ cursor_position,
+ shell,
+ self.spacing,
+ self.elements.iter().map(|(pane, content)| (*pane, content)),
+ &self.on_click,
+ &self.on_drag,
+ &self.on_resize,
+ );
+
+ let picked_pane = action.picked_pane().map(|(pane, _)| pane);
+
+ self.elements
+ .iter_mut()
+ .zip(&mut tree.children)
+ .zip(layout.children())
+ .map(|(((pane, content), tree), layout)| {
+ let is_picked = picked_pane == Some(*pane);
+
+ content.on_event(
+ tree,
+ event.clone(),
+ layout,
+ cursor_position,
+ renderer,
+ clipboard,
+ shell,
+ is_picked,
+ )
+ })
+ .fold(event_status, event::Status::merge)
+ }
+
+ fn mouse_interaction(
+ &self,
+ tree: &Tree,
+ layout: Layout<'_>,
+ cursor_position: Point,
+ viewport: &Rectangle,
+ renderer: &Renderer,
+ ) -> mouse::Interaction {
+ mouse_interaction(
+ tree.state.downcast_ref(),
+ self.state,
+ layout,
+ cursor_position,
+ self.spacing,
+ self.on_resize.as_ref().map(|(leeway, _)| *leeway),
+ )
+ .unwrap_or_else(|| {
+ self.elements
+ .iter()
+ .zip(&tree.children)
+ .zip(layout.children())
+ .map(|(((_pane, content), tree), layout)| {
+ content.mouse_interaction(
+ tree,
+ layout,
+ cursor_position,
+ viewport,
+ renderer,
+ )
+ })
+ .max()
+ .unwrap_or_default()
+ })
+ }
+
+ fn draw(
+ &self,
+ tree: &Tree,
+ renderer: &mut Renderer,
+ theme: &Renderer::Theme,
+ style: &renderer::Style,
+ layout: Layout<'_>,
+ cursor_position: Point,
+ viewport: &Rectangle,
+ ) {
+ draw(
+ tree.state.downcast_ref(),
+ self.state,
+ layout,
+ cursor_position,
+ renderer,
+ theme,
+ style,
+ viewport,
+ self.spacing,
+ self.on_resize.as_ref().map(|(leeway, _)| *leeway),
+ self.style,
+ self.elements
+ .iter()
+ .zip(&tree.children)
+ .map(|((pane, content), tree)| (*pane, (content, tree))),
+ |(content, tree),
+ renderer,
+ style,
+ layout,
+ cursor_position,
+ rectangle| {
+ content.draw(
+ tree,
+ renderer,
+ theme,
+ style,
+ layout,
+ cursor_position,
+ rectangle,
+ );
+ },
+ )
+ }
+
+ fn overlay<'b>(
+ &'b self,
+ tree: &'b mut Tree,
+ layout: Layout<'_>,
+ renderer: &Renderer,
+ ) -> Option<overlay::Element<'_, Message, Renderer>> {
+ self.elements
+ .iter()
+ .zip(&mut tree.children)
+ .zip(layout.children())
+ .filter_map(|(((_, pane), tree), layout)| {
+ pane.overlay(tree, layout, renderer)
+ })
+ .next()
+ }
+}
+
+impl<'a, Message, Renderer> From<PaneGrid<'a, Message, Renderer>>
+ for Element<'a, Message, Renderer>
+where
+ Message: 'a,
+ Renderer: 'a + crate::Renderer,
+ Renderer::Theme: StyleSheet + container::StyleSheet,
+{
+ fn from(
+ pane_grid: PaneGrid<'a, Message, Renderer>,
+ ) -> Element<'a, Message, Renderer> {
+ Element::new(pane_grid)
+ }
+}
+
/// Calculates the [`Layout`] of a [`PaneGrid`].
pub fn layout<Renderer, T>(
renderer: &Renderer,
@@ -656,175 +869,6 @@ pub struct ResizeEvent {
pub ratio: f32,
}
-impl<'a, Message, Renderer> Widget<Message, Renderer>
- for PaneGrid<'a, Message, Renderer>
-where
- Renderer: crate::Renderer,
- Renderer::Theme: StyleSheet + container::StyleSheet,
-{
- fn width(&self) -> Length {
- self.width
- }
-
- fn height(&self) -> Length {
- self.height
- }
-
- fn layout(
- &self,
- renderer: &Renderer,
- limits: &layout::Limits,
- ) -> layout::Node {
- layout(
- renderer,
- limits,
- self.state,
- self.width,
- self.height,
- self.spacing,
- self.elements.iter().map(|(pane, content)| (*pane, content)),
- |element, renderer, limits| element.layout(renderer, limits),
- )
- }
-
- fn on_event(
- &mut self,
- event: Event,
- layout: Layout<'_>,
- cursor_position: Point,
- renderer: &Renderer,
- clipboard: &mut dyn Clipboard,
- shell: &mut Shell<'_, Message>,
- ) -> event::Status {
- let event_status = update(
- self.action,
- self.state,
- &event,
- layout,
- cursor_position,
- shell,
- self.spacing,
- self.elements.iter().map(|(pane, content)| (*pane, content)),
- &self.on_click,
- &self.on_drag,
- &self.on_resize,
- );
-
- let picked_pane = self.action.picked_pane().map(|(pane, _)| pane);
-
- self.elements
- .iter_mut()
- .zip(layout.children())
- .map(|((pane, content), layout)| {
- let is_picked = picked_pane == Some(*pane);
-
- content.on_event(
- event.clone(),
- layout,
- cursor_position,
- renderer,
- clipboard,
- shell,
- is_picked,
- )
- })
- .fold(event_status, event::Status::merge)
- }
-
- fn mouse_interaction(
- &self,
- layout: Layout<'_>,
- cursor_position: Point,
- viewport: &Rectangle,
- renderer: &Renderer,
- ) -> mouse::Interaction {
- mouse_interaction(
- self.action,
- self.state,
- layout,
- cursor_position,
- self.spacing,
- self.on_resize.as_ref().map(|(leeway, _)| *leeway),
- )
- .unwrap_or_else(|| {
- self.elements
- .iter()
- .zip(layout.children())
- .map(|((_pane, content), layout)| {
- content.mouse_interaction(
- layout,
- cursor_position,
- viewport,
- renderer,
- )
- })
- .max()
- .unwrap_or_default()
- })
- }
-
- fn draw(
- &self,
- renderer: &mut Renderer,
- theme: &Renderer::Theme,
- style: &renderer::Style,
- layout: Layout<'_>,
- cursor_position: Point,
- viewport: &Rectangle,
- ) {
- draw(
- self.action,
- self.state,
- layout,
- cursor_position,
- renderer,
- theme,
- style,
- viewport,
- self.spacing,
- self.on_resize.as_ref().map(|(leeway, _)| *leeway),
- self.style,
- self.elements.iter().map(|(pane, content)| (*pane, content)),
- |pane, renderer, style, layout, cursor_position, rectangle| {
- pane.draw(
- renderer,
- theme,
- style,
- layout,
- cursor_position,
- rectangle,
- );
- },
- )
- }
-
- fn overlay(
- &mut self,
- layout: Layout<'_>,
- renderer: &Renderer,
- ) -> Option<overlay::Element<'_, Message, Renderer>> {
- self.elements
- .iter_mut()
- .zip(layout.children())
- .filter_map(|((_, pane), layout)| pane.overlay(layout, renderer))
- .next()
- }
-}
-
-impl<'a, Message, Renderer> From<PaneGrid<'a, Message, Renderer>>
- for Element<'a, Message, Renderer>
-where
- Message: 'a,
- Renderer: 'a + crate::Renderer,
- Renderer::Theme: StyleSheet + container::StyleSheet,
-{
- fn from(
- pane_grid: PaneGrid<'a, Message, Renderer>,
- ) -> Element<'a, Message, Renderer> {
- Element::new(pane_grid)
- }
-}
-
/*
* Helpers
*/