diff options
| author | 2020-03-04 04:10:26 +0100 | |
|---|---|---|
| committer | 2020-03-04 04:10:26 +0100 | |
| commit | 012b4adec7a87331b2d75f6bc5d2a0189dcd7ec5 (patch) | |
| tree | ce668596d734fe9fe04e1fa40cb932cd3e1c1789 /native/src | |
| parent | 02091267bf38d4da5efab57e9b63504804b3a468 (diff) | |
| download | iced-012b4adec7a87331b2d75f6bc5d2a0189dcd7ec5.tar.gz iced-012b4adec7a87331b2d75f6bc5d2a0189dcd7ec5.tar.bz2 iced-012b4adec7a87331b2d75f6bc5d2a0189dcd7ec5.zip  | |
Draft `Panes` widget and `panes` example
Diffstat (limited to 'native/src')
| -rw-r--r-- | native/src/element.rs | 2 | ||||
| -rw-r--r-- | native/src/lib.rs | 2 | ||||
| -rw-r--r-- | native/src/widget.rs | 3 | ||||
| -rw-r--r-- | native/src/widget/panes.rs | 238 | 
4 files changed, 243 insertions, 2 deletions
diff --git a/native/src/element.rs b/native/src/element.rs index 276f7614..4e7c7fc6 100644 --- a/native/src/element.rs +++ b/native/src/element.rs @@ -243,7 +243,7 @@ where      }      /// Computes the _layout_ hash of the [`Element`]. -    ///  +    ///      /// [`Element`]: struct.Element.html      pub fn hash_layout(&self, state: &mut Hasher) {          self.widget.hash_layout(state); diff --git a/native/src/lib.rs b/native/src/lib.rs index e4e7baee..4551a982 100644 --- a/native/src/lib.rs +++ b/native/src/lib.rs @@ -34,7 +34,7 @@  //! [`window::Renderer`]: window/trait.Renderer.html  //! [`UserInterface`]: struct.UserInterface.html  //! [renderer]: renderer/index.html -#![deny(missing_docs)] +//#![deny(missing_docs)]  #![deny(missing_debug_implementations)]  #![deny(unused_results)]  #![forbid(unsafe_code)] diff --git a/native/src/widget.rs b/native/src/widget.rs index f9424b02..d97e836c 100644 --- a/native/src/widget.rs +++ b/native/src/widget.rs @@ -25,6 +25,7 @@ pub mod checkbox;  pub mod column;  pub mod container;  pub mod image; +pub mod panes;  pub mod progress_bar;  pub mod radio;  pub mod row; @@ -46,6 +47,8 @@ pub use container::Container;  #[doc(no_inline)]  pub use image::Image;  #[doc(no_inline)] +pub use panes::Panes; +#[doc(no_inline)]  pub use progress_bar::ProgressBar;  #[doc(no_inline)]  pub use radio::Radio; diff --git a/native/src/widget/panes.rs b/native/src/widget/panes.rs new file mode 100644 index 00000000..d69d251e --- /dev/null +++ b/native/src/widget/panes.rs @@ -0,0 +1,238 @@ +use crate::{ +    layout, Clipboard, Element, Event, Hasher, Layout, Length, Point, Size, +    Widget, +}; + +use std::collections::HashMap; + +#[allow(missing_debug_implementations)] +pub struct Panes<'a, Message, Renderer> { +    state: &'a mut Internal, +    elements: Vec<Element<'a, Message, Renderer>>, +    width: Length, +    height: Length, +} + +impl<'a, Message, Renderer> Panes<'a, Message, Renderer> { +    pub fn new<T>( +        state: &'a mut State<T>, +        view: impl Fn(Pane, &'a mut T) -> Element<'a, Message, Renderer>, +    ) -> Self { +        let elements = state +            .panes +            .iter_mut() +            .map(|(pane, state)| view(*pane, state)) +            .collect(); + +        Self { +            state: &mut state.internal, +            elements, +            width: Length::Fill, +            height: Length::Fill, +        } +    } + +    /// Sets the width of the [`Panes`]. +    /// +    /// [`Panes`]: struct.Column.html +    pub fn width(mut self, width: Length) -> Self { +        self.width = width; +        self +    } + +    /// Sets the height of the [`Panes`]. +    /// +    /// [`Panes`]: struct.Column.html +    pub fn height(mut self, height: Length) -> Self { +        self.height = height; +        self +    } +} + +impl<'a, Message, Renderer> Widget<Message, Renderer> +    for Panes<'a, Message, Renderer> +where +    Renderer: self::Renderer + 'static, +    Message: 'static, +{ +    fn width(&self) -> Length { +        self.width +    } + +    fn height(&self) -> Length { +        self.height +    } + +    fn layout( +        &self, +        renderer: &Renderer, +        limits: &layout::Limits, +    ) -> layout::Node { +        let limits = limits.width(self.width).height(self.height); +        let size = limits.resolve(Size::ZERO); + +        let children = self +            .elements +            .iter() +            .map(|element| element.layout(renderer, &limits)) +            .collect(); + +        layout::Node::with_children(size, children) +    } + +    fn draw( +        &self, +        renderer: &mut Renderer, +        defaults: &Renderer::Defaults, +        layout: Layout<'_>, +        cursor_position: Point, +    ) -> Renderer::Output { +        renderer.draw(defaults, &self.elements, layout, cursor_position) +    } + +    fn hash_layout(&self, state: &mut Hasher) { +        use std::hash::Hash; + +        std::any::TypeId::of::<Panes<'_, Message, Renderer>>().hash(state); +        self.width.hash(state); +        self.height.hash(state); +        self.state.layout.hash(state); + +        for element in &self.elements { +            element.hash_layout(state); +        } +    } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct Pane(usize); + +#[derive(Debug)] +pub struct State<T> { +    panes: HashMap<Pane, T>, +    internal: Internal, +} + +#[derive(Debug)] +struct Internal { +    layout: Node, +    last_pane: usize, +    focused_pane: Option<Pane>, +} + +impl<T> State<T> { +    pub fn new(first_pane_state: T) -> (Self, Pane) { +        let first_pane = Pane(0); + +        let mut panes = HashMap::new(); +        let _ = panes.insert(first_pane, first_pane_state); + +        ( +            State { +                panes, +                internal: Internal { +                    layout: Node::Pane(first_pane), +                    last_pane: 0, +                    focused_pane: None, +                }, +            }, +            first_pane, +        ) +    } + +    pub fn get_mut(&mut self, pane: &Pane) -> Option<&mut T> { +        self.panes.get_mut(pane) +    } + +    pub fn iter(&self) -> impl Iterator<Item = (Pane, &T)> { +        self.panes.iter().map(|(pane, state)| (*pane, state)) +    } + +    pub fn iter_mut(&mut self) -> impl Iterator<Item = (Pane, &mut T)> { +        self.panes.iter_mut().map(|(pane, state)| (*pane, state)) +    } + +    pub fn focused_pane(&self) -> Option<Pane> { +        self.internal.focused_pane +    } + +    pub fn focus(&mut self, pane: Pane) { +        self.internal.focused_pane = Some(pane); +    } + +    pub fn split_vertically(&mut self, pane: &Pane, state: T) -> Option<Pane> { +        let new_pane = Pane(self.internal.last_pane.checked_add(1)?); + +        // TODO + +        Some(new_pane) +    } + +    pub fn split_horizontally( +        &mut self, +        pane: &Pane, +        state: T, +    ) -> Option<Pane> { +        let new_pane = Pane(self.internal.last_pane.checked_add(1)?); + +        // TODO + +        Some(new_pane) +    } +} + +#[derive(Debug, Clone, Hash)] +enum Node { +    Split { +        kind: Split, +        ratio: u32, +        a: Box<Node>, +        b: Box<Node>, +    }, +    Pane(Pane), +} + +#[derive(Debug, Clone, Copy, Hash)] +enum Split { +    Horizontal, +    Vertical, +} + +/// The renderer of some [`Panes`]. +/// +/// Your [renderer] will need to implement this trait before being +/// able to use [`Panes`] in your user interface. +/// +/// [`Panes`]: struct.Panes.html +/// [renderer]: ../../renderer/index.html +pub trait Renderer: crate::Renderer + Sized { +    /// Draws some [`Panes`]. +    /// +    /// It receives: +    /// - the children of the [`Column`] +    /// - the [`Layout`] of the [`Column`] and its children +    /// - the cursor position +    /// +    /// [`Column`]: struct.Row.html +    /// [`Layout`]: ../layout/struct.Layout.html +    fn draw<Message>( +        &mut self, +        defaults: &Self::Defaults, +        content: &[Element<'_, Message, Self>], +        layout: Layout<'_>, +        cursor_position: Point, +    ) -> Self::Output; +} + +impl<'a, Message, Renderer> From<Panes<'a, Message, Renderer>> +    for Element<'a, Message, Renderer> +where +    Renderer: self::Renderer + 'static, +    Message: 'static, +{ +    fn from( +        panes: Panes<'a, Message, Renderer>, +    ) -> Element<'a, Message, Renderer> { +        Element::new(panes) +    } +}  | 
