diff options
Diffstat (limited to '')
| -rw-r--r-- | native/src/element.rs | 64 | ||||
| -rw-r--r-- | native/src/input/mouse/event.rs | 8 | ||||
| -rw-r--r-- | native/src/layout.rs | 16 | ||||
| -rw-r--r-- | native/src/layout/flex.rs | 24 | ||||
| -rw-r--r-- | native/src/layout/limits.rs | 53 | ||||
| -rw-r--r-- | native/src/layout/node.rs | 23 | ||||
| -rw-r--r-- | native/src/lib.rs | 172 | ||||
| -rw-r--r-- | native/src/renderer.rs | 12 | ||||
| -rw-r--r-- | native/src/renderer/null.rs | 1 | ||||
| -rw-r--r-- | native/src/renderer/windowed.rs | 19 | ||||
| -rw-r--r-- | native/src/size.rs | 14 | ||||
| -rw-r--r-- | native/src/widget.rs | 9 | ||||
| -rw-r--r-- | native/src/widget/checkbox.rs | 9 | ||||
| -rw-r--r-- | native/src/widget/column.rs | 17 | ||||
| -rw-r--r-- | native/src/widget/container.rs | 1 | ||||
| -rw-r--r-- | native/src/widget/image.rs | 3 | ||||
| -rw-r--r-- | native/src/widget/radio.rs | 7 | ||||
| -rw-r--r-- | native/src/widget/row.rs | 17 | ||||
| -rw-r--r-- | native/src/widget/scrollable.rs | 24 | ||||
| -rw-r--r-- | native/src/widget/slider.rs | 25 | ||||
| -rw-r--r-- | native/src/widget/text.rs | 11 | ||||
| -rw-r--r-- | native/src/widget/text_input.rs | 60 | 
22 files changed, 391 insertions, 198 deletions
diff --git a/native/src/element.rs b/native/src/element.rs index 3bf24317..5335fdc1 100644 --- a/native/src/element.rs +++ b/native/src/element.rs @@ -33,31 +33,6 @@ where          }      } -    pub fn width(&self) -> Length { -        self.widget.width() -    } - -    pub fn height(&self) -> Length { -        self.widget.height() -    } - -    pub fn layout( -        &self, -        renderer: &Renderer, -        limits: &layout::Limits, -    ) -> layout::Node { -        self.widget.layout(renderer, limits) -    } - -    pub fn draw( -        &self, -        renderer: &mut Renderer, -        layout: Layout<'_>, -        cursor_position: Point, -    ) -> Renderer::Output { -        self.widget.draw(renderer, layout, cursor_position) -    } -      /// Applies a transformation to the produced message of the [`Element`].      ///      /// This method is useful when you want to decouple different parts of your @@ -225,6 +200,45 @@ where          }      } +    /// Returns the width of the [`Element`]. +    /// +    /// [`Element`]: struct.Element.html +    pub fn width(&self) -> Length { +        self.widget.width() +    } + +    /// Returns the height of the [`Element`]. +    /// +    /// [`Element`]: struct.Element.html +    pub fn height(&self) -> Length { +        self.widget.height() +    } + +    /// Computes the layout of the [`Element`] in the given [`Limits`]. +    /// +    /// [`Element`]: struct.Element.html +    /// [`Limits`]: layout/struct.Limits.html +    pub fn layout( +        &self, +        renderer: &Renderer, +        limits: &layout::Limits, +    ) -> layout::Node { +        self.widget.layout(renderer, limits) +    } + +    /// Draws the [`Element`] and its children using the given [`Layout`]. +    /// +    /// [`Element`]: struct.Element.html +    /// [`Layout`]: layout/struct.Layout.html +    pub fn draw( +        &self, +        renderer: &mut Renderer, +        layout: Layout<'_>, +        cursor_position: Point, +    ) -> Renderer::Output { +        self.widget.draw(renderer, layout, cursor_position) +    } +      pub(crate) fn hash_layout(&self, state: &mut Hasher) {          self.widget.hash_layout(state);      } diff --git a/native/src/input/mouse/event.rs b/native/src/input/mouse/event.rs index 478f9b4d..aafc4fe3 100644 --- a/native/src/input/mouse/event.rs +++ b/native/src/input/mouse/event.rs @@ -34,11 +34,16 @@ pub enum Event {      },      /// The mouse wheel was scrolled. -    WheelScrolled { delta: ScrollDelta }, +    WheelScrolled { +        /// The scroll movement. +        delta: ScrollDelta, +    },  } +/// A scroll movement.  #[derive(Debug, Clone, Copy, PartialEq)]  pub enum ScrollDelta { +    /// A line-based scroll movement      Lines {          /// The number of horizontal lines scrolled          x: f32, @@ -46,6 +51,7 @@ pub enum ScrollDelta {          /// The number of vertical lines scrolled          y: f32,      }, +    /// A pixel-based scroll movement      Pixels {          /// The number of horizontal pixels scrolled          x: f32, diff --git a/native/src/layout.rs b/native/src/layout.rs index 0a744346..e945706b 100644 --- a/native/src/layout.rs +++ b/native/src/layout.rs @@ -1,3 +1,4 @@ +//! Position your widgets properly.  mod limits;  mod node; @@ -8,6 +9,9 @@ pub use node::Node;  use crate::{Point, Rectangle, Vector}; +/// The bounds of a [`Node`] and its children, using absolute coordinates. +/// +/// [`Node`]: struct.Node.html  #[derive(Debug, Clone, Copy)]  pub struct Layout<'a> {      position: Point, @@ -28,6 +32,14 @@ impl<'a> Layout<'a> {          }      } +    /// Gets the bounds of the [`Layout`]. +    /// +    /// The returned [`Rectangle`] describes the position and size of a +    /// [`Node`]. +    /// +    /// [`Layout`]: struct.Layout.html +    /// [`Rectangle`]: struct.Rectangle.html +    /// [`Node`]: struct.Node.html      pub fn bounds(&self) -> Rectangle {          let bounds = self.node.bounds(); @@ -39,6 +51,10 @@ impl<'a> Layout<'a> {          }      } +    /// Returns an iterator over the [`Layout`] of the children of a [`Node`]. +    /// +    /// [`Layout`]: struct.Layout.html +    /// [`Node`]: struct.Node.html      pub fn children(&'a self) -> impl Iterator<Item = Layout<'a>> {          self.node.children().iter().map(move |node| {              Layout::with_offset( diff --git a/native/src/layout/flex.rs b/native/src/layout/flex.rs index 7a2b0d70..bc90553e 100644 --- a/native/src/layout/flex.rs +++ b/native/src/layout/flex.rs @@ -1,3 +1,4 @@ +//! Distribute elements using a flex-based layout.  // This code is heavily inspired by the [`druid`] codebase.  //  // [`druid`]: https://github.com/xi-editor/druid @@ -20,9 +21,13 @@ use crate::{      Align, Element, Size,  }; +/// The main axis of a flex layout.  #[derive(Debug)]  pub enum Axis { +    /// The horizontal axis      Horizontal, + +    /// The vertical axis      Vertical,  } @@ -49,7 +54,12 @@ impl Axis {      }  } -// TODO: Remove `Message` type parameter +/// Computes the flex layout with the given axis and limits, applying spacing, +/// padding and alignment to the items as needed. +/// +/// It returns a new layout [`Node`]. +/// +/// [`Node`]: ../struct.Node.html  pub fn resolve<Message, Renderer>(      axis: Axis,      renderer: &Renderer, @@ -57,7 +67,7 @@ pub fn resolve<Message, Renderer>(      padding: f32,      spacing: f32,      align_items: Align, -    children: &[Element<'_, Message, Renderer>], +    items: &[Element<'_, Message, Renderer>],  ) -> Node  where      Renderer: crate::Renderer, @@ -65,14 +75,14 @@ where      let limits = limits.pad(padding);      let mut total_non_fill = -        spacing as f32 * (children.len() as i32 - 1).max(0) as f32; +        spacing as f32 * (items.len() as i32 - 1).max(0) as f32;      let mut fill_sum = 0;      let mut cross = axis.cross(limits.min()); -    let mut nodes: Vec<Node> = Vec::with_capacity(children.len()); -    nodes.resize(children.len(), Node::default()); +    let mut nodes: Vec<Node> = Vec::with_capacity(items.len()); +    nodes.resize(items.len(), Node::default()); -    for (i, child) in children.iter().enumerate() { +    for (i, child) in items.iter().enumerate() {          let fill_factor = match axis {              Axis::Horizontal => child.width(),              Axis::Vertical => child.height(), @@ -97,7 +107,7 @@ where      let available = axis.main(limits.max());      let remaining = (available - total_non_fill).max(0.0); -    for (i, child) in children.iter().enumerate() { +    for (i, child) in items.iter().enumerate() {          let fill_factor = match axis {              Axis::Horizontal => child.width(),              Axis::Vertical => child.height(), diff --git a/native/src/layout/limits.rs b/native/src/layout/limits.rs index af269acd..2705a47d 100644 --- a/native/src/layout/limits.rs +++ b/native/src/layout/limits.rs @@ -1,5 +1,6 @@  use crate::{Length, Size}; +/// A set of size constraints for layouting.  #[derive(Debug, Clone, Copy)]  pub struct Limits {      min: Size, @@ -8,12 +9,17 @@ pub struct Limits {  }  impl Limits { +    /// No limits      pub const NONE: Limits = Limits {          min: Size::ZERO,          max: Size::INFINITY,          fill: Size::INFINITY,      }; +    /// Creates new [`Limits`] with the given minimum and maximum [`Size`]. +    /// +    /// [`Limits`]: struct.Limits.html +    /// [`Size`]: ../struct.Size.html      pub fn new(min: Size, max: Size) -> Limits {          Limits {              min, @@ -22,14 +28,25 @@ impl Limits {          }      } +    /// Returns the minimum [`Size`] of the [`Limits`]. +    /// +    /// [`Limits`]: struct.Limits.html +    /// [`Size`]: ../struct.Size.html      pub fn min(&self) -> Size {          self.min      } +    /// Returns the maximum [`Size`] of the [`Limits`]. +    /// +    /// [`Limits`]: struct.Limits.html +    /// [`Size`]: ../struct.Size.html      pub fn max(&self) -> Size {          self.max      } +    /// Applies a width constraint to the current [`Limits`]. +    /// +    /// [`Limits`]: struct.Limits.html      pub fn width(mut self, width: Length) -> Limits {          match width {              Length::Shrink => { @@ -51,6 +68,9 @@ impl Limits {          self      } +    /// Applies a height constraint to the current [`Limits`]. +    /// +    /// [`Limits`]: struct.Limits.html      pub fn height(mut self, height: Length) -> Limits {          match height {              Length::Shrink => { @@ -72,6 +92,9 @@ impl Limits {          self      } +    /// Applies a minimum width constraint to the current [`Limits`]. +    /// +    /// [`Limits`]: struct.Limits.html      pub fn min_width(mut self, min_width: u32) -> Limits {          self.min.width =              self.min.width.max(min_width as f32).min(self.max.width); @@ -79,6 +102,9 @@ impl Limits {          self      } +    /// Applies a maximum width constraint to the current [`Limits`]. +    /// +    /// [`Limits`]: struct.Limits.html      pub fn max_width(mut self, max_width: u32) -> Limits {          self.max.width =              self.max.width.min(max_width as f32).max(self.min.width); @@ -86,6 +112,19 @@ impl Limits {          self      } +    /// Applies a minimum height constraint to the current [`Limits`]. +    /// +    /// [`Limits`]: struct.Limits.html +    pub fn min_height(mut self, min_height: u32) -> Limits { +        self.min.height = +            self.min.height.max(min_height as f32).min(self.max.height); + +        self +    } + +    /// Applies a maximum height constraint to the current [`Limits`]. +    /// +    /// [`Limits`]: struct.Limits.html      pub fn max_height(mut self, max_height: u32) -> Limits {          self.max.height =              self.max.height.min(max_height as f32).max(self.min.height); @@ -93,10 +132,17 @@ impl Limits {          self      } +    /// Shrinks the current [`Limits`] to account for the given padding. +    /// +    /// [`Limits`]: struct.Limits.html      pub fn pad(&self, padding: f32) -> Limits {          self.shrink(Size::new(padding * 2.0, padding * 2.0))      } +    /// Shrinks the current [`Limits`] by the given [`Size`]. +    /// +    /// [`Limits`]: struct.Limits.html +    /// [`Size`]: ../struct.Size.html      pub fn shrink(&self, size: Size) -> Limits {          let min = Size::new(              (self.min().width - size.width).max(0.0), @@ -116,6 +162,9 @@ impl Limits {          Limits { min, max, fill }      } +    /// Removes the minimum width constraint for the current [`Limits`]. +    /// +    /// [`Limits`]: struct.Limits.html      pub fn loose(&self) -> Limits {          Limits {              min: Size::ZERO, @@ -124,6 +173,10 @@ impl Limits {          }      } +    /// Computes the resulting [`Size`] that fits the [`Limits`] given the +    /// intrinsic size of some content. +    /// +    /// [`Limits`]: struct.Limits.html      pub fn resolve(&self, intrinsic_size: Size) -> Size {          Size::new(              intrinsic_size diff --git a/native/src/layout/node.rs b/native/src/layout/node.rs index 64ebf2d0..ed1cd3da 100644 --- a/native/src/layout/node.rs +++ b/native/src/layout/node.rs @@ -1,16 +1,25 @@  use crate::{Align, Rectangle, Size}; +/// The bounds of an element and its children.  #[derive(Debug, Clone, Default)]  pub struct Node { -    pub bounds: Rectangle, +    pub(crate) bounds: Rectangle,      children: Vec<Node>,  }  impl Node { +    /// Creates a new [`Node`] with the given [`Size`]. +    /// +    /// [`Node`]: struct.Node.html +    /// [`Size`]: ../struct.Size.html      pub fn new(size: Size) -> Self {          Self::with_children(size, Vec::new())      } +    /// Creates a new [`Node`] with the given [`Size`] and children. +    /// +    /// [`Node`]: struct.Node.html +    /// [`Size`]: ../struct.Size.html      pub fn with_children(size: Size, children: Vec<Node>) -> Self {          Node {              bounds: Rectangle { @@ -23,19 +32,29 @@ impl Node {          }      } +    /// Returns the [`Size`] of the [`Node`]. +    /// +    /// [`Node`]: struct.Node.html +    /// [`Size`]: ../struct.Size.html      pub fn size(&self) -> Size {          Size::new(self.bounds.width, self.bounds.height)      } +    /// Returns the bounds of the [`Node`]. +    /// +    /// [`Node`]: struct.Node.html      pub fn bounds(&self) -> Rectangle {          self.bounds      } +    /// Returns the children of the [`Node`]. +    /// +    /// [`Node`]: struct.Node.html      pub fn children(&self) -> &[Node] {          &self.children      } -    pub fn align( +    pub(crate) fn align(          &mut self,          horizontal_alignment: Align,          vertical_alignment: Align, diff --git a/native/src/lib.rs b/native/src/lib.rs index 55331ba5..57d014b6 100644 --- a/native/src/lib.rs +++ b/native/src/lib.rs @@ -1,162 +1,34 @@ -//! Iced is a renderer-agnostic GUI library focused on simplicity and -//! type-safety. Inspired by [Elm]. +//! A renderer-agnostic native GUI runtime.  //! -//! # Features -//!   * Simple, easy-to-use, renderer-agnostic API -//!   * Responsive, flexbox-based layouting -//!   * Type-safe, reactive programming model -//!   * Built-in widgets -//!   * Custom widget support +//!   //! -//! Check out the [repository] and the [examples] for more details! +//! `iced_native` takes [`iced_core`] and builds a native runtime on top of it, +//! featuring:  //! -//! [examples]: https://github.com/hecrj/iced/tree/0.1.0/examples -//! [repository]: https://github.com/hecrj/iced +//! - A custom layout engine, greatly inspired by [`druid`] +//! - Event handling for all the built-in widgets +//! - A renderer-agnostic API  //! -//! # Usage -//! Inspired by [The Elm Architecture], Iced expects you to split user -//! interfaces into four different concepts: -//! -//!   * __State__ — the state of your application -//!   * __Messages__ — user interactions or meaningful events that you care -//!   about -//!   * __View logic__ — a way to display your __state__ as widgets that -//!   may produce __messages__ on user interaction -//!   * __Update logic__ — a way to react to __messages__ and update your -//!   __state__ -//! -//! We can build something to see how this works! Let's say we want a simple -//! counter that can be incremented and decremented using two buttons. -//! -//! We start by modelling the __state__ of our application: -//! -//! ``` -//! use iced_native::button; -//! -//! struct Counter { -//!     // The counter value -//!     value: i32, -//! -//!     // The local state of the two buttons -//!     increment_button: button::State, -//!     decrement_button: button::State, -//! } -//! ``` -//! -//! Next, we need to define the possible user interactions of our counter: -//! the button presses. These interactions are our __messages__: -//! -//! ``` -//! #[derive(Debug, Clone, Copy)] -//! pub enum Message { -//!     IncrementPressed, -//!     DecrementPressed, -//! } -//! ``` +//! To achieve this, it introduces a bunch of reusable interfaces:  //! -//! Now, let's show the actual counter by putting it all together in our -//! __view logic__: -//! -//! ``` -//! # use iced_native::button; -//! # -//! # struct Counter { -//! #     // The counter value -//! #     value: i32, -//! # -//! #     // The local state of the two buttons -//! #     increment_button: button::State, -//! #     decrement_button: button::State, -//! # } -//! # -//! # #[derive(Debug, Clone, Copy)] -//! # pub enum Message { -//! #     IncrementPressed, -//! #     DecrementPressed, -//! # } -//! # -//! # mod iced_wgpu { -//! #     pub use iced_native::renderer::Null as Renderer; -//! # } -//! use iced_native::{Button, Column, Text}; -//! use iced_wgpu::Renderer; // Iced does not include a renderer! We need to bring our own! -//! -//! impl Counter { -//!     pub fn view(&mut self) -> Column<Message, Renderer> { -//!         // We use a column: a simple vertical layout -//!         Column::new() -//!             .push( -//!                 // The increment button. We tell it to produce an -//!                 // `IncrementPressed` message when pressed -//!                 Button::new(&mut self.increment_button, Text::new("+")) -//!                     .on_press(Message::IncrementPressed), -//!             ) -//!             .push( -//!                 // We show the value of the counter here -//!                 Text::new(&self.value.to_string()).size(50), -//!             ) -//!             .push( -//!                 // The decrement button. We tell it to produce a -//!                 // `DecrementPressed` message when pressed -//!                 Button::new(&mut self.decrement_button, Text::new("-")) -//!                     .on_press(Message::DecrementPressed), -//!             ) -//!     } -//! } -//! ``` -//! -//! Finally, we need to be able to react to any produced __messages__ and change -//! our __state__ accordingly in our __update logic__: -//! -//! ``` -//! # use iced_native::button; -//! # -//! # struct Counter { -//! #     // The counter value -//! #     value: i32, -//! # -//! #     // The local state of the two buttons -//! #     increment_button: button::State, -//! #     decrement_button: button::State, -//! # } -//! # -//! # #[derive(Debug, Clone, Copy)] -//! # pub enum Message { -//! #     IncrementPressed, -//! #     DecrementPressed, -//! # } -//! impl Counter { -//!     // ... -//! -//!     pub fn update(&mut self, message: Message) { -//!         match message { -//!             Message::IncrementPressed => { -//!                 self.value += 1; -//!             } -//!             Message::DecrementPressed => { -//!                 self.value -= 1; -//!             } -//!         } -//!     } -//! } -//! ``` -//! -//! And that's everything! We just wrote a whole user interface. Iced is now -//! able to: -//! -//!   1. Take the result of our __view logic__ and layout its widgets. -//!   1. Process events from our system and produce __messages__ for our -//!      __update logic__. -//!   1. Draw the resulting user interface using our chosen __renderer__. +//! - A [`Widget`] trait, which is used to implement new widgets: from layout +//!   requirements to event and drawing logic. +//! - A bunch of `Renderer` traits, meant to keep the crate renderer-agnostic. +//! - A [`Windowed`] trait, leveraging [`raw-window-handle`], which can be +//!   implemented by graphical renderers that target _windows_. Window-based +//!   shells (like [`iced_winit`]) can use this trait to stay renderer-agnostic.  //! +//! # Usage  //! Check out the [`UserInterface`] type to learn how to wire everything up!  //! -//! [Elm]: https://elm-lang.org/ -//! [The Elm Architecture]: https://guide.elm-lang.org/architecture/ -//! [documentation]: https://docs.rs/iced -//! [examples]: https://github.com/hecrj/iced/tree/master/examples +//! [`iced_core`]: https://github.com/hecrj/iced/tree/master/core +//! [`iced_winit`]: https://github.com/hecrj/iced/tree/master/winit +//! [`druid`]: https://github.com/xi-editor/druid +//! [`raw-window-handle`]: https://github.com/rust-windowing/raw-window-handle +//! [`Widget`]: widget/trait.Widget.html +//! [`Windowed`]: renderer/trait.Windowed.html  //! [`UserInterface`]: struct.UserInterface.html -//#![deny(missing_docs)] +#![deny(missing_docs)]  //#![deny(missing_debug_implementations)]  #![deny(unused_results)]  #![deny(unsafe_code)] diff --git a/native/src/renderer.rs b/native/src/renderer.rs index 3e19be33..7a68ada4 100644 --- a/native/src/renderer.rs +++ b/native/src/renderer.rs @@ -32,9 +32,21 @@ pub use windowed::{Target, Windowed};  use crate::{layout, Element}; +/// A component that can take the state of a user interface and produce an +/// output for its users.  pub trait Renderer: Sized { +    /// The type of output of the [`Renderer`]. +    /// +    /// If you are implementing a graphical renderer, your output will most +    /// likely be a tree of visual primitives. +    /// +    /// [`Renderer`]: trait.Renderer.html      type Output; +    /// Lays out the elements of a user interface. +    /// +    /// You should override this if you need to perform any operations before or +    /// after layouting. For instance, trimming the measurements cache.      fn layout<'a, Message>(          &mut self,          element: &Element<'a, Message, Self>, diff --git a/native/src/renderer/null.rs b/native/src/renderer/null.rs index 8933b09b..3334e6b6 100644 --- a/native/src/renderer/null.rs +++ b/native/src/renderer/null.rs @@ -4,6 +4,7 @@ use crate::{      Rectangle, Renderer, Size, VerticalAlignment,  }; +/// A renderer that does nothing.  pub struct Null;  impl Renderer for Null { diff --git a/native/src/renderer/windowed.rs b/native/src/renderer/windowed.rs index 6d0419d2..813a03f2 100644 --- a/native/src/renderer/windowed.rs +++ b/native/src/renderer/windowed.rs @@ -2,11 +2,21 @@ use crate::MouseCursor;  use raw_window_handle::HasRawWindowHandle; +/// A renderer that can target windows.  pub trait Windowed: super::Renderer + Sized { +    /// The type of target.      type Target: Target<Renderer = Self>; +    /// Creates a new [`Windowed`] renderer. +    /// +    /// [`Windowed`]: trait.Windowed.html      fn new() -> Self; +    /// Performs the drawing operations described in the output on the given +    /// target. +    /// +    /// The overlay can be a bunch of debug text logs. It should be rendered on +    /// top of the GUI on most scenarios.      fn draw<T: AsRef<str>>(          &mut self,          output: &Self::Output, @@ -15,9 +25,15 @@ pub trait Windowed: super::Renderer + Sized {      ) -> MouseCursor;  } +/// A rendering target.  pub trait Target { +    /// The renderer of this target.      type Renderer; +    /// Creates a new rendering [`Target`] from the given window handle, width, +    /// height and dpi factor. +    /// +    /// [`Target`]: trait.Target.html      fn new<W: HasRawWindowHandle>(          window: &W,          width: u16, @@ -26,6 +42,9 @@ pub trait Target {          renderer: &Self::Renderer,      ) -> Self; +    /// Resizes the current [`Target`]. +    /// +    /// [`Target`]: trait.Target.html      fn resize(          &mut self,          width: u16, diff --git a/native/src/size.rs b/native/src/size.rs index bd909292..30e2a57e 100644 --- a/native/src/size.rs +++ b/native/src/size.rs @@ -1,5 +1,6 @@  use std::f32; +/// An amount of space in 2 dimensions.  #[derive(Debug, Clone, Copy, PartialEq)]  pub struct Size {      /// The width. @@ -9,13 +10,26 @@ pub struct Size {  }  impl Size { +    /// A [`Size`] with zero width and height. +    /// +    /// [`Size`]: struct.Size.html      pub const ZERO: Size = Size::new(0., 0.); + +    /// A [`Size`] with infinite width and height. +    /// +    /// [`Size`]: struct.Size.html      pub const INFINITY: Size = Size::new(f32::INFINITY, f32::INFINITY); +    /// A [`Size`] of infinite width and height. +    /// +    /// [`Size`]: struct.Size.html      pub const fn new(width: f32, height: f32) -> Self {          Size { width, height }      } +    /// Increments the [`Size`] to account for the given padding. +    /// +    /// [`Size`]: struct.Size.html      pub fn pad(&self, padding: f32) -> Self {          Size {              width: self.width + padding * 2.0, diff --git a/native/src/widget.rs b/native/src/widget.rs index 61b66c5b..48605ee3 100644 --- a/native/src/widget.rs +++ b/native/src/widget.rs @@ -23,6 +23,7 @@  pub mod button;  pub mod checkbox;  pub mod column; +pub mod container;  pub mod image;  pub mod radio;  pub mod row; @@ -31,8 +32,6 @@ pub mod slider;  pub mod text;  pub mod text_input; -mod container; -  #[doc(no_inline)]  pub use button::Button;  #[doc(no_inline)] @@ -69,8 +68,14 @@ pub trait Widget<Message, Renderer>  where      Renderer: crate::Renderer,  { +    /// Returns the width of the [`Widget`]. +    /// +    /// [`Widget`]: trait.Widget.html      fn width(&self) -> Length; +    /// Returns the height of the [`Widget`]. +    /// +    /// [`Widget`]: trait.Widget.html      fn height(&self) -> Length;      /// Returns the [`Node`] of the [`Widget`]. diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index f7bda146..8101e6be 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -166,15 +166,18 @@ where  /// [`Checkbox`]: struct.Checkbox.html  /// [renderer]: ../../renderer/index.html  pub trait Renderer: crate::Renderer { +    /// Returns the default size of a [`Checkbox`]. +    /// +    /// [`Checkbox`]: struct.Checkbox.html      fn default_size(&self) -> u32;      /// 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 +    ///   * whether the [`Checkbox`] is selected or not +    ///   * whether the mouse is over the [`Checkbox`] or not +    ///   * the drawn label of the [`Checkbox`]      ///      /// [`Checkbox`]: struct.Checkbox.html      fn draw( diff --git a/native/src/widget/column.rs b/native/src/widget/column.rs index 87c51f48..281437fd 100644 --- a/native/src/widget/column.rs +++ b/native/src/widget/column.rs @@ -1,3 +1,4 @@ +//! Distribute content vertically.  use std::hash::Hash;  use crate::{ @@ -189,7 +190,23 @@ where      }  } +/// The renderer of a [`Column`]. +/// +/// Your [renderer] will need to implement this trait before being +/// able to use a [`Column`] in your user interface. +/// +/// [`Column`]: struct.Column.html +/// [renderer]: ../../renderer/index.html  pub trait Renderer: crate::Renderer + Sized { +    /// Draws a [`Column`]. +    /// +    /// 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,          content: &[Element<'_, Message, Self>], diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index 2f15573d..64a5f4da 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -1,3 +1,4 @@ +//! Decorate content and apply alignment.  use std::hash::Hash;  use crate::{ diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs index 696de683..c64f07b1 100644 --- a/native/src/widget/image.rs +++ b/native/src/widget/image.rs @@ -116,6 +116,9 @@ where  /// [`Image`]: struct.Image.html  /// [renderer]: ../../renderer/index.html  pub trait Renderer: crate::Renderer { +    /// Returns the dimensions of an [`Image`] located on the given path. +    /// +    /// [`Image`]: struct.Image.html      fn dimensions(&self, path: &str) -> (u32, u32);      /// Draws an [`Image`]. diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index 3dc764fe..4e48728f 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -174,15 +174,18 @@ where  /// [`Radio`]: struct.Radio.html  /// [renderer]: ../../renderer/index.html  pub trait Renderer: crate::Renderer { +    /// Returns the default size of a [`Radio`] button. +    /// +    /// [`Radio`]: struct.Radio.html      fn default_size(&self) -> u32;      /// 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 +    ///   * whether the mouse is over the [`Radio`] or not +    ///   * the drawn label of the [`Radio`]      ///      /// [`Radio`]: struct.Radio.html      fn draw( diff --git a/native/src/widget/row.rs b/native/src/widget/row.rs index 33222b8a..34c7ca7c 100644 --- a/native/src/widget/row.rs +++ b/native/src/widget/row.rs @@ -1,3 +1,4 @@ +//! Distribute content horizontally.  use std::hash::Hash;  use crate::{ @@ -192,7 +193,23 @@ where      }  } +/// The renderer of a [`Row`]. +/// +/// Your [renderer] will need to implement this trait before being +/// able to use a [`Row`] in your user interface. +/// +/// [`Row`]: struct.Row.html +/// [renderer]: ../../renderer/index.html  pub trait Renderer: crate::Renderer + Sized { +    /// Draws a [`Row`]. +    /// +    /// It receives: +    /// - the children of the [`Row`] +    /// - the [`Layout`] of the [`Row`] and its children +    /// - the cursor position +    /// +    /// [`Row`]: struct.Row.html +    /// [`Layout`]: ../layout/struct.Layout.html      fn draw<Message>(          &mut self,          children: &[Element<'_, Message, Self>], diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 438f04cf..7b231b5f 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -1,3 +1,4 @@ +//! Navigate an endless amount of content with a scrollbar.  use crate::{      column,      input::{mouse, ButtonState}, @@ -361,7 +362,18 @@ impl State {      }  } +/// The renderer of a [`Scrollable`]. +/// +/// Your [renderer] will need to implement this trait before being +/// able to use a [`Scrollable`] in your user interface. +/// +/// [`Scrollable`]: struct.Scrollable.html +/// [renderer]: ../../renderer/index.html  pub trait Renderer: crate::Renderer + Sized { +    /// Returns whether the mouse is over the scrollbar given the bounds of +    /// the [`Scrollable`] and its contents. +    /// +    /// [`Scrollable`]: struct.Scrollable.html      fn is_mouse_over_scrollbar(          &self,          bounds: Rectangle, @@ -369,6 +381,18 @@ pub trait Renderer: crate::Renderer + Sized {          cursor_position: Point,      ) -> bool; +    /// Draws the [`Scrollable`]. +    /// +    /// It receives: +    /// - the [`State`] of the [`Scrollable`] +    /// - the bounds of the [`Scrollable`] +    /// - whether the mouse is over the [`Scrollable`] or not +    /// - whether the mouse is over the scrollbar or not +    /// - the scrolling offset +    /// - the drawn content +    /// +    /// [`Scrollable`]: struct.Scrollable.html +    /// [`State`]: struct.State.html      fn draw(          &mut self,          scrollable: &State, diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs index 113cc2a4..fe503c34 100644 --- a/native/src/widget/slider.rs +++ b/native/src/widget/slider.rs @@ -13,6 +13,28 @@ use crate::{  use std::{hash::Hash, ops::RangeInclusive}; +/// An horizontal bar and a handle that selects a single value from a range of +/// values. +/// +/// A [`Slider`] will try to fill the horizontal space of its container. +/// +/// [`Slider`]: struct.Slider.html +/// +/// # Example +/// ``` +/// # use iced_native::{slider, Slider}; +/// # +/// pub enum Message { +///     SliderChanged(f32), +/// } +/// +/// let state = &mut slider::State::new(); +/// let value = 50.0; +/// +/// Slider::new(state, 0.0..=100.0, value, Message::SliderChanged); +/// ``` +/// +///   pub struct Slider<'a, Message> {      state: &'a mut State,      range: RangeInclusive<f32>, @@ -180,6 +202,9 @@ where  /// [`Slider`]: struct.Slider.html  /// [renderer]: ../../renderer/index.html  pub trait Renderer: crate::Renderer { +    /// Returns the height of the [`Slider`]. +    /// +    /// [`Slider`]: struct.Slider.html      fn height(&self) -> u32;      /// Draws a [`Slider`]. diff --git a/native/src/widget/text.rs b/native/src/widget/text.rs index c4ab88d3..cf0701b9 100644 --- a/native/src/widget/text.rs +++ b/native/src/widget/text.rs @@ -32,9 +32,9 @@ impl Text {      /// Create a new fragment of [`Text`] with the given contents.      ///      /// [`Text`]: struct.Text.html -    pub fn new(label: &str) -> Self { +    pub fn new<T: Into<String>>(label: T) -> Self {          Text { -            content: String::from(label), +            content: label.into(),              size: None,              color: None,              font: Font::Default, @@ -174,8 +174,15 @@ where  /// [renderer]: ../../renderer/index.html  /// [`UserInterface`]: ../../struct.UserInterface.html  pub trait Renderer: crate::Renderer { +    /// Returns the default size of the [`Text`]. +    /// +    /// [`Text`]: struct.Text.html      fn default_size(&self) -> u16; +    /// Measures the [`Text`] in the given bounds and returns the minimum +    /// boundaries that can fit the contents. +    /// +    /// [`Text`]: struct.Text.html      fn measure(          &self,          content: &str, diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 65306504..c3876b1d 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -10,7 +10,26 @@ use crate::{      Widget,  }; -/// A widget that can be filled with text by using a keyboard. +/// A field that can be filled with text. +/// +/// # Example +/// ``` +/// # use iced_native::{text_input, TextInput}; +/// # +/// enum Message { +///     TextInputChanged(String), +/// } +/// +/// let mut state = text_input::State::new(); +/// let value = "Some text"; +/// +/// let input = TextInput::new( +///     &mut state, +///     "This is the placeholder...", +///     value, +///     Message::TextInputChanged, +/// ); +/// ```  pub struct TextInput<'a, Message> {      state: &'a mut State,      placeholder: String, @@ -26,7 +45,14 @@ pub struct TextInput<'a, Message> {  impl<'a, Message> TextInput<'a, Message> {      /// Creates a new [`TextInput`].      /// +    /// It expects: +    /// - some [`State`] +    /// - a placeholder +    /// - the current value +    /// - a function that produces a message when the [`TextInput`] changes +    ///      /// [`TextInput`]: struct.TextInput.html +    /// [`State`]: struct.State.html      pub fn new<F>(          state: &'a mut State,          placeholder: &str, @@ -232,9 +258,32 @@ where      }  } +/// The renderer of a [`TextInput`]. +/// +/// Your [renderer] will need to implement this trait before being +/// able to use a [`TextInput`] in your user interface. +/// +/// [`TextInput`]: struct.TextInput.html +/// [renderer]: ../../renderer/index.html  pub trait Renderer: crate::Renderer + Sized { +    /// Returns the default size of the text of the [`TextInput`]. +    /// +    /// [`TextInput`]: struct.TextInput.html      fn default_size(&self) -> u16; +    /// Draws a [`TextInput`]. +    /// +    /// It receives: +    /// - its bounds of the [`TextInput`] +    /// - the bounds of the text (i.e. the current value) +    /// - the cursor position +    /// - the placeholder to show when the value is empty +    /// - the current [`Value`] +    /// - the current [`State`] +    /// +    /// [`TextInput`]: struct.TextInput.html +    /// [`Value`]: struct.Value.html +    /// [`State`]: struct.State.html      fn draw(          &mut self,          bounds: Rectangle, @@ -289,6 +338,9 @@ impl State {          }      } +    /// Returns whether the [`TextInput`] is currently focused or not. +    /// +    /// [`TextInput`]: struct.TextInput.html      pub fn is_focused(&self) -> bool {          self.is_focused      } @@ -303,7 +355,7 @@ impl State {      /// Moves the cursor of a [`TextInput`] to the right.      ///      /// [`TextInput`]: struct.TextInput.html -    pub fn move_cursor_right(&mut self, value: &Value) { +    pub(crate) fn move_cursor_right(&mut self, value: &Value) {          let current = self.cursor_position(value);          if current < value.len() { @@ -314,7 +366,7 @@ impl State {      /// Moves the cursor of a [`TextInput`] to the left.      ///      /// [`TextInput`]: struct.TextInput.html -    pub fn move_cursor_left(&mut self, value: &Value) { +    pub(crate) fn move_cursor_left(&mut self, value: &Value) {          let current = self.cursor_position(value);          if current > 0 { @@ -325,7 +377,7 @@ impl State {      /// Moves the cursor of a [`TextInput`] to the end.      ///      /// [`TextInput`]: struct.TextInput.html -    pub fn move_cursor_to_end(&mut self, value: &Value) { +    pub(crate) fn move_cursor_to_end(&mut self, value: &Value) {          self.cursor_position = value.len();      }  }  | 
