diff options
author | 2022-07-27 06:49:20 +0200 | |
---|---|---|
committer | 2022-07-27 06:49:20 +0200 | |
commit | ff2519b1d43d481987351a83b6dd7237524c21f0 (patch) | |
tree | 5731eeb7eb1247d4a8951de0d5bc5d8102640559 /native/src/widget/pane_grid.rs | |
parent | c44267b85f7aaa2997e3caf1323b837d95818c22 (diff) | |
download | iced-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.rs | 408 |
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 */ |