diff options
| author | 2023-03-09 19:05:38 +0100 | |
|---|---|---|
| committer | 2023-03-09 19:05:38 +0100 | |
| commit | caf2836b1b15bff6e8a2ea72441d67f297eb8707 (patch) | |
| tree | 0ffa0d1d604780999892b88de85ee93e3ed7d539 /core | |
| parent | 11b2c3bbe31a43e73a61b9bd9f022233f302ae27 (diff) | |
| parent | 424ac8177309440bbd8efe0dd9f7622cb10807ce (diff) | |
| download | iced-caf2836b1b15bff6e8a2ea72441d67f297eb8707.tar.gz iced-caf2836b1b15bff6e8a2ea72441d67f297eb8707.tar.bz2 iced-caf2836b1b15bff6e8a2ea72441d67f297eb8707.zip  | |
Merge pull request #1748 from iced-rs/feature/software-renderer
Software renderer, runtime renderer fallback, and core consolidation
Diffstat (limited to '')
| -rw-r--r-- | core/Cargo.toml | 4 | ||||
| -rw-r--r-- | core/src/alignment.rs | 3 | ||||
| -rw-r--r-- | core/src/clipboard.rs | 23 | ||||
| -rw-r--r-- | core/src/element.rs (renamed from native/src/element.rs) | 67 | ||||
| -rw-r--r-- | core/src/event.rs (renamed from native/src/event.rs) | 2 | ||||
| -rw-r--r-- | core/src/gradient.rs (renamed from graphics/src/gradient.rs) | 0 | ||||
| -rw-r--r-- | core/src/gradient/linear.rs (renamed from graphics/src/gradient/linear.rs) | 0 | ||||
| -rw-r--r-- | core/src/hasher.rs (renamed from native/src/hasher.rs) | 0 | ||||
| -rw-r--r-- | core/src/image.rs (renamed from native/src/image.rs) | 0 | ||||
| -rw-r--r-- | core/src/layout.rs (renamed from native/src/layout.rs) | 0 | ||||
| -rw-r--r-- | core/src/layout/DRUID_LICENSE (renamed from native/src/layout/DRUID_LICENSE) | 0 | ||||
| -rw-r--r-- | core/src/layout/flex.rs (renamed from native/src/layout/flex.rs) | 67 | ||||
| -rw-r--r-- | core/src/layout/limits.rs (renamed from native/src/layout/limits.rs) | 0 | ||||
| -rw-r--r-- | core/src/layout/node.rs (renamed from native/src/layout/node.rs) | 6 | ||||
| -rw-r--r-- | core/src/lib.rs | 26 | ||||
| -rw-r--r-- | core/src/mouse.rs | 3 | ||||
| -rw-r--r-- | core/src/mouse/click.rs (renamed from native/src/mouse/click.rs) | 0 | ||||
| -rw-r--r-- | core/src/overlay.rs (renamed from native/src/overlay.rs) | 3 | ||||
| -rw-r--r-- | core/src/overlay/element.rs (renamed from native/src/overlay/element.rs) | 0 | ||||
| -rw-r--r-- | core/src/overlay/group.rs (renamed from native/src/overlay/group.rs) | 4 | ||||
| -rw-r--r-- | core/src/padding.rs | 10 | ||||
| -rw-r--r-- | core/src/renderer.rs (renamed from native/src/renderer.rs) | 1 | ||||
| -rw-r--r-- | core/src/renderer/null.rs (renamed from native/src/renderer/null.rs) | 4 | ||||
| -rw-r--r-- | core/src/shell.rs (renamed from native/src/shell.rs) | 0 | ||||
| -rw-r--r-- | core/src/size.rs | 2 | ||||
| -rw-r--r-- | core/src/svg.rs (renamed from native/src/svg.rs) | 0 | ||||
| -rw-r--r-- | core/src/text.rs (renamed from native/src/text.rs) | 0 | ||||
| -rw-r--r-- | core/src/touch.rs (renamed from native/src/touch.rs) | 0 | ||||
| -rw-r--r-- | core/src/widget.rs (renamed from native/src/widget.rs) | 87 | ||||
| -rw-r--r-- | core/src/widget/id.rs (renamed from native/src/widget/id.rs) | 2 | ||||
| -rw-r--r-- | core/src/widget/operation.rs | 226 | ||||
| -rw-r--r-- | core/src/widget/operation/focusable.rs (renamed from native/src/widget/operation/focusable.rs) | 0 | ||||
| -rw-r--r-- | core/src/widget/operation/scrollable.rs (renamed from native/src/widget/operation/scrollable.rs) | 0 | ||||
| -rw-r--r-- | core/src/widget/operation/text_input.rs (renamed from native/src/widget/operation/text_input.rs) | 0 | ||||
| -rw-r--r-- | core/src/widget/text.rs (renamed from native/src/widget/text.rs) | 54 | ||||
| -rw-r--r-- | core/src/widget/tree.rs (renamed from native/src/widget/tree.rs) | 0 | ||||
| -rw-r--r-- | core/src/window.rs | 10 | ||||
| -rw-r--r-- | core/src/window/event.rs (renamed from native/src/window/event.rs) | 0 | ||||
| -rw-r--r-- | core/src/window/mode.rs (renamed from native/src/window/mode.rs) | 0 | ||||
| -rw-r--r-- | core/src/window/redraw_request.rs (renamed from native/src/window/redraw_request.rs) | 0 | ||||
| -rw-r--r-- | core/src/window/user_attention.rs (renamed from native/src/window/user_attention.rs) | 0 | 
41 files changed, 397 insertions, 207 deletions
diff --git a/core/Cargo.toml b/core/Cargo.toml index 43865e4d..dac31828 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -1,6 +1,6 @@  [package]  name = "iced_core" -version = "0.8.0" +version = "0.8.1"  authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]  edition = "2021"  description = "The essential concepts of Iced" @@ -9,6 +9,8 @@ repository = "https://github.com/iced-rs/iced"  [dependencies]  bitflags = "1.2" +thiserror = "1" +twox-hash = { version = "1.5", default-features = false }  [dependencies.palette]  version = "0.6" diff --git a/core/src/alignment.rs b/core/src/alignment.rs index 73f41d3f..51b7fca9 100644 --- a/core/src/alignment.rs +++ b/core/src/alignment.rs @@ -11,9 +11,6 @@ pub enum Alignment {      /// Align at the end of the axis.      End, - -    /// Fill the entire axis. -    Fill,  }  impl From<Horizontal> for Alignment { diff --git a/core/src/clipboard.rs b/core/src/clipboard.rs new file mode 100644 index 00000000..081b4004 --- /dev/null +++ b/core/src/clipboard.rs @@ -0,0 +1,23 @@ +//! Access the clipboard. + +/// A buffer for short-term storage and transfer within and between +/// applications. +pub trait Clipboard { +    /// Reads the current content of the [`Clipboard`] as text. +    fn read(&self) -> Option<String>; + +    /// Writes the given text contents to the [`Clipboard`]. +    fn write(&mut self, contents: String); +} + +/// A null implementation of the [`Clipboard`] trait. +#[derive(Debug, Clone, Copy)] +pub struct Null; + +impl Clipboard for Null { +    fn read(&self) -> Option<String> { +        None +    } + +    fn write(&mut self, _contents: String) {} +} diff --git a/native/src/element.rs b/core/src/element.rs index 0a677d20..98c53737 100644 --- a/native/src/element.rs +++ b/core/src/element.rs @@ -90,41 +90,65 @@ impl<'a, Message, Renderer> Element<'a, Message, Renderer> {      /// We compose the previous __messages__ with the index of the counter      /// producing them. Let's implement our __view logic__ now:      /// -    /// ``` +    /// ```no_run      /// # mod counter { -    /// #     type Text<'a> = iced_native::widget::Text<'a, iced_native::renderer::Null>; -    /// #      /// #     #[derive(Debug, Clone, Copy)]      /// #     pub enum Message {}      /// #     pub struct Counter;      /// #      /// #     impl Counter { -    /// #         pub fn view(&mut self) -> Text { -    /// #             Text::new("") +    /// #         pub fn view( +    /// #             &self, +    /// #         ) -> iced_core::Element<Message, iced_core::renderer::Null> { +    /// #             unimplemented!()      /// #         }      /// #     }      /// # }      /// # -    /// # mod iced_wgpu { -    /// #     pub use iced_native::renderer::Null as Renderer; -    /// # } +    /// # mod iced { +    /// #     pub use iced_core::renderer::Null as Renderer; +    /// #     pub use iced_core::Element;      /// # -    /// # use counter::Counter; +    /// #     pub mod widget { +    /// #         pub struct Row<Message> { +    /// #             _t: std::marker::PhantomData<Message>, +    /// #         }      /// # -    /// # struct ManyCounters { -    /// #     counters: Vec<Counter>, -    /// # } +    /// #         impl<Message> Row<Message> { +    /// #             pub fn new() -> Self { +    /// #                 unimplemented!() +    /// #             }      /// # -    /// # #[derive(Debug, Clone, Copy)] -    /// # pub enum Message { -    /// #    Counter(usize, counter::Message) +    /// #             pub fn spacing(mut self, _: u32) -> Self { +    /// #                 unimplemented!() +    /// #             } +    /// # +    /// #             pub fn push( +    /// #                 mut self, +    /// #                 _: iced_core::Element<Message, iced_core::renderer::Null>, +    /// #             ) -> Self { +    /// #                 unimplemented!() +    /// #             } +    /// #         } +    /// #     }      /// # } -    /// use iced_native::Element; -    /// use iced_native::widget::Row; -    /// use iced_wgpu::Renderer; +    /// # +    /// use counter::Counter; +    /// +    /// use iced::widget::Row; +    /// use iced::{Element, Renderer}; +    /// +    /// struct ManyCounters { +    ///     counters: Vec<Counter>, +    /// } +    /// +    /// #[derive(Debug, Clone, Copy)] +    /// pub enum Message { +    ///     Counter(usize, counter::Message), +    /// }      ///      /// impl ManyCounters { -    ///     pub fn view(&mut self) -> Row<Message, Renderer> { +    ///     pub fn view(&mut self) -> Row<Message> {      ///         // We can quickly populate a `Row` by folding over our counters      ///         self.counters.iter_mut().enumerate().fold(      ///             Row::new().spacing(20), @@ -137,9 +161,10 @@ impl<'a, Message, Renderer> Element<'a, Message, Renderer> {      ///                     // Here we turn our `Element<counter::Message>` into      ///                     // an `Element<Message>` by combining the `index` and the      ///                     // message of the `element`. -    ///                     element.map(move |message| Message::Counter(index, message)) +    ///                     element +    ///                         .map(move |message| Message::Counter(index, message)),      ///                 ) -    ///             } +    ///             },      ///         )      ///     }      /// } diff --git a/native/src/event.rs b/core/src/event.rs index bcfaf891..953cd73f 100644 --- a/native/src/event.rs +++ b/core/src/event.rs @@ -62,7 +62,7 @@ impl Status {      /// `Captured` takes precedence over `Ignored`:      ///      /// ``` -    /// use iced_native::event::Status; +    /// use iced_core::event::Status;      ///      /// assert_eq!(Status::Ignored.merge(Status::Ignored), Status::Ignored);      /// assert_eq!(Status::Ignored.merge(Status::Captured), Status::Captured); diff --git a/graphics/src/gradient.rs b/core/src/gradient.rs index 61e919d6..61e919d6 100644 --- a/graphics/src/gradient.rs +++ b/core/src/gradient.rs diff --git a/graphics/src/gradient/linear.rs b/core/src/gradient/linear.rs index c886db47..c886db47 100644 --- a/graphics/src/gradient/linear.rs +++ b/core/src/gradient/linear.rs diff --git a/native/src/hasher.rs b/core/src/hasher.rs index fa52f16d..fa52f16d 100644 --- a/native/src/hasher.rs +++ b/core/src/hasher.rs diff --git a/native/src/image.rs b/core/src/image.rs index 70fbade0..70fbade0 100644 --- a/native/src/image.rs +++ b/core/src/image.rs diff --git a/native/src/layout.rs b/core/src/layout.rs index 04954fb9..04954fb9 100644 --- a/native/src/layout.rs +++ b/core/src/layout.rs diff --git a/native/src/layout/DRUID_LICENSE b/core/src/layout/DRUID_LICENSE index d6456956..d6456956 100644 --- a/native/src/layout/DRUID_LICENSE +++ b/core/src/layout/DRUID_LICENSE diff --git a/native/src/layout/flex.rs b/core/src/layout/flex.rs index 5d70c2fc..8b967849 100644 --- a/native/src/layout/flex.rs +++ b/core/src/layout/flex.rs @@ -81,32 +81,6 @@ where      let mut nodes: Vec<Node> = Vec::with_capacity(items.len());      nodes.resize(items.len(), Node::default()); -    if align_items == Alignment::Fill { -        let mut fill_cross = axis.cross(limits.min()); - -        items.iter().for_each(|child| { -            let cross_fill_factor = match axis { -                Axis::Horizontal => child.as_widget().height(), -                Axis::Vertical => child.as_widget().width(), -            } -            .fill_factor(); - -            if cross_fill_factor == 0 { -                let (max_width, max_height) = axis.pack(available, max_cross); - -                let child_limits = -                    Limits::new(Size::ZERO, Size::new(max_width, max_height)); - -                let layout = child.as_widget().layout(renderer, &child_limits); -                let size = layout.size(); - -                fill_cross = fill_cross.max(axis.cross(size)); -            } -        }); - -        cross = fill_cross; -    } -      for (i, child) in items.iter().enumerate() {          let fill_factor = match axis {              Axis::Horizontal => child.as_widget().width(), @@ -115,31 +89,16 @@ where          .fill_factor();          if fill_factor == 0 { -            let (min_width, min_height) = if align_items == Alignment::Fill { -                axis.pack(0.0, cross) -            } else { -                axis.pack(0.0, 0.0) -            }; +            let (max_width, max_height) = axis.pack(available, max_cross); -            let (max_width, max_height) = if align_items == Alignment::Fill { -                axis.pack(available, cross) -            } else { -                axis.pack(available, max_cross) -            }; - -            let child_limits = Limits::new( -                Size::new(min_width, min_height), -                Size::new(max_width, max_height), -            ); +            let child_limits = +                Limits::new(Size::ZERO, Size::new(max_width, max_height));              let layout = child.as_widget().layout(renderer, &child_limits);              let size = layout.size();              available -= axis.main(size); - -            if align_items != Alignment::Fill { -                cross = cross.max(axis.cross(size)); -            } +            cross = cross.max(axis.cross(size));              nodes[i] = layout;          } else { @@ -164,17 +123,10 @@ where                  max_main              }; -            let (min_width, min_height) = if align_items == Alignment::Fill { -                axis.pack(min_main, cross) -            } else { -                axis.pack(min_main, axis.cross(limits.min())) -            }; +            let (min_width, min_height) = +                axis.pack(min_main, axis.cross(limits.min())); -            let (max_width, max_height) = if align_items == Alignment::Fill { -                axis.pack(max_main, cross) -            } else { -                axis.pack(max_main, max_cross) -            }; +            let (max_width, max_height) = axis.pack(max_main, max_cross);              let child_limits = Limits::new(                  Size::new(min_width, min_height), @@ -182,10 +134,7 @@ where              );              let layout = child.as_widget().layout(renderer, &child_limits); - -            if align_items != Alignment::Fill { -                cross = cross.max(axis.cross(layout.size())); -            } +            cross = cross.max(axis.cross(layout.size()));              nodes[i] = layout;          } diff --git a/native/src/layout/limits.rs b/core/src/layout/limits.rs index 5d3c1556..5d3c1556 100644 --- a/native/src/layout/limits.rs +++ b/core/src/layout/limits.rs diff --git a/native/src/layout/node.rs b/core/src/layout/node.rs index e0c7dcb2..2b44a7d5 100644 --- a/native/src/layout/node.rs +++ b/core/src/layout/node.rs @@ -56,9 +56,6 @@ impl Node {              Alignment::End => {                  self.bounds.x += space.width - self.bounds.width;              } -            Alignment::Fill => { -                self.bounds.width = space.width; -            }          }          match vertical_alignment { @@ -69,9 +66,6 @@ impl Node {              Alignment::End => {                  self.bounds.y += space.height - self.bounds.height;              } -            Alignment::Fill => { -                self.bounds.height = space.height; -            }          }      } diff --git a/core/src/lib.rs b/core/src/lib.rs index d7314851..5bdcee6a 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -25,31 +25,57 @@  #![forbid(unsafe_code, rust_2018_idioms)]  #![allow(clippy::inherent_to_string, clippy::type_complexity)]  pub mod alignment; +pub mod clipboard; +pub mod event;  pub mod font; +pub mod gradient; +pub mod image;  pub mod keyboard; +pub mod layout;  pub mod mouse; +pub mod overlay; +pub mod renderer; +pub mod svg; +pub mod text;  pub mod time; +pub mod touch; +pub mod widget; +pub mod window;  mod background;  mod color;  mod content_fit; +mod element; +mod hasher;  mod length;  mod padding;  mod pixels;  mod point;  mod rectangle; +mod shell;  mod size;  mod vector;  pub use alignment::Alignment;  pub use background::Background; +pub use clipboard::Clipboard;  pub use color::Color;  pub use content_fit::ContentFit; +pub use element::Element; +pub use event::Event;  pub use font::Font; +pub use gradient::Gradient; +pub use hasher::Hasher; +pub use layout::Layout;  pub use length::Length; +pub use overlay::Overlay;  pub use padding::Padding;  pub use pixels::Pixels;  pub use point::Point;  pub use rectangle::Rectangle; +pub use renderer::Renderer; +pub use shell::Shell;  pub use size::Size; +pub use text::Text;  pub use vector::Vector; +pub use widget::Widget; diff --git a/core/src/mouse.rs b/core/src/mouse.rs index 48214f65..0c405ce6 100644 --- a/core/src/mouse.rs +++ b/core/src/mouse.rs @@ -1,8 +1,11 @@  //! Handle mouse events. +pub mod click; +  mod button;  mod event;  mod interaction;  pub use button::Button; +pub use click::Click;  pub use event::{Event, ScrollDelta};  pub use interaction::Interaction; diff --git a/native/src/mouse/click.rs b/core/src/mouse/click.rs index 4a7d796c..4a7d796c 100644 --- a/native/src/mouse/click.rs +++ b/core/src/mouse/click.rs diff --git a/native/src/overlay.rs b/core/src/overlay.rs index 6cada416..b9f3c735 100644 --- a/native/src/overlay.rs +++ b/core/src/overlay.rs @@ -2,11 +2,8 @@  mod element;  mod group; -pub mod menu; -  pub use element::Element;  pub use group::Group; -pub use menu::Menu;  use crate::event::{self, Event};  use crate::layout; diff --git a/native/src/overlay/element.rs b/core/src/overlay/element.rs index 237d25d1..237d25d1 100644 --- a/native/src/overlay/element.rs +++ b/core/src/overlay/element.rs diff --git a/native/src/overlay/group.rs b/core/src/overlay/group.rs index 1126f0cf..0c48df34 100644 --- a/native/src/overlay/group.rs +++ b/core/src/overlay/group.rs @@ -1,12 +1,10 @@ -use iced_core::{Point, Rectangle, Size}; -  use crate::event;  use crate::layout;  use crate::mouse;  use crate::overlay;  use crate::renderer;  use crate::widget; -use crate::{Clipboard, Event, Layout, Overlay, Shell}; +use crate::{Clipboard, Event, Layout, Overlay, Point, Rectangle, Shell, Size};  /// An [`Overlay`] container that displays multiple overlay [`overlay::Element`]  /// children. diff --git a/core/src/padding.rs b/core/src/padding.rs index 752b2b86..0b1bba13 100644 --- a/core/src/padding.rs +++ b/core/src/padding.rs @@ -77,12 +77,14 @@ impl Padding {      /// Fits the [`Padding`] between the provided `inner` and `outer` [`Size`].      pub fn fit(self, inner: Size, outer: Size) -> Self {          let available = (outer - inner).max(Size::ZERO); +        let new_top = self.top.min(available.height); +        let new_left = self.left.min(available.width);          Padding { -            top: self.top.min(available.height / 2.0), -            right: self.right.min(available.width / 2.0), -            bottom: self.bottom.min(available.height / 2.0), -            left: self.left.min(available.width / 2.0), +            top: new_top, +            bottom: self.bottom.min(available.height - new_top), +            left: new_left, +            right: self.right.min(available.width - new_left),          }      }  } diff --git a/native/src/renderer.rs b/core/src/renderer.rs index 2ac78982..d6247e39 100644 --- a/native/src/renderer.rs +++ b/core/src/renderer.rs @@ -1,6 +1,7 @@  //! Write your own renderer.  #[cfg(debug_assertions)]  mod null; +  #[cfg(debug_assertions)]  pub use null::Null; diff --git a/native/src/renderer/null.rs b/core/src/renderer/null.rs index 150ee786..d93338ae 100644 --- a/native/src/renderer/null.rs +++ b/core/src/renderer/null.rs @@ -1,6 +1,6 @@  use crate::renderer::{self, Renderer};  use crate::text::{self, Text}; -use crate::{Background, Font, Point, Rectangle, Size, Theme, Vector}; +use crate::{Background, Font, Point, Rectangle, Size, Vector};  use std::borrow::Cow; @@ -18,7 +18,7 @@ impl Null {  }  impl Renderer for Null { -    type Theme = Theme; +    type Theme = ();      fn with_layer(&mut self, _bounds: Rectangle, _f: impl FnOnce(&mut Self)) {} diff --git a/native/src/shell.rs b/core/src/shell.rs index 74a5c616..74a5c616 100644 --- a/native/src/shell.rs +++ b/core/src/shell.rs diff --git a/core/src/size.rs b/core/src/size.rs index fbe940ef..7ef2f602 100644 --- a/core/src/size.rs +++ b/core/src/size.rs @@ -1,7 +1,7 @@  use crate::{Padding, Vector};  /// An amount of space in 2 dimensions. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]  pub struct Size<T = f32> {      /// The width.      pub width: T, diff --git a/native/src/svg.rs b/core/src/svg.rs index 9b98877a..9b98877a 100644 --- a/native/src/svg.rs +++ b/core/src/svg.rs diff --git a/native/src/text.rs b/core/src/text.rs index 4c72abc3..4c72abc3 100644 --- a/native/src/text.rs +++ b/core/src/text.rs diff --git a/native/src/touch.rs b/core/src/touch.rs index 18120644..18120644 100644 --- a/native/src/touch.rs +++ b/core/src/touch.rs diff --git a/native/src/widget.rs b/core/src/widget.rs index 2b3ca7be..70e2c2d9 100644 --- a/native/src/widget.rs +++ b/core/src/widget.rs @@ -1,98 +1,21 @@ -//! Use the built-in widgets or create your own. -//! -//! # Built-in widgets -//! Every built-in drawable widget has its own module with a `Renderer` trait -//! that must be implemented by a [renderer] before being able to use it as -//! a [`Widget`]. -//! -//! # Custom widgets -//! If you want to implement a custom widget, you simply need to implement the -//! [`Widget`] trait. You can use the API of the built-in widgets as a guide or -//! source of inspiration. -//! -//! [renderer]: crate::renderer -pub mod button; -pub mod checkbox; -pub mod column; -pub mod container; -pub mod helpers; -pub mod image; +//! Create custom widgets and operate on them.  pub mod operation; -pub mod pane_grid; -pub mod pick_list; -pub mod progress_bar; -pub mod radio; -pub mod row; -pub mod rule; -pub mod scrollable; -pub mod slider; -pub mod space; -pub mod svg;  pub mod text; -pub mod text_input; -pub mod toggler; -pub mod tooltip;  pub mod tree; -pub mod vertical_slider; -mod action;  mod id; -#[doc(no_inline)] -pub use button::Button; -#[doc(no_inline)] -pub use checkbox::Checkbox; -#[doc(no_inline)] -pub use column::Column; -#[doc(no_inline)] -pub use container::Container; -#[doc(no_inline)] -pub use helpers::*; -#[doc(no_inline)] -pub use image::Image; -#[doc(no_inline)] -pub use pane_grid::PaneGrid; -#[doc(no_inline)] -pub use pick_list::PickList; -#[doc(no_inline)] -pub use progress_bar::ProgressBar; -#[doc(no_inline)] -pub use radio::Radio; -#[doc(no_inline)] -pub use row::Row; -#[doc(no_inline)] -pub use rule::Rule; -#[doc(no_inline)] -pub use scrollable::Scrollable; -#[doc(no_inline)] -pub use slider::Slider; -#[doc(no_inline)] -pub use space::Space; -#[doc(no_inline)] -pub use svg::Svg; -#[doc(no_inline)] -pub use text::Text; -#[doc(no_inline)] -pub use text_input::TextInput; -#[doc(no_inline)] -pub use toggler::Toggler; -#[doc(no_inline)] -pub use tooltip::Tooltip; -#[doc(no_inline)] -pub use tree::Tree; -#[doc(no_inline)] -pub use vertical_slider::VerticalSlider; - -pub use action::Action;  pub use id::Id;  pub use operation::Operation; +pub use text::Text; +pub use tree::Tree;  use crate::event::{self, Event}; -use crate::layout; +use crate::layout::{self, Layout};  use crate::mouse;  use crate::overlay;  use crate::renderer; -use crate::{Clipboard, Layout, Length, Point, Rectangle, Shell}; +use crate::{Clipboard, Length, Point, Rectangle, Shell};  /// A component that displays information and allows interaction.  /// diff --git a/native/src/widget/id.rs b/core/src/widget/id.rs index 4b8fedf1..ae739bb7 100644 --- a/native/src/widget/id.rs +++ b/core/src/widget/id.rs @@ -24,7 +24,7 @@ impl Id {  }  #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum Internal { +enum Internal {      Unique(usize),      Custom(borrow::Cow<'static, str>),  } diff --git a/core/src/widget/operation.rs b/core/src/widget/operation.rs new file mode 100644 index 00000000..ad188c36 --- /dev/null +++ b/core/src/widget/operation.rs @@ -0,0 +1,226 @@ +//! Query or update internal widget state. +pub mod focusable; +pub mod scrollable; +pub mod text_input; + +pub use focusable::Focusable; +pub use scrollable::Scrollable; +pub use text_input::TextInput; + +use crate::widget::Id; + +use std::any::Any; +use std::fmt; +use std::rc::Rc; + +/// A piece of logic that can traverse the widget tree of an application in +/// order to query or update some widget state. +pub trait Operation<T> { +    /// Operates on a widget that contains other widgets. +    /// +    /// The `operate_on_children` function can be called to return control to +    /// the widget tree and keep traversing it. +    fn container( +        &mut self, +        id: Option<&Id>, +        operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>), +    ); + +    /// Operates on a widget that can be focused. +    fn focusable(&mut self, _state: &mut dyn Focusable, _id: Option<&Id>) {} + +    /// Operates on a widget that can be scrolled. +    fn scrollable(&mut self, _state: &mut dyn Scrollable, _id: Option<&Id>) {} + +    /// Operates on a widget that has text input. +    fn text_input(&mut self, _state: &mut dyn TextInput, _id: Option<&Id>) {} + +    /// Operates on a custom widget with some state. +    fn custom(&mut self, _state: &mut dyn Any, _id: Option<&Id>) {} + +    /// Finishes the [`Operation`] and returns its [`Outcome`]. +    fn finish(&self) -> Outcome<T> { +        Outcome::None +    } +} + +/// The result of an [`Operation`]. +pub enum Outcome<T> { +    /// The [`Operation`] produced no result. +    None, + +    /// The [`Operation`] produced some result. +    Some(T), + +    /// The [`Operation`] needs to be followed by another [`Operation`]. +    Chain(Box<dyn Operation<T>>), +} + +impl<T> fmt::Debug for Outcome<T> +where +    T: fmt::Debug, +{ +    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +        match self { +            Self::None => write!(f, "Outcome::None"), +            Self::Some(output) => write!(f, "Outcome::Some({output:?})"), +            Self::Chain(_) => write!(f, "Outcome::Chain(...)"), +        } +    } +} + +/// Maps the output of an [`Operation`] using the given function. +pub fn map<A, B>( +    operation: Box<dyn Operation<A>>, +    f: impl Fn(A) -> B + 'static, +) -> impl Operation<B> +where +    A: 'static, +    B: 'static, +{ +    #[allow(missing_debug_implementations)] +    struct Map<A, B> { +        operation: Box<dyn Operation<A>>, +        f: Rc<dyn Fn(A) -> B>, +    } + +    impl<A, B> Operation<B> for Map<A, B> +    where +        A: 'static, +        B: 'static, +    { +        fn container( +            &mut self, +            id: Option<&Id>, +            operate_on_children: &mut dyn FnMut(&mut dyn Operation<B>), +        ) { +            struct MapRef<'a, A> { +                operation: &'a mut dyn Operation<A>, +            } + +            impl<'a, A, B> Operation<B> for MapRef<'a, A> { +                fn container( +                    &mut self, +                    id: Option<&Id>, +                    operate_on_children: &mut dyn FnMut(&mut dyn Operation<B>), +                ) { +                    let Self { operation, .. } = self; + +                    operation.container(id, &mut |operation| { +                        operate_on_children(&mut MapRef { operation }); +                    }); +                } + +                fn scrollable( +                    &mut self, +                    state: &mut dyn Scrollable, +                    id: Option<&Id>, +                ) { +                    self.operation.scrollable(state, id); +                } + +                fn focusable( +                    &mut self, +                    state: &mut dyn Focusable, +                    id: Option<&Id>, +                ) { +                    self.operation.focusable(state, id); +                } + +                fn text_input( +                    &mut self, +                    state: &mut dyn TextInput, +                    id: Option<&Id>, +                ) { +                    self.operation.text_input(state, id); +                } + +                fn custom(&mut self, state: &mut dyn Any, id: Option<&Id>) { +                    self.operation.custom(state, id); +                } +            } + +            let Self { operation, .. } = self; + +            MapRef { +                operation: operation.as_mut(), +            } +            .container(id, operate_on_children); +        } + +        fn focusable(&mut self, state: &mut dyn Focusable, id: Option<&Id>) { +            self.operation.focusable(state, id); +        } + +        fn scrollable(&mut self, state: &mut dyn Scrollable, id: Option<&Id>) { +            self.operation.scrollable(state, id); +        } + +        fn text_input(&mut self, state: &mut dyn TextInput, id: Option<&Id>) { +            self.operation.text_input(state, id); +        } + +        fn custom(&mut self, state: &mut dyn Any, id: Option<&Id>) { +            self.operation.custom(state, id); +        } + +        fn finish(&self) -> Outcome<B> { +            match self.operation.finish() { +                Outcome::None => Outcome::None, +                Outcome::Some(output) => Outcome::Some((self.f)(output)), +                Outcome::Chain(next) => Outcome::Chain(Box::new(Map { +                    operation: next, +                    f: self.f.clone(), +                })), +            } +        } +    } + +    Map { +        operation, +        f: Rc::new(f), +    } +} + +/// Produces an [`Operation`] that applies the given [`Operation`] to the +/// children of a container with the given [`Id`]. +pub fn scope<T: 'static>( +    target: Id, +    operation: impl Operation<T> + 'static, +) -> impl Operation<T> { +    struct ScopedOperation<Message> { +        target: Id, +        operation: Box<dyn Operation<Message>>, +    } + +    impl<Message: 'static> Operation<Message> for ScopedOperation<Message> { +        fn container( +            &mut self, +            id: Option<&Id>, +            operate_on_children: &mut dyn FnMut(&mut dyn Operation<Message>), +        ) { +            if id == Some(&self.target) { +                operate_on_children(self.operation.as_mut()); +            } else { +                operate_on_children(self); +            } +        } + +        fn finish(&self) -> Outcome<Message> { +            match self.operation.finish() { +                Outcome::Chain(next) => { +                    Outcome::Chain(Box::new(ScopedOperation { +                        target: self.target.clone(), +                        operation: next, +                    })) +                } +                outcome => outcome, +            } +        } +    } + +    ScopedOperation { +        target, +        operation: Box::new(operation), +    } +} diff --git a/native/src/widget/operation/focusable.rs b/core/src/widget/operation/focusable.rs index 312e4894..312e4894 100644 --- a/native/src/widget/operation/focusable.rs +++ b/core/src/widget/operation/focusable.rs diff --git a/native/src/widget/operation/scrollable.rs b/core/src/widget/operation/scrollable.rs index 3b20631f..3b20631f 100644 --- a/native/src/widget/operation/scrollable.rs +++ b/core/src/widget/operation/scrollable.rs diff --git a/native/src/widget/operation/text_input.rs b/core/src/widget/operation/text_input.rs index 4c773e99..4c773e99 100644 --- a/native/src/widget/operation/text_input.rs +++ b/core/src/widget/operation/text_input.rs diff --git a/native/src/widget/text.rs b/core/src/widget/text.rs index aede754a..485bb542 100644 --- a/native/src/widget/text.rs +++ b/core/src/widget/text.rs @@ -4,27 +4,13 @@ use crate::layout;  use crate::renderer;  use crate::text;  use crate::widget::Tree; -use crate::{Element, Layout, Length, Pixels, Point, Rectangle, Size, Widget}; +use crate::{ +    Color, Element, Layout, Length, Pixels, Point, Rectangle, Size, Widget, +};  use std::borrow::Cow; -pub use iced_style::text::{Appearance, StyleSheet}; -  /// A paragraph of text. -/// -/// # Example -/// -/// ``` -/// # use iced_native::Color; -/// # -/// # type Text<'a> = iced_native::widget::Text<'a, iced_native::renderer::Null>; -/// # -/// Text::new("I <3 iced!") -///     .size(40) -///     .style(Color::from([0.0, 0.0, 1.0])); -/// ``` -/// -///   #[allow(missing_debug_implementations)]  pub struct Text<'a, Renderer>  where @@ -211,7 +197,7 @@ pub fn draw<Renderer>(          alignment::Vertical::Bottom => bounds.y + bounds.height,      }; -    renderer.fill_text(crate::text::Text { +    renderer.fill_text(crate::Text {          content,          size: size.unwrap_or_else(|| renderer.default_size()),          bounds: Rectangle { x, y, ..bounds }, @@ -252,12 +238,40 @@ where      }  } +impl<'a, Renderer> From<&'a str> for Text<'a, Renderer> +where +    Renderer: text::Renderer, +    Renderer::Theme: StyleSheet, +{ +    fn from(content: &'a str) -> Self { +        Self::new(content) +    } +} +  impl<'a, Message, Renderer> From<&'a str> for Element<'a, Message, Renderer>  where      Renderer: text::Renderer + 'a,      Renderer::Theme: StyleSheet,  { -    fn from(contents: &'a str) -> Self { -        Text::new(contents).into() +    fn from(content: &'a str) -> Self { +        Text::from(content).into()      }  } + +/// The style sheet of some text. +pub trait StyleSheet { +    /// The supported style of the [`StyleSheet`]. +    type Style: Default + Copy; + +    /// Produces the [`Appearance`] of some text. +    fn appearance(&self, style: Self::Style) -> Appearance; +} + +/// The apperance of some text. +#[derive(Debug, Clone, Copy, Default)] +pub struct Appearance { +    /// The [`Color`] of the text. +    /// +    /// The default, `None`, means using the inherited color. +    pub color: Option<Color>, +} diff --git a/native/src/widget/tree.rs b/core/src/widget/tree.rs index 0af40c33..0af40c33 100644 --- a/native/src/widget/tree.rs +++ b/core/src/widget/tree.rs diff --git a/core/src/window.rs b/core/src/window.rs new file mode 100644 index 00000000..d829a4b4 --- /dev/null +++ b/core/src/window.rs @@ -0,0 +1,10 @@ +//! Build window-based GUI applications. +mod event; +mod mode; +mod redraw_request; +mod user_attention; + +pub use event::Event; +pub use mode::Mode; +pub use redraw_request::RedrawRequest; +pub use user_attention::UserAttention; diff --git a/native/src/window/event.rs b/core/src/window/event.rs index e2fb5e66..e2fb5e66 100644 --- a/native/src/window/event.rs +++ b/core/src/window/event.rs diff --git a/native/src/window/mode.rs b/core/src/window/mode.rs index fdce8e23..fdce8e23 100644 --- a/native/src/window/mode.rs +++ b/core/src/window/mode.rs diff --git a/native/src/window/redraw_request.rs b/core/src/window/redraw_request.rs index 3b4f0fd3..3b4f0fd3 100644 --- a/native/src/window/redraw_request.rs +++ b/core/src/window/redraw_request.rs diff --git a/native/src/window/user_attention.rs b/core/src/window/user_attention.rs index b03dfeef..b03dfeef 100644 --- a/native/src/window/user_attention.rs +++ b/core/src/window/user_attention.rs  | 
