summaryrefslogtreecommitdiffstats
path: root/native/src/widget
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2019-09-20 19:15:31 +0200
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2019-09-20 19:15:31 +0200
commitb9e0f7494881ad7cdfbcbc16878ecc6ef717753f (patch)
treec8a7419b5cb4c0161306c479b93038f2f86498c2 /native/src/widget
parentb83a4b42dd912b5f59d40e7d4f7f7ccdabc43019 (diff)
downloadiced-b9e0f7494881ad7cdfbcbc16878ecc6ef717753f.tar.gz
iced-b9e0f7494881ad7cdfbcbc16878ecc6ef717753f.tar.bz2
iced-b9e0f7494881ad7cdfbcbc16878ecc6ef717753f.zip
Create `iced_core` and `iced_native`
Diffstat (limited to 'native/src/widget')
-rw-r--r--native/src/widget/button.rs111
-rw-r--r--native/src/widget/checkbox.rs95
-rw-r--r--native/src/widget/column.rs118
-rw-r--r--native/src/widget/image.rs67
-rw-r--r--native/src/widget/radio.rs92
-rw-r--r--native/src/widget/row.rs117
-rw-r--r--native/src/widget/slider.rs126
-rw-r--r--native/src/widget/text.rs77
8 files changed, 803 insertions, 0 deletions
diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs
new file mode 100644
index 00000000..c9436dc4
--- /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, Rectangle, 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.width.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..17f06ebe
--- /dev/null
+++ b/native/src/widget/image.rs
@@ -0,0 +1,67 @@
+//! Display images in your user interface.
+
+use crate::{
+ Element, Hasher, Layout, MouseCursor, Node, Point, Rectangle, 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);
+ }
+}
+
+/// 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..affdfd64
--- /dev/null
+++ b/native/src/widget/text.rs
@@ -0,0 +1,77 @@
+//! 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);
+ }
+}
+
+/// 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)
+ }
+}