diff options
| author | 2019-09-24 15:39:33 +0200 | |
|---|---|---|
| committer | 2019-09-24 15:39:33 +0200 | |
| commit | 68c4752e998dca1d618380ce4e7d8ac52b710056 (patch) | |
| tree | 35e386030b072c189509bb2ed3adeaec5b0fd4d1 /native/src/widget | |
| parent | bb5cac49d028eb53c259ae58e3a007ebfb736fd4 (diff) | |
| parent | 05c7c39ecb8910c75b82dc4052a7720fb2d42b4a (diff) | |
| download | iced-68c4752e998dca1d618380ce4e7d8ac52b710056.tar.gz iced-68c4752e998dca1d618380ce4e7d8ac52b710056.tar.bz2 iced-68c4752e998dca1d618380ce4e7d8ac52b710056.zip  | |
Merge pull request #17 from hecrj/web
Basic web support (core, native, and web crates)
Diffstat (limited to 'native/src/widget')
| -rw-r--r-- | native/src/widget/button.rs | 111 | ||||
| -rw-r--r-- | native/src/widget/checkbox.rs | 95 | ||||
| -rw-r--r-- | native/src/widget/column.rs | 118 | ||||
| -rw-r--r-- | native/src/widget/image.rs | 66 | ||||
| -rw-r--r-- | native/src/widget/radio.rs | 92 | ||||
| -rw-r--r-- | native/src/widget/row.rs | 117 | ||||
| -rw-r--r-- | native/src/widget/slider.rs | 126 | ||||
| -rw-r--r-- | native/src/widget/text.rs | 79 | 
8 files changed, 804 insertions, 0 deletions
diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs new file mode 100644 index 00000000..7b5c4a86 --- /dev/null +++ b/native/src/widget/button.rs @@ -0,0 +1,111 @@ +//! Allow your users to perform actions by pressing a button. +//! +//! A [`Button`] has some local [`State`] and a [`Class`]. +//! +//! [`Button`]: struct.Button.html +//! [`State`]: struct.State.html +//! [`Class`]: enum.Class.html + +use crate::input::{mouse, ButtonState}; +use crate::{Element, Event, Hasher, Layout, MouseCursor, Node, Point, Widget}; +use std::hash::Hash; + +pub use iced_core::button::*; + +impl<'a, Message, Renderer> Widget<Message, Renderer> for Button<'a, Message> +where +    Renderer: self::Renderer, +    Message: Copy + std::fmt::Debug, +{ +    fn node(&self, renderer: &mut Renderer) -> Node { +        renderer.node(&self) +    } + +    fn on_event( +        &mut self, +        event: Event, +        layout: Layout<'_>, +        cursor_position: Point, +        messages: &mut Vec<Message>, +    ) { +        match event { +            Event::Mouse(mouse::Event::Input { +                button: mouse::Button::Left, +                state, +            }) => { +                if let Some(on_press) = self.on_press { +                    let bounds = layout.bounds(); + +                    match state { +                        ButtonState::Pressed => { +                            self.state.is_pressed = +                                bounds.contains(cursor_position); +                        } +                        ButtonState::Released => { +                            let is_clicked = self.state.is_pressed +                                && bounds.contains(cursor_position); + +                            self.state.is_pressed = false; + +                            if is_clicked { +                                messages.push(on_press); +                            } +                        } +                    } +                } +            } +            _ => {} +        } +    } + +    fn draw( +        &self, +        renderer: &mut Renderer, +        layout: Layout<'_>, +        cursor_position: Point, +    ) -> MouseCursor { +        renderer.draw(&self, layout, cursor_position) +    } + +    fn hash_layout(&self, state: &mut Hasher) { +        self.label.hash(state); +        self.width.hash(state); +        self.align_self.hash(state); +    } +} + +/// The renderer of a [`Button`]. +/// +/// Your [renderer] will need to implement this trait before being +/// able to use a [`Button`] in your user interface. +/// +/// [`Button`]: struct.Button.html +/// [renderer]: ../../renderer/index.html +pub trait Renderer { +    /// Creates a [`Node`] for the provided [`Button`]. +    /// +    /// [`Node`]: ../../struct.Node.html +    /// [`Button`]: struct.Button.html +    fn node<Message>(&self, button: &Button<'_, Message>) -> Node; + +    /// Draws a [`Button`]. +    /// +    /// [`Button`]: struct.Button.html +    fn draw<Message>( +        &mut self, +        button: &Button<'_, Message>, +        layout: Layout<'_>, +        cursor_position: Point, +    ) -> MouseCursor; +} + +impl<'a, Message, Renderer> From<Button<'a, Message>> +    for Element<'a, Message, Renderer> +where +    Renderer: self::Renderer, +    Message: 'static + Copy + std::fmt::Debug, +{ +    fn from(button: Button<'a, Message>) -> Element<'a, Message, Renderer> { +        Element::new(button) +    } +} diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs new file mode 100644 index 00000000..3e307f64 --- /dev/null +++ b/native/src/widget/checkbox.rs @@ -0,0 +1,95 @@ +//! Show toggle controls using checkboxes. +use std::hash::Hash; + +use crate::input::{mouse, ButtonState}; +use crate::{Element, Event, Hasher, Layout, MouseCursor, Node, Point, Widget}; + +pub use iced_core::Checkbox; + +impl<Message, Renderer> Widget<Message, Renderer> for Checkbox<Message> +where +    Renderer: self::Renderer, +{ +    fn node(&self, renderer: &mut Renderer) -> Node { +        renderer.node(&self) +    } + +    fn on_event( +        &mut self, +        event: Event, +        layout: Layout<'_>, +        cursor_position: Point, +        messages: &mut Vec<Message>, +    ) { +        match event { +            Event::Mouse(mouse::Event::Input { +                button: mouse::Button::Left, +                state: ButtonState::Pressed, +            }) => { +                let mouse_over = layout +                    .children() +                    .any(|child| child.bounds().contains(cursor_position)); + +                if mouse_over { +                    messages.push((self.on_toggle)(!self.is_checked)); +                } +            } +            _ => {} +        } +    } + +    fn draw( +        &self, +        renderer: &mut Renderer, +        layout: Layout<'_>, +        cursor_position: Point, +    ) -> MouseCursor { +        renderer.draw(&self, layout, cursor_position) +    } + +    fn hash_layout(&self, state: &mut Hasher) { +        self.label.hash(state); +    } +} + +/// The renderer of a [`Checkbox`]. +/// +/// Your [renderer] will need to implement this trait before being +/// able to use a [`Checkbox`] in your user interface. +/// +/// [`Checkbox`]: struct.Checkbox.html +/// [renderer]: ../../renderer/index.html +pub trait Renderer { +    /// Creates a [`Node`] for the provided [`Checkbox`]. +    /// +    /// [`Node`]: ../../struct.Node.html +    /// [`Checkbox`]: struct.Checkbox.html +    fn node<Message>(&mut self, checkbox: &Checkbox<Message>) -> Node; + +    /// Draws a [`Checkbox`]. +    /// +    /// It receives: +    ///   * the current cursor position +    ///   * the bounds of the [`Checkbox`] +    ///   * the bounds of the label of the [`Checkbox`] +    ///   * whether the [`Checkbox`] is checked or not +    /// +    /// [`Checkbox`]: struct.Checkbox.html +    fn draw<Message>( +        &mut self, +        checkbox: &Checkbox<Message>, +        layout: Layout<'_>, +        cursor_position: Point, +    ) -> MouseCursor; +} + +impl<'a, Message, Renderer> From<Checkbox<Message>> +    for Element<'a, Message, Renderer> +where +    Renderer: self::Renderer, +    Message: 'static, +{ +    fn from(checkbox: Checkbox<Message>) -> Element<'a, Message, Renderer> { +        Element::new(checkbox) +    } +} diff --git a/native/src/widget/column.rs b/native/src/widget/column.rs new file mode 100644 index 00000000..9da2e161 --- /dev/null +++ b/native/src/widget/column.rs @@ -0,0 +1,118 @@ +use std::hash::Hash; + +use crate::{ +    Element, Event, Hasher, Layout, MouseCursor, Node, Point, Style, Widget, +}; + +/// A container that distributes its contents vertically. +pub type Column<'a, Message, Renderer> = +    iced_core::Column<Element<'a, Message, Renderer>>; + +impl<'a, Message, Renderer> Widget<Message, Renderer> +    for Column<'a, Message, Renderer> +{ +    fn node(&self, renderer: &mut 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); +        } + +        let mut style = Style::default() +            .width(self.width) +            .height(self.height) +            .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) +    } + +    fn on_event( +        &mut self, +        event: Event, +        layout: Layout<'_>, +        cursor_position: Point, +        messages: &mut Vec<Message>, +    ) { +        self.children.iter_mut().zip(layout.children()).for_each( +            |(child, layout)| { +                child +                    .widget +                    .on_event(event, layout, cursor_position, messages) +            }, +        ); +    } + +    fn draw( +        &self, +        renderer: &mut Renderer, +        layout: Layout<'_>, +        cursor_position: Point, +    ) -> MouseCursor { +        let mut cursor = MouseCursor::OutOfBounds; + +        self.children.iter().zip(layout.children()).for_each( +            |(child, layout)| { +                let new_cursor = +                    child.widget.draw(renderer, layout, cursor_position); + +                if new_cursor != MouseCursor::OutOfBounds { +                    cursor = new_cursor; +                } +            }, +        ); + +        cursor +    } + +    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.align_self.hash(state); +        self.align_items.hash(state); +        self.justify_content.hash(state); +        self.spacing.hash(state); + +        for child in &self.children { +            child.widget.hash_layout(state); +        } +    } +} + +impl<'a, Message, Renderer> From<Column<'a, Message, Renderer>> +    for Element<'a, Message, Renderer> +where +    Renderer: 'a, +    Message: 'static, +{ +    fn from( +        column: Column<'a, Message, Renderer>, +    ) -> Element<'a, Message, Renderer> { +        Element::new(column) +    } +} diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs new file mode 100644 index 00000000..81f99acb --- /dev/null +++ b/native/src/widget/image.rs @@ -0,0 +1,66 @@ +//! Display images in your user interface. + +use crate::{Element, Hasher, Layout, MouseCursor, Node, Point, Widget}; + +use std::hash::Hash; + +pub use iced_core::Image; + +impl<I, Message, Renderer> Widget<Message, Renderer> for Image<I> +where +    Renderer: self::Renderer<I>, +    I: Clone, +{ +    fn node(&self, renderer: &mut Renderer) -> Node { +        renderer.node(&self) +    } + +    fn draw( +        &self, +        renderer: &mut Renderer, +        layout: Layout<'_>, +        _cursor_position: Point, +    ) -> MouseCursor { +        renderer.draw(&self, layout); + +        MouseCursor::OutOfBounds +    } + +    fn hash_layout(&self, state: &mut Hasher) { +        self.width.hash(state); +        self.height.hash(state); +        self.align_self.hash(state); +    } +} + +/// The renderer of an [`Image`]. +/// +/// Your [renderer] will need to implement this trait before being able to use +/// an [`Image`] in your user interface. +/// +/// [`Image`]: struct.Image.html +/// [renderer]: ../../renderer/index.html +pub trait Renderer<I> { +    /// Creates a [`Node`] for the provided [`Image`]. +    /// +    /// You should probably keep the original aspect ratio, if possible. +    /// +    /// [`Node`]: ../../struct.Node.html +    /// [`Image`]: struct.Image.html +    fn node(&mut self, image: &Image<I>) -> Node; + +    /// Draws an [`Image`]. +    /// +    /// [`Image`]: struct.Image.html +    fn draw(&mut self, image: &Image<I>, layout: Layout<'_>); +} + +impl<'a, I, Message, Renderer> From<Image<I>> for Element<'a, Message, Renderer> +where +    Renderer: self::Renderer<I>, +    I: Clone + 'a, +{ +    fn from(image: Image<I>) -> Element<'a, Message, Renderer> { +        Element::new(image) +    } +} diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs new file mode 100644 index 00000000..33d42e61 --- /dev/null +++ b/native/src/widget/radio.rs @@ -0,0 +1,92 @@ +//! Create choices using radio buttons. +use crate::input::{mouse, ButtonState}; +use crate::{Element, Event, Hasher, Layout, MouseCursor, Node, Point, Widget}; + +use std::hash::Hash; + +pub use iced_core::Radio; + +impl<Message, Renderer> Widget<Message, Renderer> for Radio<Message> +where +    Renderer: self::Renderer, +    Message: Copy + std::fmt::Debug, +{ +    fn node(&self, renderer: &mut Renderer) -> Node { +        renderer.node(&self) +    } + +    fn on_event( +        &mut self, +        event: Event, +        layout: Layout<'_>, +        cursor_position: Point, +        messages: &mut Vec<Message>, +    ) { +        match event { +            Event::Mouse(mouse::Event::Input { +                button: mouse::Button::Left, +                state: ButtonState::Pressed, +            }) => { +                if layout.bounds().contains(cursor_position) { +                    messages.push(self.on_click); +                } +            } +            _ => {} +        } +    } + +    fn draw( +        &self, +        renderer: &mut Renderer, +        layout: Layout<'_>, +        cursor_position: Point, +    ) -> MouseCursor { +        renderer.draw(&self, layout, cursor_position) +    } + +    fn hash_layout(&self, state: &mut Hasher) { +        self.label.hash(state); +    } +} + +/// The renderer of a [`Radio`] button. +/// +/// Your [renderer] will need to implement this trait before being +/// able to use a [`Radio`] button in your user interface. +/// +/// [`Radio`]: struct.Radio.html +/// [renderer]: ../../renderer/index.html +pub trait Renderer { +    /// Creates a [`Node`] for the provided [`Radio`]. +    /// +    /// [`Node`]: ../../struct.Node.html +    /// [`Radio`]: struct.Radio.html +    fn node<Message>(&mut self, radio: &Radio<Message>) -> Node; + +    /// Draws a [`Radio`] button. +    /// +    /// It receives: +    ///   * the current cursor position +    ///   * the bounds of the [`Radio`] +    ///   * the bounds of the label of the [`Radio`] +    ///   * whether the [`Radio`] is selected or not +    /// +    /// [`Radio`]: struct.Radio.html +    fn draw<Message>( +        &mut self, +        radio: &Radio<Message>, +        layout: Layout<'_>, +        cursor_position: Point, +    ) -> MouseCursor; +} + +impl<'a, Message, Renderer> From<Radio<Message>> +    for Element<'a, Message, Renderer> +where +    Renderer: self::Renderer, +    Message: 'static + Copy + std::fmt::Debug, +{ +    fn from(checkbox: Radio<Message>) -> Element<'a, Message, Renderer> { +        Element::new(checkbox) +    } +} diff --git a/native/src/widget/row.rs b/native/src/widget/row.rs new file mode 100644 index 00000000..3cd451b7 --- /dev/null +++ b/native/src/widget/row.rs @@ -0,0 +1,117 @@ +use std::hash::Hash; + +use crate::{ +    Element, Event, Hasher, Layout, MouseCursor, Node, Point, Style, Widget, +}; + +/// A container that distributes its contents horizontally. +pub type Row<'a, Message, Renderer> = +    iced_core::Row<Element<'a, Message, Renderer>>; + +impl<'a, Message, Renderer> Widget<Message, Renderer> +    for Row<'a, Message, Renderer> +{ +    fn node(&self, renderer: &mut 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); +        } + +        let mut style = Style::default() +            .width(self.width) +            .height(self.height) +            .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) +    } + +    fn on_event( +        &mut self, +        event: Event, +        layout: Layout<'_>, +        cursor_position: Point, +        messages: &mut Vec<Message>, +    ) { +        self.children.iter_mut().zip(layout.children()).for_each( +            |(child, layout)| { +                child +                    .widget +                    .on_event(event, layout, cursor_position, messages) +            }, +        ); +    } + +    fn draw( +        &self, +        renderer: &mut Renderer, +        layout: Layout<'_>, +        cursor_position: Point, +    ) -> MouseCursor { +        let mut cursor = MouseCursor::OutOfBounds; + +        self.children.iter().zip(layout.children()).for_each( +            |(child, layout)| { +                let new_cursor = +                    child.widget.draw(renderer, layout, cursor_position); + +                if new_cursor != MouseCursor::OutOfBounds { +                    cursor = new_cursor; +                } +            }, +        ); + +        cursor +    } + +    fn hash_layout(&self, state: &mut Hasher) { +        1.hash(state); +        self.width.hash(state); +        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); + +        for child in &self.children { +            child.widget.hash_layout(state); +        } +    } +} + +impl<'a, Message, Renderer> From<Row<'a, Message, Renderer>> +    for Element<'a, Message, Renderer> +where +    Renderer: 'a, +    Message: 'static, +{ +    fn from(row: Row<'a, Message, Renderer>) -> Element<'a, Message, Renderer> { +        Element::new(row) +    } +} diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs new file mode 100644 index 00000000..481296bd --- /dev/null +++ b/native/src/widget/slider.rs @@ -0,0 +1,126 @@ +//! Display an interactive selector of a single value from a range of values. +//! +//! A [`Slider`] has some local [`State`]. +//! +//! [`Slider`]: struct.Slider.html +//! [`State`]: struct.State.html +use std::hash::Hash; + +use crate::input::{mouse, ButtonState}; +use crate::{Element, Event, Hasher, Layout, MouseCursor, Node, Point, Widget}; + +pub use iced_core::slider::*; + +impl<'a, Message, Renderer> Widget<Message, Renderer> for Slider<'a, Message> +where +    Renderer: self::Renderer, +{ +    fn node(&self, renderer: &mut Renderer) -> Node { +        renderer.node(&self) +    } + +    fn on_event( +        &mut self, +        event: Event, +        layout: Layout<'_>, +        cursor_position: Point, +        messages: &mut Vec<Message>, +    ) { +        let mut change = || { +            let bounds = layout.bounds(); + +            if cursor_position.x <= bounds.x { +                messages.push((self.on_change)(*self.range.start())); +            } else if cursor_position.x >= bounds.x + bounds.width { +                messages.push((self.on_change)(*self.range.end())); +            } else { +                let percent = (cursor_position.x - bounds.x) / bounds.width; +                let value = (self.range.end() - self.range.start()) * percent +                    + self.range.start(); + +                messages.push((self.on_change)(value)); +            } +        }; + +        match event { +            Event::Mouse(mouse::Event::Input { +                button: mouse::Button::Left, +                state, +            }) => match state { +                ButtonState::Pressed => { +                    if layout.bounds().contains(cursor_position) { +                        change(); +                        self.state.is_dragging = true; +                    } +                } +                ButtonState::Released => { +                    self.state.is_dragging = false; +                } +            }, +            Event::Mouse(mouse::Event::CursorMoved { .. }) => { +                if self.state.is_dragging { +                    change(); +                } +            } +            _ => {} +        } +    } + +    fn draw( +        &self, +        renderer: &mut Renderer, +        layout: Layout<'_>, +        cursor_position: Point, +    ) -> MouseCursor { +        renderer.draw(&self, layout, cursor_position) +    } + +    fn hash_layout(&self, state: &mut Hasher) { +        self.width.hash(state); +    } +} + +/// The renderer of a [`Slider`]. +/// +/// Your [renderer] will need to implement this trait before being +/// able to use a [`Slider`] in your user interface. +/// +/// [`Slider`]: struct.Slider.html +/// [renderer]: ../../renderer/index.html +pub trait Renderer { +    /// Creates a [`Node`] for the provided [`Radio`]. +    /// +    /// [`Node`]: ../../struct.Node.html +    /// [`Radio`]: struct.Radio.html +    fn node<Message>(&self, slider: &Slider<'_, Message>) -> Node; + +    /// Draws a [`Slider`]. +    /// +    /// It receives: +    ///   * the current cursor position +    ///   * the bounds of the [`Slider`] +    ///   * the local state of the [`Slider`] +    ///   * the range of values of the [`Slider`] +    ///   * the current value of the [`Slider`] +    /// +    /// [`Slider`]: struct.Slider.html +    /// [`State`]: struct.State.html +    /// [`Class`]: enum.Class.html +    fn draw<Message>( +        &mut self, +        slider: &Slider<'_, Message>, +        layout: Layout<'_>, +        cursor_position: Point, +    ) -> MouseCursor; +} + +impl<'a, Message, Renderer> From<Slider<'a, Message>> +    for Element<'a, Message, Renderer> +where +    Renderer: self::Renderer, +    Message: 'static, +{ +    fn from(slider: Slider<'a, Message>) -> Element<'a, Message, Renderer> { +        Element::new(slider) +    } +} diff --git a/native/src/widget/text.rs b/native/src/widget/text.rs new file mode 100644 index 00000000..5ca6ebf3 --- /dev/null +++ b/native/src/widget/text.rs @@ -0,0 +1,79 @@ +//! Write some text for your users to read. +use crate::{Element, Hasher, Layout, MouseCursor, Node, Point, Widget}; + +use std::hash::Hash; + +pub use iced_core::text::*; + +impl<Message, Renderer> Widget<Message, Renderer> for Text +where +    Renderer: self::Renderer, +{ +    fn node(&self, renderer: &mut Renderer) -> Node { +        renderer.node(&self) +    } + +    fn draw( +        &self, +        renderer: &mut Renderer, +        layout: Layout<'_>, +        _cursor_position: Point, +    ) -> MouseCursor { +        renderer.draw(&self, layout); + +        MouseCursor::OutOfBounds +    } + +    fn hash_layout(&self, state: &mut Hasher) { +        self.content.hash(state); +        self.size.hash(state); +        self.width.hash(state); +        self.height.hash(state); +    } +} + +/// The renderer of a [`Text`] fragment. +/// +/// Your [renderer] will need to implement this trait before being +/// able to use [`Text`] in your [`UserInterface`]. +/// +/// [`Text`]: struct.Text.html +/// [renderer]: ../../renderer/index.html +/// [`UserInterface`]: ../../struct.UserInterface.html +pub trait Renderer { +    /// Creates a [`Node`] with the given [`Style`] for the provided [`Text`] +    /// contents and size. +    /// +    /// You should probably use [`Node::with_measure`] to allow [`Text`] to +    /// adapt to the dimensions of its container. +    /// +    /// [`Node`]: ../../struct.Node.html +    /// [`Style`]: ../../struct.Style.html +    /// [`Text`]: struct.Text.html +    /// [`Node::with_measure`]: ../../struct.Node.html#method.with_measure +    fn node(&self, text: &Text) -> Node; + +    /// Draws a [`Text`] fragment. +    /// +    /// It receives: +    ///   * the bounds of the [`Text`] +    ///   * the contents of the [`Text`] +    ///   * the size of the [`Text`] +    ///   * the color of the [`Text`] +    ///   * the [`HorizontalAlignment`] of the [`Text`] +    ///   * the [`VerticalAlignment`] of the [`Text`] +    /// +    /// [`Text`]: struct.Text.html +    /// [`HorizontalAlignment`]: enum.HorizontalAlignment.html +    /// [`VerticalAlignment`]: enum.VerticalAlignment.html +    fn draw(&mut self, text: &Text, layout: Layout<'_>); +} + +impl<'a, Message, Renderer> From<Text> for Element<'a, Message, Renderer> +where +    Renderer: self::Renderer, +{ +    fn from(text: Text) -> Element<'a, Message, Renderer> { +        Element::new(text) +    } +}  | 
