diff options
| author | 2019-11-14 06:46:50 +0100 | |
|---|---|---|
| committer | 2019-11-14 06:46:50 +0100 | |
| commit | bc8d347736ec997ec0e0c401289e2bc09e212b8a (patch) | |
| tree | b98798c09a3aa914b7d0869fba0cfd3efff7754f /native/src/widget | |
| parent | 839e039dbf2fb89dcb8c141503740777d2af2eb3 (diff) | |
| parent | 73f3c900071f950ea914652ca3f0002c1e173f61 (diff) | |
| download | iced-bc8d347736ec997ec0e0c401289e2bc09e212b8a.tar.gz iced-bc8d347736ec997ec0e0c401289e2bc09e212b8a.tar.bz2 iced-bc8d347736ec997ec0e0c401289e2bc09e212b8a.zip  | |
Merge pull request #52 from hecrj/custom-layout-engine
Custom layout engine
Diffstat (limited to 'native/src/widget')
| -rw-r--r-- | native/src/widget/button.rs | 17 | ||||
| -rw-r--r-- | native/src/widget/checkbox.rs | 16 | ||||
| -rw-r--r-- | native/src/widget/column.rs | 58 | ||||
| -rw-r--r-- | native/src/widget/container.rs | 90 | ||||
| -rw-r--r-- | native/src/widget/image.rs | 13 | ||||
| -rw-r--r-- | native/src/widget/radio.rs | 20 | ||||
| -rw-r--r-- | native/src/widget/row.rs | 58 | ||||
| -rw-r--r-- | native/src/widget/scrollable.rs | 38 | ||||
| -rw-r--r-- | native/src/widget/slider.rs | 20 | ||||
| -rw-r--r-- | native/src/widget/text.rs | 16 | ||||
| -rw-r--r-- | native/src/widget/text_input.rs | 33 | 
11 files changed, 248 insertions, 131 deletions
diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs index 31dd6fcc..15beaeba 100644 --- a/native/src/widget/button.rs +++ b/native/src/widget/button.rs @@ -7,7 +7,7 @@  //! [`Class`]: enum.Class.html  use crate::input::{mouse, ButtonState}; -use crate::{Element, Event, Hasher, Layout, Node, Point, Widget}; +use crate::{layout, Element, Event, Hasher, Layout, Point, Widget};  use std::hash::Hash;  pub use iced_core::button::State; @@ -21,8 +21,12 @@ where      Renderer: self::Renderer,      Message: Clone + std::fmt::Debug,  { -    fn node(&self, renderer: &Renderer) -> Node { -        renderer.node(&self) +    fn layout( +        &self, +        renderer: &Renderer, +        limits: &layout::Limits, +    ) -> layout::Node { +        renderer.layout(&self, limits)      }      fn on_event( @@ -74,7 +78,6 @@ where      fn hash_layout(&self, state: &mut Hasher) {          self.width.hash(state); -        self.align_self.hash(state);          self.content.hash_layout(state);      }  } @@ -91,7 +94,11 @@ pub trait Renderer: crate::Renderer + Sized {      ///      /// [`Node`]: ../../struct.Node.html      /// [`Button`]: struct.Button.html -    fn node<Message>(&self, button: &Button<'_, Message, Self>) -> Node; +    fn layout<Message>( +        &self, +        button: &Button<'_, Message, Self>, +        limits: &layout::Limits, +    ) -> layout::Node;      /// Draws a [`Button`].      /// diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index b8053238..a7040e02 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -2,7 +2,7 @@  use std::hash::Hash;  use crate::input::{mouse, ButtonState}; -use crate::{Element, Event, Hasher, Layout, Node, Point, Widget}; +use crate::{layout, Element, Event, Hasher, Layout, Point, Widget};  pub use iced_core::Checkbox; @@ -10,8 +10,12 @@ impl<Message, Renderer> Widget<Message, Renderer> for Checkbox<Message>  where      Renderer: self::Renderer,  { -    fn node(&self, renderer: &Renderer) -> Node { -        renderer.node(&self) +    fn layout( +        &self, +        renderer: &Renderer, +        limits: &layout::Limits, +    ) -> layout::Node { +        renderer.layout(&self, limits)      }      fn on_event( @@ -63,7 +67,11 @@ pub trait Renderer: crate::Renderer {      ///      /// [`Node`]: ../../struct.Node.html      /// [`Checkbox`]: struct.Checkbox.html -    fn node<Message>(&self, checkbox: &Checkbox<Message>) -> Node; +    fn layout<Message>( +        &self, +        checkbox: &Checkbox<Message>, +        limits: &layout::Limits, +    ) -> layout::Node;      /// Draws a [`Checkbox`].      /// diff --git a/native/src/widget/column.rs b/native/src/widget/column.rs index 086d05ef..7e7156a0 100644 --- a/native/src/widget/column.rs +++ b/native/src/widget/column.rs @@ -1,6 +1,6 @@  use std::hash::Hash; -use crate::{Element, Event, Hasher, Layout, Node, Point, Style, Widget}; +use crate::{layout, Element, Event, Hasher, Layout, Length, Point, Widget};  /// A container that distributes its contents vertically.  pub type Column<'a, Message, Renderer> = @@ -11,42 +11,30 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>  where      Renderer: self::Renderer,  { -    fn node(&self, renderer: &Renderer) -> Node { -        let mut children: Vec<Node> = self -            .children -            .iter() -            .map(|child| { -                let mut node = child.widget.node(renderer); - -                let mut style = node.0.style(); -                style.margin.bottom = -                    stretch::style::Dimension::Points(f32::from(self.spacing)); - -                node.0.set_style(style); -                node -            }) -            .collect(); - -        if let Some(node) = children.last_mut() { -            let mut style = node.0.style(); -            style.margin.bottom = stretch::style::Dimension::Undefined; - -            node.0.set_style(style); -        } +    fn width(&self) -> Length { +        self.width +    } -        let mut style = Style::default() -            .width(self.width) -            .height(self.height) +    fn layout( +        &self, +        renderer: &Renderer, +        limits: &layout::Limits, +    ) -> layout::Node { +        let limits = limits              .max_width(self.max_width)              .max_height(self.max_height) -            .padding(self.padding) -            .align_self(self.align_self) -            .align_items(self.align_items) -            .justify_content(self.justify_content); - -        style.0.flex_direction = stretch::style::FlexDirection::Column; - -        Node::with_children(style, children) +            .width(self.width) +            .height(self.height); + +        layout::flex::resolve( +            layout::flex::Axis::Vertical, +            renderer, +            &limits, +            self.padding as f32, +            self.spacing as f32, +            self.align_items, +            &self.children, +        )      }      fn on_event( @@ -85,9 +73,7 @@ where          self.height.hash(state);          self.max_width.hash(state);          self.max_height.hash(state); -        self.align_self.hash(state);          self.align_items.hash(state); -        self.justify_content.hash(state);          self.spacing.hash(state);          for child in &self.children { diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs new file mode 100644 index 00000000..c616db2a --- /dev/null +++ b/native/src/widget/container.rs @@ -0,0 +1,90 @@ +use std::hash::Hash; + +use crate::{layout, Element, Event, Hasher, Layout, Length, Point, Widget}; + +/// A container that distributes its contents vertically. +pub type Container<'a, Message, Renderer> = +    iced_core::Container<Element<'a, Message, Renderer>>; + +impl<'a, Message, Renderer> Widget<Message, Renderer> +    for Container<'a, Message, Renderer> +where +    Renderer: crate::Renderer, +{ +    fn width(&self) -> Length { +        self.width +    } + +    fn layout( +        &self, +        renderer: &Renderer, +        limits: &layout::Limits, +    ) -> layout::Node { +        let limits = limits +            .loose() +            .max_width(self.max_width) +            .max_height(self.max_height) +            .width(self.width) +            .height(self.height); + +        let mut content = self.content.layout(renderer, &limits); +        let size = limits.resolve(content.size()); + +        content.align(self.horizontal_alignment, self.vertical_alignment, size); + +        layout::Node::with_children(size, vec![content]) +    } + +    fn on_event( +        &mut self, +        event: Event, +        layout: Layout<'_>, +        cursor_position: Point, +        messages: &mut Vec<Message>, +        renderer: &Renderer, +    ) { +        self.content.widget.on_event( +            event, +            layout.children().next().unwrap(), +            cursor_position, +            messages, +            renderer, +        ) +    } + +    fn draw( +        &self, +        renderer: &mut Renderer, +        layout: Layout<'_>, +        cursor_position: Point, +    ) -> Renderer::Output { +        self.content.draw( +            renderer, +            layout.children().next().unwrap(), +            cursor_position, +        ) +    } + +    fn hash_layout(&self, state: &mut Hasher) { +        0.hash(state); +        self.width.hash(state); +        self.height.hash(state); +        self.max_width.hash(state); +        self.max_height.hash(state); + +        self.content.hash_layout(state); +    } +} + +impl<'a, Message, Renderer> From<Container<'a, Message, Renderer>> +    for Element<'a, Message, Renderer> +where +    Renderer: 'a + crate::Renderer, +    Message: 'static, +{ +    fn from( +        column: Container<'a, Message, Renderer>, +    ) -> Element<'a, Message, Renderer> { +        Element::new(column) +    } +} diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs index 6255a7b5..b2541b87 100644 --- a/native/src/widget/image.rs +++ b/native/src/widget/image.rs @@ -1,6 +1,6 @@  //! Display images in your user interface. -use crate::{Element, Hasher, Layout, Node, Point, Widget}; +use crate::{layout, Element, Hasher, Layout, Point, Widget};  use std::hash::Hash; @@ -10,8 +10,12 @@ impl<Message, Renderer> Widget<Message, Renderer> for Image  where      Renderer: self::Renderer,  { -    fn node(&self, renderer: &Renderer) -> Node { -        renderer.node(&self) +    fn layout( +        &self, +        renderer: &Renderer, +        limits: &layout::Limits, +    ) -> layout::Node { +        renderer.layout(&self, limits)      }      fn draw( @@ -26,7 +30,6 @@ where      fn hash_layout(&self, state: &mut Hasher) {          self.width.hash(state);          self.height.hash(state); -        self.align_self.hash(state);      }  } @@ -44,7 +47,7 @@ pub trait Renderer: crate::Renderer {      ///      /// [`Node`]: ../../struct.Node.html      /// [`Image`]: struct.Image.html -    fn node(&self, image: &Image) -> Node; +    fn layout(&self, image: &Image, limits: &layout::Limits) -> layout::Node;      /// Draws an [`Image`].      /// diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index 626e6ffc..b68919e5 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -1,6 +1,6 @@  //! Create choices using radio buttons.  use crate::input::{mouse, ButtonState}; -use crate::{Element, Event, Hasher, Layout, Node, Point, Widget}; +use crate::{layout, Element, Event, Hasher, Layout, Length, Point, Widget};  use std::hash::Hash; @@ -11,8 +11,16 @@ where      Renderer: self::Renderer,      Message: Clone + std::fmt::Debug,  { -    fn node(&self, renderer: &Renderer) -> Node { -        renderer.node(&self) +    fn width(&self) -> Length { +        Length::Fill +    } + +    fn layout( +        &self, +        renderer: &Renderer, +        limits: &layout::Limits, +    ) -> layout::Node { +        renderer.layout(&self, limits)      }      fn on_event( @@ -62,7 +70,11 @@ pub trait Renderer: crate::Renderer {      ///      /// [`Node`]: ../../struct.Node.html      /// [`Radio`]: struct.Radio.html -    fn node<Message>(&self, radio: &Radio<Message>) -> Node; +    fn layout<Message>( +        &self, +        radio: &Radio<Message>, +        limits: &layout::Limits, +    ) -> layout::Node;      /// Draws a [`Radio`] button.      /// diff --git a/native/src/widget/row.rs b/native/src/widget/row.rs index 7dbfb92a..132479fd 100644 --- a/native/src/widget/row.rs +++ b/native/src/widget/row.rs @@ -1,6 +1,6 @@  use std::hash::Hash; -use crate::{Element, Event, Hasher, Layout, Node, Point, Style, Widget}; +use crate::{layout, Element, Event, Hasher, Layout, Length, Point, Widget};  /// A container that distributes its contents horizontally.  pub type Row<'a, Message, Renderer> = @@ -11,42 +11,30 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>  where      Renderer: self::Renderer,  { -    fn node(&self, renderer: &Renderer) -> Node { -        let mut children: Vec<Node> = self -            .children -            .iter() -            .map(|child| { -                let mut node = child.widget.node(renderer); - -                let mut style = node.0.style(); -                style.margin.end = -                    stretch::style::Dimension::Points(f32::from(self.spacing)); - -                node.0.set_style(style); -                node -            }) -            .collect(); - -        if let Some(node) = children.last_mut() { -            let mut style = node.0.style(); -            style.margin.end = stretch::style::Dimension::Undefined; - -            node.0.set_style(style); -        } +    fn width(&self) -> Length { +        self.width +    } -        let mut style = Style::default() -            .width(self.width) -            .height(self.height) +    fn layout( +        &self, +        renderer: &Renderer, +        limits: &layout::Limits, +    ) -> layout::Node { +        let limits = limits              .max_width(self.max_width)              .max_height(self.max_height) -            .padding(self.padding) -            .align_self(self.align_self) -            .align_items(self.align_items) -            .justify_content(self.justify_content); - -        style.0.flex_direction = stretch::style::FlexDirection::Row; - -        Node::with_children(style, children) +            .width(self.width) +            .height(self.height); + +        layout::flex::resolve( +            layout::flex::Axis::Horizontal, +            renderer, +            &limits, +            self.padding as f32, +            self.spacing as f32, +            self.align_items, +            &self.children, +        )      }      fn on_event( @@ -85,9 +73,7 @@ where          self.height.hash(state);          self.max_width.hash(state);          self.max_height.hash(state); -        self.align_self.hash(state);          self.align_items.hash(state); -        self.justify_content.hash(state);          self.spacing.hash(state);          self.spacing.hash(state); diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index de4c749c..091dac47 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -1,11 +1,13 @@  use crate::{      column,      input::{mouse, ButtonState}, -    Element, Event, Hasher, Layout, Node, Point, Rectangle, Style, Widget, +    layout, Element, Event, Hasher, Layout, Length, Point, Rectangle, Size, +    Widget,  };  pub use iced_core::scrollable::State; +use std::f32;  use std::hash::Hash;  /// A scrollable [`Column`]. @@ -19,26 +21,25 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>  where      Renderer: self::Renderer + column::Renderer,  { -    fn node(&self, renderer: &Renderer) -> Node { -        let mut content = self.content.node(renderer); - -        { -            let mut style = content.0.style(); -            style.flex_shrink = 0.0; - -            content.0.set_style(style); -        } - -        let mut style = Style::default() -            .width(self.content.width) -            .max_width(self.content.max_width) -            .height(self.height) +    fn layout( +        &self, +        renderer: &Renderer, +        limits: &layout::Limits, +    ) -> layout::Node { +        let limits = limits              .max_height(self.max_height) -            .align_self(self.align_self); +            .width(Length::Fill) +            .height(self.height); + +        let child_limits = layout::Limits::new( +            Size::new(limits.min().width, 0.0), +            Size::new(limits.max().width, f32::INFINITY), +        ); -        style.0.flex_direction = stretch::style::FlexDirection::Column; +        let content = self.content.layout(renderer, &child_limits); +        let size = limits.resolve(content.size()); -        Node::with_children(style, vec![content]) +        layout::Node::with_children(size, vec![content])      }      fn on_event( @@ -167,7 +168,6 @@ where          self.height.hash(state);          self.max_height.hash(state); -        self.align_self.hash(state);          self.content.hash_layout(state)      } diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs index be2b9b22..3a998c40 100644 --- a/native/src/widget/slider.rs +++ b/native/src/widget/slider.rs @@ -7,7 +7,7 @@  use std::hash::Hash;  use crate::input::{mouse, ButtonState}; -use crate::{Element, Event, Hasher, Layout, Node, Point, Widget}; +use crate::{layout, Element, Event, Hasher, Layout, Length, Point, Widget};  pub use iced_core::slider::*; @@ -15,8 +15,16 @@ impl<'a, Message, Renderer> Widget<Message, Renderer> for Slider<'a, Message>  where      Renderer: self::Renderer,  { -    fn node(&self, renderer: &Renderer) -> Node { -        renderer.node(&self) +    fn width(&self) -> Length { +        self.width +    } + +    fn layout( +        &self, +        renderer: &Renderer, +        limits: &layout::Limits, +    ) -> layout::Node { +        renderer.layout(&self, limits)      }      fn on_event( @@ -93,7 +101,11 @@ pub trait Renderer: crate::Renderer {      ///      /// [`Node`]: ../../struct.Node.html      /// [`Radio`]: struct.Radio.html -    fn node<Message>(&self, slider: &Slider<'_, Message>) -> Node; +    fn layout<Message>( +        &self, +        slider: &Slider<'_, Message>, +        limits: &layout::Limits, +    ) -> layout::Node;      /// Draws a [`Slider`].      /// diff --git a/native/src/widget/text.rs b/native/src/widget/text.rs index e389e1d9..10d892a3 100644 --- a/native/src/widget/text.rs +++ b/native/src/widget/text.rs @@ -1,5 +1,5 @@  //! Write some text for your users to read. -use crate::{Element, Hasher, Layout, Node, Point, Widget}; +use crate::{layout, Element, Hasher, Layout, Length, Point, Widget};  use std::hash::Hash; @@ -9,8 +9,16 @@ impl<Message, Renderer> Widget<Message, Renderer> for Text  where      Renderer: self::Renderer,  { -    fn node(&self, renderer: &Renderer) -> Node { -        renderer.node(&self) +    fn width(&self) -> Length { +        self.width +    } + +    fn layout( +        &self, +        renderer: &Renderer, +        limits: &layout::Limits, +    ) -> layout::Node { +        renderer.layout(&self, limits)      }      fn draw( @@ -49,7 +57,7 @@ pub trait Renderer: crate::Renderer {      /// [`Style`]: ../../struct.Style.html      /// [`Text`]: struct.Text.html      /// [`Node::with_measure`]: ../../struct.Node.html#method.with_measure -    fn node(&self, text: &Text) -> Node; +    fn layout(&self, text: &Text, limits: &layout::Limits) -> layout::Node;      /// Draws a [`Text`] fragment.      /// diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index d9837b61..7e81e257 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -1,6 +1,6 @@  use crate::{      input::{keyboard, mouse, ButtonState}, -    Element, Event, Hasher, Layout, Length, Node, Point, Rectangle, Style, +    layout, Element, Event, Hasher, Layout, Length, Point, Rectangle, Size,      Widget,  }; @@ -11,19 +11,24 @@ where      Renderer: self::Renderer,      Message: Clone + std::fmt::Debug,  { -    fn node(&self, renderer: &Renderer) -> Node { -        let text_bounds = -            Node::new(Style::default().width(Length::Fill).height( -                Length::Units(self.size.unwrap_or(renderer.default_size())), -            )); - -        Node::with_children( -            Style::default() -                .width(self.width) -                .max_width(self.width) -                .padding(self.padding), -            vec![text_bounds], -        ) +    fn layout( +        &self, +        renderer: &Renderer, +        limits: &layout::Limits, +    ) -> layout::Node { +        let padding = self.padding as f32; +        let text_size = self.size.unwrap_or(renderer.default_size()); + +        let limits = limits +            .pad(padding) +            .width(self.width) +            .height(Length::Units(text_size)); + +        let mut text = layout::Node::new(limits.resolve(Size::ZERO)); +        text.bounds.x = padding; +        text.bounds.y = padding; + +        layout::Node::with_children(text.size().pad(padding), vec![text])      }      fn on_event(  | 
