summaryrefslogtreecommitdiffstats
path: root/native/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-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/hasher.rs (renamed from native/src/hasher.rs)0
-rw-r--r--core/src/image.rs (renamed from native/src/image.rs)12
-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)0
-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)0
-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/renderer.rs (renamed from native/src/renderer.rs)1
-rw-r--r--core/src/renderer/null.rs (renamed from native/src/renderer/null.rs)20
-rw-r--r--core/src/shell.rs (renamed from native/src/shell.rs)0
-rw-r--r--core/src/svg.rs (renamed from native/src/svg.rs)4
-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)90
-rw-r--r--core/src/widget/id.rs (renamed from native/src/widget/id.rs)2
-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)110
-rw-r--r--core/src/widget/tree.rs (renamed from native/src/widget/tree.rs)0
-rw-r--r--core/src/window/event.rs (renamed from native/src/window/event.rs)0
-rw-r--r--core/src/window/icon.rs (renamed from native/src/window/icon.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
-rw-r--r--native/src/mouse.rs6
-rw-r--r--native/src/runtime.rs18
-rw-r--r--native/src/subscription.rs283
-rw-r--r--native/src/text.rs114
-rw-r--r--native/src/widget/action.rs154
-rw-r--r--native/src/widget/helpers.rs326
-rw-r--r--native/src/widget/operation.rs112
-rw-r--r--native/src/window.rs33
-rw-r--r--runtime/src/clipboard.rs (renamed from native/src/clipboard.rs)37
-rw-r--r--runtime/src/command.rs (renamed from native/src/command.rs)55
-rw-r--r--runtime/src/command/action.rs (renamed from native/src/command/action.rs)24
-rw-r--r--runtime/src/debug/basic.rs (renamed from native/src/debug/basic.rs)2
-rw-r--r--runtime/src/debug/null.rs (renamed from native/src/debug/null.rs)0
-rw-r--r--runtime/src/keyboard.rs (renamed from native/src/keyboard.rs)0
-rw-r--r--runtime/src/lib.rs (renamed from native/src/lib.rs)45
-rw-r--r--runtime/src/program.rs (renamed from native/src/program.rs)7
-rw-r--r--runtime/src/program/state.rs (renamed from native/src/program/state.rs)18
-rw-r--r--runtime/src/system.rs (renamed from native/src/system.rs)0
-rw-r--r--runtime/src/system/action.rs (renamed from native/src/system/action.rs)0
-rw-r--r--runtime/src/system/information.rs (renamed from native/src/system/information.rs)0
-rw-r--r--runtime/src/user_interface.rs (renamed from native/src/user_interface.rs)89
-rw-r--r--runtime/src/window/action.rs (renamed from native/src/window/action.rs)4
-rw-r--r--widget/src/button.rs (renamed from native/src/widget/button.rs)36
-rw-r--r--widget/src/checkbox.rs (renamed from native/src/widget/checkbox.rs)89
-rw-r--r--widget/src/column.rs (renamed from native/src/widget/column.rs)20
-rw-r--r--widget/src/container.rs (renamed from native/src/widget/container.rs)28
-rw-r--r--widget/src/image.rs (renamed from native/src/widget/image.rs)17
-rw-r--r--widget/src/image/viewer.rs (renamed from native/src/widget/image/viewer.rs)14
-rw-r--r--widget/src/mouse_area.rs (renamed from native/src/widget/mouse_area.rs)20
-rw-r--r--widget/src/overlay/menu.rs (renamed from native/src/overlay/menu.rs)105
-rw-r--r--widget/src/pane_grid.rs (renamed from native/src/widget/pane_grid.rs)42
-rw-r--r--widget/src/pane_grid/axis.rs (renamed from native/src/widget/pane_grid/axis.rs)2
-rw-r--r--widget/src/pane_grid/configuration.rs (renamed from native/src/widget/pane_grid/configuration.rs)2
-rw-r--r--widget/src/pane_grid/content.rs (renamed from native/src/widget/pane_grid/content.rs)30
-rw-r--r--widget/src/pane_grid/direction.rs (renamed from native/src/widget/pane_grid/direction.rs)0
-rw-r--r--widget/src/pane_grid/draggable.rs (renamed from native/src/widget/pane_grid/draggable.rs)2
-rw-r--r--widget/src/pane_grid/node.rs (renamed from native/src/widget/pane_grid/node.rs)4
-rw-r--r--widget/src/pane_grid/pane.rs (renamed from native/src/widget/pane_grid/pane.rs)0
-rw-r--r--widget/src/pane_grid/split.rs (renamed from native/src/widget/pane_grid/split.rs)0
-rw-r--r--widget/src/pane_grid/state.rs (renamed from native/src/widget/pane_grid/state.rs)6
-rw-r--r--widget/src/pane_grid/title_bar.rs (renamed from native/src/widget/pane_grid/title_bar.rs)24
-rw-r--r--widget/src/pick_list.rs (renamed from native/src/widget/pick_list.rs)152
-rw-r--r--widget/src/progress_bar.rs (renamed from native/src/widget/progress_bar.rs)26
-rw-r--r--widget/src/radio.rs (renamed from native/src/widget/radio.rs)79
-rw-r--r--widget/src/row.rs (renamed from native/src/widget/row.rs)20
-rw-r--r--widget/src/rule.rs (renamed from native/src/widget/rule.rs)20
-rw-r--r--widget/src/scrollable.rs (renamed from native/src/widget/scrollable.rs)168
-rw-r--r--widget/src/slider.rs (renamed from native/src/widget/slider.rs)34
-rw-r--r--widget/src/space.rs (renamed from native/src/widget/space.rs)13
-rw-r--r--widget/src/svg.rs (renamed from native/src/widget/svg.rs)14
-rw-r--r--widget/src/text_input.rs (renamed from native/src/widget/text_input.rs)145
-rw-r--r--widget/src/text_input/cursor.rs (renamed from native/src/widget/text_input/cursor.rs)2
-rw-r--r--widget/src/text_input/editor.rs (renamed from native/src/widget/text_input/editor.rs)2
-rw-r--r--widget/src/text_input/value.rs (renamed from native/src/widget/text_input/value.rs)0
-rw-r--r--widget/src/toggler.rs (renamed from native/src/widget/toggler.rs)69
-rw-r--r--widget/src/tooltip.rs (renamed from native/src/widget/tooltip.rs)37
-rw-r--r--widget/src/vertical_slider.rs (renamed from native/src/widget/vertical_slider.rs)39
87 files changed, 1045 insertions, 1858 deletions
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/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..85d9d475 100644
--- a/native/src/image.rs
+++ b/core/src/image.rs
@@ -6,7 +6,7 @@ use std::path::PathBuf;
use std::sync::Arc;
/// A handle of some image data.
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Handle {
id: u64,
data: Data,
@@ -110,6 +110,14 @@ impl std::hash::Hash for Bytes {
}
}
+impl PartialEq for Bytes {
+ fn eq(&self, other: &Self) -> bool {
+ self.as_ref() == other.as_ref()
+ }
+}
+
+impl Eq for Bytes {}
+
impl AsRef<[u8]> for Bytes {
fn as_ref(&self) -> &[u8] {
self.0.as_ref().as_ref()
@@ -125,7 +133,7 @@ impl std::ops::Deref for Bytes {
}
/// The data of a raster image.
-#[derive(Clone, Hash)]
+#[derive(Clone, PartialEq, Eq, Hash)]
pub enum Data {
/// File data
Path(PathBuf),
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 8b967849..8b967849 100644
--- a/native/src/layout/flex.rs
+++ b/core/src/layout/flex.rs
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 2b44a7d5..2b44a7d5 100644
--- a/native/src/layout/node.rs
+++ b/core/src/layout/node.rs
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/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 9376d540..f0cc952e 100644
--- a/native/src/renderer/null.rs
+++ b/core/src/renderer/null.rs
@@ -1,6 +1,8 @@
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;
/// A renderer that does nothing.
///
@@ -16,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)) {}
@@ -40,20 +42,28 @@ impl Renderer for Null {
impl text::Renderer for Null {
type Font = Font;
- const ICON_FONT: Font = Font::Default;
+ const ICON_FONT: Font = Font::DEFAULT;
const CHECKMARK_ICON: char = '0';
const ARROW_DOWN_ICON: char = '0';
+ fn default_font(&self) -> Self::Font {
+ Font::default()
+ }
+
fn default_size(&self) -> f32 {
- 20.0
+ 16.0
}
+ fn load_font(&mut self, _font: Cow<'static, [u8]>) {}
+
fn measure(
&self,
_content: &str,
_size: f32,
+ _line_height: text::LineHeight,
_font: Font,
_bounds: Size,
+ _shaping: text::Shaping,
) -> (f32, f32) {
(0.0, 20.0)
}
@@ -62,8 +72,10 @@ impl text::Renderer for Null {
&self,
_contents: &str,
_size: f32,
+ _line_height: text::LineHeight,
_font: Self::Font,
_bounds: Size,
+ _shaping: text::Shaping,
_point: Point,
_nearest_only: bool,
) -> Option<text::Hit> {
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/native/src/svg.rs b/core/src/svg.rs
index 9b98877a..54e9434e 100644
--- a/native/src/svg.rs
+++ b/core/src/svg.rs
@@ -7,7 +7,7 @@ use std::path::PathBuf;
use std::sync::Arc;
/// A handle of Svg data.
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Handle {
id: u64,
data: Arc<Data>,
@@ -57,7 +57,7 @@ impl Hash for Handle {
}
/// The data of a vectorial image.
-#[derive(Clone, Hash)]
+#[derive(Clone, Hash, PartialEq, Eq)]
pub enum Data {
/// File data
Path(PathBuf),
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 6b83f1fa..769f8659 100644
--- a/native/src/widget.rs
+++ b/core/src/widget.rs
@@ -1,101 +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;
-pub mod mouse_area;
+//! 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 mouse_area::MouseArea;
-#[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/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 f947344d..f947344d 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 3fee48f2..90af88b7 100644
--- a/native/src/widget/text.rs
+++ b/core/src/widget/text.rs
@@ -4,27 +4,15 @@ 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};
+pub use text::{LineHeight, Shaping};
/// 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]));
-/// ```
-///
-/// ![Text drawn by `iced_wgpu`](https://github.com/iced-rs/iced/blob/7760618fb112074bc40b148944521f312152012a/docs/images/text.png?raw=true)
#[allow(missing_debug_implementations)]
pub struct Text<'a, Renderer>
where
@@ -33,11 +21,13 @@ where
{
content: Cow<'a, str>,
size: Option<f32>,
+ line_height: LineHeight,
width: Length,
height: Length,
horizontal_alignment: alignment::Horizontal,
vertical_alignment: alignment::Vertical,
- font: Renderer::Font,
+ font: Option<Renderer::Font>,
+ shaping: Shaping,
style: <Renderer::Theme as StyleSheet>::Style,
}
@@ -51,11 +41,13 @@ where
Text {
content: content.into(),
size: None,
- font: Default::default(),
+ line_height: LineHeight::default(),
+ font: None,
width: Length::Shrink,
height: Length::Shrink,
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
+ shaping: Shaping::Basic,
style: Default::default(),
}
}
@@ -66,11 +58,17 @@ where
self
}
+ /// Sets the [`LineHeight`] of the [`Text`].
+ pub fn line_height(mut self, line_height: impl Into<LineHeight>) -> Self {
+ self.line_height = line_height.into();
+ self
+ }
+
/// Sets the [`Font`] of the [`Text`].
///
/// [`Font`]: crate::text::Renderer::Font
pub fn font(mut self, font: impl Into<Renderer::Font>) -> Self {
- self.font = font.into();
+ self.font = Some(font.into());
self
}
@@ -112,6 +110,12 @@ where
self.vertical_alignment = alignment;
self
}
+
+ /// Sets the [`Shaping`] strategy of the [`Text`].
+ pub fn shaping(mut self, shaping: Shaping) -> Self {
+ self.shaping = shaping;
+ self
+ }
}
impl<'a, Message, Renderer> Widget<Message, Renderer> for Text<'a, Renderer>
@@ -138,8 +142,14 @@ where
let bounds = limits.max();
- let (width, height) =
- renderer.measure(&self.content, size, self.font.clone(), bounds);
+ let (width, height) = renderer.measure(
+ &self.content,
+ size,
+ self.line_height,
+ self.font.unwrap_or_else(|| renderer.default_font()),
+ bounds,
+ self.shaping,
+ );
let size = limits.resolve(Size::new(width, height));
@@ -162,10 +172,12 @@ where
layout,
&self.content,
self.size,
- self.font.clone(),
- theme.appearance(self.style),
+ self.line_height,
+ self.font,
+ theme.appearance(self.style.clone()),
self.horizontal_alignment,
self.vertical_alignment,
+ self.shaping,
);
}
}
@@ -186,10 +198,12 @@ pub fn draw<Renderer>(
layout: Layout<'_>,
content: &str,
size: Option<f32>,
- font: Renderer::Font,
+ line_height: LineHeight,
+ font: Option<Renderer::Font>,
appearance: Appearance,
horizontal_alignment: alignment::Horizontal,
vertical_alignment: alignment::Vertical,
+ shaping: Shaping,
) where
Renderer: text::Renderer,
{
@@ -207,14 +221,18 @@ pub fn draw<Renderer>(
alignment::Vertical::Bottom => bounds.y + bounds.height,
};
- renderer.fill_text(crate::text::Text {
+ let size = size.unwrap_or_else(|| renderer.default_size());
+
+ renderer.fill_text(crate::Text {
content,
- size: size.unwrap_or_else(|| renderer.default_size()),
+ size,
+ line_height,
bounds: Rectangle { x, y, ..bounds },
color: appearance.color.unwrap_or(style.text_color),
- font,
+ font: font.unwrap_or_else(|| renderer.default_font()),
horizontal_alignment,
vertical_alignment,
+ shaping,
});
}
@@ -238,22 +256,52 @@ where
Self {
content: self.content.clone(),
size: self.size,
+ line_height: self.line_height,
width: self.width,
height: self.height,
horizontal_alignment: self.horizontal_alignment,
vertical_alignment: self.vertical_alignment,
- font: self.font.clone(),
- style: self.style,
+ font: self.font,
+ style: self.style.clone(),
+ shaping: self.shaping,
}
}
}
+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 + Clone;
+
+ /// 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/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/icon.rs b/core/src/window/icon.rs
index 31868ecf..31868ecf 100644
--- a/native/src/window/icon.rs
+++ b/core/src/window/icon.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
diff --git a/native/src/mouse.rs b/native/src/mouse.rs
deleted file mode 100644
index 9ee406cf..00000000
--- a/native/src/mouse.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-//! Track mouse events.
-
-pub mod click;
-
-pub use click::Click;
-pub use iced_core::mouse::*;
diff --git a/native/src/runtime.rs b/native/src/runtime.rs
deleted file mode 100644
index 5b0a6925..00000000
--- a/native/src/runtime.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-//! Run commands and subscriptions.
-use crate::event::{self, Event};
-use crate::Hasher;
-
-/// A native runtime with a generic executor and receiver of results.
-///
-/// It can be used by shells to easily spawn a [`Command`] or track a
-/// [`Subscription`].
-///
-/// [`Command`]: crate::Command
-/// [`Subscription`]: crate::Subscription
-pub type Runtime<Executor, Receiver, Message> = iced_futures::Runtime<
- Hasher,
- (Event, event::Status),
- Executor,
- Receiver,
- Message,
->;
diff --git a/native/src/subscription.rs b/native/src/subscription.rs
deleted file mode 100644
index 115ffc42..00000000
--- a/native/src/subscription.rs
+++ /dev/null
@@ -1,283 +0,0 @@
-//! Listen to external events in your application.
-use crate::event::{self, Event};
-use crate::window;
-use crate::Hasher;
-
-use iced_futures::futures::channel::mpsc;
-use iced_futures::futures::never::Never;
-use iced_futures::futures::{self, Future, Stream};
-use iced_futures::{BoxStream, MaybeSend};
-
-use std::hash::Hash;
-
-/// A request to listen to external events.
-///
-/// Besides performing async actions on demand with [`Command`], most
-/// applications also need to listen to external events passively.
-///
-/// A [`Subscription`] is normally provided to some runtime, like a [`Command`],
-/// and it will generate events as long as the user keeps requesting it.
-///
-/// For instance, you can use a [`Subscription`] to listen to a WebSocket
-/// connection, keyboard presses, mouse events, time ticks, etc.
-///
-/// [`Command`]: crate::Command
-pub type Subscription<T> =
- iced_futures::Subscription<Hasher, (Event, event::Status), T>;
-
-/// A stream of runtime events.
-///
-/// It is the input of a [`Subscription`] in the native runtime.
-pub type EventStream = BoxStream<(Event, event::Status)>;
-
-/// A native [`Subscription`] tracker.
-pub type Tracker =
- iced_futures::subscription::Tracker<Hasher, (Event, event::Status)>;
-
-pub use iced_futures::subscription::Recipe;
-
-/// Returns a [`Subscription`] to all the ignored runtime events.
-///
-/// This subscription will notify your application of any [`Event`] that was
-/// not captured by any widget.
-pub fn events() -> Subscription<Event> {
- events_with(|event, status| match status {
- event::Status::Ignored => Some(event),
- event::Status::Captured => None,
- })
-}
-
-/// Returns a [`Subscription`] that filters all the runtime events with the
-/// provided function, producing messages accordingly.
-///
-/// This subscription will call the provided function for every [`Event`]
-/// handled by the runtime. If the function:
-///
-/// - Returns `None`, the [`Event`] will be discarded.
-/// - Returns `Some` message, the `Message` will be produced.
-pub fn events_with<Message>(
- f: fn(Event, event::Status) -> Option<Message>,
-) -> Subscription<Message>
-where
- Message: 'static + MaybeSend,
-{
- #[derive(Hash)]
- struct EventsWith;
-
- Subscription::from_recipe(Runner {
- id: (EventsWith, f),
- spawn: move |events| {
- use futures::future;
- use futures::stream::StreamExt;
-
- events.filter_map(move |(event, status)| {
- future::ready(match event {
- Event::Window(window::Event::RedrawRequested(_)) => None,
- _ => f(event, status),
- })
- })
- },
- })
-}
-
-pub(crate) fn raw_events<Message>(
- f: fn(Event, event::Status) -> Option<Message>,
-) -> Subscription<Message>
-where
- Message: 'static + MaybeSend,
-{
- #[derive(Hash)]
- struct RawEvents;
-
- Subscription::from_recipe(Runner {
- id: (RawEvents, f),
- spawn: move |events| {
- use futures::future;
- use futures::stream::StreamExt;
-
- events.filter_map(move |(event, status)| {
- future::ready(f(event, status))
- })
- },
- })
-}
-
-/// Returns a [`Subscription`] that will call the given function to create and
-/// asynchronously run the given [`Stream`].
-pub fn run<S, Message>(builder: fn() -> S) -> Subscription<Message>
-where
- S: Stream<Item = Message> + MaybeSend + 'static,
- Message: 'static,
-{
- Subscription::from_recipe(Runner {
- id: builder,
- spawn: move |_| builder(),
- })
-}
-
-/// Returns a [`Subscription`] that will create and asynchronously run the
-/// given [`Stream`].
-///
-/// The `id` will be used to uniquely identify the [`Subscription`].
-pub fn run_with_id<I, S, Message>(id: I, stream: S) -> Subscription<Message>
-where
- I: Hash + 'static,
- S: Stream<Item = Message> + MaybeSend + 'static,
- Message: 'static,
-{
- Subscription::from_recipe(Runner {
- id,
- spawn: move |_| stream,
- })
-}
-
-/// Returns a [`Subscription`] that will create and asynchronously run a
-/// [`Stream`] that will call the provided closure to produce every `Message`.
-///
-/// The `id` will be used to uniquely identify the [`Subscription`].
-pub fn unfold<I, T, Fut, Message>(
- id: I,
- initial: T,
- mut f: impl FnMut(T) -> Fut + MaybeSend + Sync + 'static,
-) -> Subscription<Message>
-where
- I: Hash + 'static,
- T: MaybeSend + 'static,
- Fut: Future<Output = (Message, T)> + MaybeSend + 'static,
- Message: 'static + MaybeSend,
-{
- use futures::future::FutureExt;
-
- run_with_id(
- id,
- futures::stream::unfold(initial, move |state| f(state).map(Some)),
- )
-}
-
-/// Creates a [`Subscription`] that publishes the events sent from a [`Future`]
-/// to an [`mpsc::Sender`] with the given bounds.
-///
-/// # Creating an asynchronous worker with bidirectional communication
-/// You can leverage this helper to create a [`Subscription`] that spawns
-/// an asynchronous worker in the background and establish a channel of
-/// communication with an `iced` application.
-///
-/// You can achieve this by creating an `mpsc` channel inside the closure
-/// and returning the `Sender` as a `Message` for the `Application`:
-///
-/// ```
-/// use iced_native::subscription::{self, Subscription};
-/// use iced_native::futures::channel::mpsc;
-/// use iced_native::futures::sink::SinkExt;
-///
-/// pub enum Event {
-/// Ready(mpsc::Sender<Input>),
-/// WorkFinished,
-/// // ...
-/// }
-///
-/// enum Input {
-/// DoSomeWork,
-/// // ...
-/// }
-///
-/// enum State {
-/// Starting,
-/// Ready(mpsc::Receiver<Input>),
-/// }
-///
-/// fn some_worker() -> Subscription<Event> {
-/// struct SomeWorker;
-///
-/// subscription::channel(std::any::TypeId::of::<SomeWorker>(), 100, |mut output| async move {
-/// let mut state = State::Starting;
-///
-/// loop {
-/// match &mut state {
-/// State::Starting => {
-/// // Create channel
-/// let (sender, receiver) = mpsc::channel(100);
-///
-/// // Send the sender back to the application
-/// output.send(Event::Ready(sender)).await;
-///
-/// // We are ready to receive messages
-/// state = State::Ready(receiver);
-/// }
-/// State::Ready(receiver) => {
-/// use iced_native::futures::StreamExt;
-///
-/// // Read next input sent from `Application`
-/// let input = receiver.select_next_some().await;
-///
-/// match input {
-/// Input::DoSomeWork => {
-/// // Do some async work...
-///
-/// // Finally, we can optionally produce a message to tell the
-/// // `Application` the work is done
-/// output.send(Event::WorkFinished).await;
-/// }
-/// }
-/// }
-/// }
-/// }
-/// })
-/// }
-/// ```
-///
-/// Check out the [`websocket`] example, which showcases this pattern to maintain a WebSocket
-/// connection open.
-///
-/// [`websocket`]: https://github.com/iced-rs/iced/tree/0.9/examples/websocket
-pub fn channel<I, Fut, Message>(
- id: I,
- size: usize,
- f: impl Fn(mpsc::Sender<Message>) -> Fut + MaybeSend + Sync + 'static,
-) -> Subscription<Message>
-where
- I: Hash + 'static,
- Fut: Future<Output = Never> + MaybeSend + 'static,
- Message: 'static + MaybeSend,
-{
- use futures::stream::{self, StreamExt};
-
- Subscription::from_recipe(Runner {
- id,
- spawn: move |_| {
- let (sender, receiver) = mpsc::channel(size);
-
- let runner = stream::once(f(sender)).map(|_| unreachable!());
-
- stream::select(receiver, runner)
- },
- })
-}
-
-struct Runner<I, F, S, Message>
-where
- F: FnOnce(EventStream) -> S,
- S: Stream<Item = Message>,
-{
- id: I,
- spawn: F,
-}
-
-impl<I, S, F, Message> Recipe<Hasher, (Event, event::Status)>
- for Runner<I, F, S, Message>
-where
- I: Hash + 'static,
- F: FnOnce(EventStream) -> S,
- S: Stream<Item = Message> + MaybeSend + 'static,
-{
- type Output = Message;
-
- fn hash(&self, state: &mut Hasher) {
- std::any::TypeId::of::<I>().hash(state);
- self.id.hash(state);
- }
-
- fn stream(self: Box<Self>, input: EventStream) -> BoxStream<Self::Output> {
- iced_futures::boxed_stream((self.spawn)(input))
- }
-}
diff --git a/native/src/text.rs b/native/src/text.rs
deleted file mode 100644
index 55c3cfd3..00000000
--- a/native/src/text.rs
+++ /dev/null
@@ -1,114 +0,0 @@
-//! Draw and interact with text.
-use crate::alignment;
-use crate::{Color, Point, Rectangle, Size, Vector};
-
-/// A paragraph.
-#[derive(Debug, Clone, Copy)]
-pub struct Text<'a, Font> {
- /// The content of the paragraph.
- pub content: &'a str,
-
- /// The bounds of the paragraph.
- pub bounds: Rectangle,
-
- /// The size of the [`Text`].
- pub size: f32,
-
- /// The color of the [`Text`].
- pub color: Color,
-
- /// The font of the [`Text`].
- pub font: Font,
-
- /// The horizontal alignment of the [`Text`].
- pub horizontal_alignment: alignment::Horizontal,
-
- /// The vertical alignment of the [`Text`].
- pub vertical_alignment: alignment::Vertical,
-}
-
-/// The result of hit testing on text.
-#[derive(Debug, Clone, Copy, PartialEq)]
-pub enum Hit {
- /// The point was within the bounds of the returned character index.
- CharOffset(usize),
- /// The provided point was not within the bounds of a glyph. The index
- /// of the character with the closest centeroid position is returned,
- /// as well as its delta.
- NearestCharOffset(usize, Vector),
-}
-
-impl Hit {
- /// Computes the cursor position of the [`Hit`] .
- pub fn cursor(self) -> usize {
- match self {
- Self::CharOffset(i) => i,
- Self::NearestCharOffset(i, delta) => {
- if delta.x > f32::EPSILON {
- i + 1
- } else {
- i
- }
- }
- }
- }
-}
-
-/// A renderer capable of measuring and drawing [`Text`].
-pub trait Renderer: crate::Renderer {
- /// The font type used.
- type Font: Default + Clone;
-
- /// The icon font of the backend.
- const ICON_FONT: Self::Font;
-
- /// The `char` representing a ✔ icon in the [`ICON_FONT`].
- ///
- /// [`ICON_FONT`]: Self::ICON_FONT
- const CHECKMARK_ICON: char;
-
- /// The `char` representing a â–¼ icon in the built-in [`ICON_FONT`].
- ///
- /// [`ICON_FONT`]: Self::ICON_FONT
- const ARROW_DOWN_ICON: char;
-
- /// Returns the default size of [`Text`].
- fn default_size(&self) -> f32;
-
- /// Measures the text in the given bounds and returns the minimum boundaries
- /// that can fit the contents.
- fn measure(
- &self,
- content: &str,
- size: f32,
- font: Self::Font,
- bounds: Size,
- ) -> (f32, f32);
-
- /// Measures the width of the text as if it were laid out in a single line.
- fn measure_width(&self, content: &str, size: f32, font: Self::Font) -> f32 {
- let (width, _) = self.measure(content, size, font, Size::INFINITY);
-
- width
- }
-
- /// Tests whether the provided point is within the boundaries of text
- /// laid out with the given parameters, returning information about
- /// the nearest character.
- ///
- /// If `nearest_only` is true, the hit test does not consider whether the
- /// the point is interior to any glyph bounds, returning only the character
- /// with the nearest centeroid.
- fn hit_test(
- &self,
- contents: &str,
- size: f32,
- font: Self::Font,
- bounds: Size,
- point: Point,
- nearest_only: bool,
- ) -> Option<Hit>;
-
- /// Draws the given [`Text`].
- fn fill_text(&mut self, text: Text<'_, Self::Font>);
-}
diff --git a/native/src/widget/action.rs b/native/src/widget/action.rs
deleted file mode 100644
index 3f1b6b6c..00000000
--- a/native/src/widget/action.rs
+++ /dev/null
@@ -1,154 +0,0 @@
-use crate::widget::operation::{
- self, Focusable, Operation, Scrollable, TextInput,
-};
-use crate::widget::Id;
-
-use iced_futures::MaybeSend;
-
-use std::any::Any;
-use std::rc::Rc;
-
-/// An operation to be performed on the widget tree.
-#[allow(missing_debug_implementations)]
-pub struct Action<T>(Box<dyn Operation<T>>);
-
-impl<T> Action<T> {
- /// Creates a new [`Action`] with the given [`Operation`].
- pub fn new(operation: impl Operation<T> + 'static) -> Self {
- Self(Box::new(operation))
- }
-
- /// Maps the output of an [`Action`] using the given function.
- pub fn map<A>(
- self,
- f: impl Fn(T) -> A + 'static + MaybeSend + Sync,
- ) -> Action<A>
- where
- T: 'static,
- A: 'static,
- {
- Action(Box::new(Map {
- operation: self.0,
- f: Rc::new(f),
- }))
- }
-
- /// Consumes the [`Action`] and returns the internal [`Operation`].
- pub fn into_operation(self) -> Box<dyn Operation<T>> {
- self.0
- }
-}
-
-#[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 operation::Focusable,
- id: Option<&Id>,
- ) {
- self.operation.focusable(state, id);
- }
-
- fn scrollable(
- &mut self,
- state: &mut dyn operation::Scrollable,
- id: Option<&Id>,
- ) {
- self.operation.scrollable(state, id);
- }
-
- fn text_input(
- &mut self,
- state: &mut dyn operation::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) -> operation::Outcome<B> {
- match self.operation.finish() {
- operation::Outcome::None => operation::Outcome::None,
- operation::Outcome::Some(output) => {
- operation::Outcome::Some((self.f)(output))
- }
- operation::Outcome::Chain(next) => {
- operation::Outcome::Chain(Box::new(Map {
- operation: next,
- f: self.f.clone(),
- }))
- }
- }
- }
-}
diff --git a/native/src/widget/helpers.rs b/native/src/widget/helpers.rs
deleted file mode 100644
index 5f44e22c..00000000
--- a/native/src/widget/helpers.rs
+++ /dev/null
@@ -1,326 +0,0 @@
-//! Helper functions to create pure widgets.
-use crate::overlay;
-use crate::widget;
-use crate::{Element, Length, Pixels};
-
-use std::borrow::Cow;
-use std::ops::RangeInclusive;
-
-/// Creates a [`Column`] with the given children.
-///
-/// [`Column`]: widget::Column
-#[macro_export]
-macro_rules! column {
- () => (
- $crate::widget::Column::new()
- );
- ($($x:expr),+ $(,)?) => (
- $crate::widget::Column::with_children(vec![$($crate::Element::from($x)),+])
- );
-}
-
-/// Creates a [`Row`] with the given children.
-///
-/// [`Row`]: widget::Row
-#[macro_export]
-macro_rules! row {
- () => (
- $crate::widget::Row::new()
- );
- ($($x:expr),+ $(,)?) => (
- $crate::widget::Row::with_children(vec![$($crate::Element::from($x)),+])
- );
-}
-
-/// Creates a new [`Container`] with the provided content.
-///
-/// [`Container`]: widget::Container
-pub fn container<'a, Message, Renderer>(
- content: impl Into<Element<'a, Message, Renderer>>,
-) -> widget::Container<'a, Message, Renderer>
-where
- Renderer: crate::Renderer,
- Renderer::Theme: widget::container::StyleSheet,
-{
- widget::Container::new(content)
-}
-
-/// Creates a new [`Column`] with the given children.
-///
-/// [`Column`]: widget::Column
-pub fn column<Message, Renderer>(
- children: Vec<Element<'_, Message, Renderer>>,
-) -> widget::Column<'_, Message, Renderer> {
- widget::Column::with_children(children)
-}
-
-/// Creates a new [`Row`] with the given children.
-///
-/// [`Row`]: widget::Row
-pub fn row<Message, Renderer>(
- children: Vec<Element<'_, Message, Renderer>>,
-) -> widget::Row<'_, Message, Renderer> {
- widget::Row::with_children(children)
-}
-
-/// Creates a new [`Scrollable`] with the provided content.
-///
-/// [`Scrollable`]: widget::Scrollable
-pub fn scrollable<'a, Message, Renderer>(
- content: impl Into<Element<'a, Message, Renderer>>,
-) -> widget::Scrollable<'a, Message, Renderer>
-where
- Renderer: crate::Renderer,
- Renderer::Theme: widget::scrollable::StyleSheet,
-{
- widget::Scrollable::new(content)
-}
-
-/// Creates a new [`Button`] with the provided content.
-///
-/// [`Button`]: widget::Button
-pub fn button<'a, Message, Renderer>(
- content: impl Into<Element<'a, Message, Renderer>>,
-) -> widget::Button<'a, Message, Renderer>
-where
- Renderer: crate::Renderer,
- Renderer::Theme: widget::button::StyleSheet,
- <Renderer::Theme as widget::button::StyleSheet>::Style: Default,
-{
- widget::Button::new(content)
-}
-
-/// Creates a new [`Tooltip`] with the provided content, tooltip text, and [`tooltip::Position`].
-///
-/// [`Tooltip`]: widget::Tooltip
-/// [`tooltip::Position`]: widget::tooltip::Position
-pub fn tooltip<'a, Message, Renderer>(
- content: impl Into<Element<'a, Message, Renderer>>,
- tooltip: impl ToString,
- position: widget::tooltip::Position,
-) -> widget::Tooltip<'a, Message, Renderer>
-where
- Renderer: crate::text::Renderer,
- Renderer::Theme: widget::container::StyleSheet + widget::text::StyleSheet,
-{
- widget::Tooltip::new(content, tooltip.to_string(), position)
-}
-
-/// Creates a new [`Text`] widget with the provided content.
-///
-/// [`Text`]: widget::Text
-pub fn text<'a, Renderer>(text: impl ToString) -> widget::Text<'a, Renderer>
-where
- Renderer: crate::text::Renderer,
- Renderer::Theme: widget::text::StyleSheet,
-{
- widget::Text::new(text.to_string())
-}
-
-/// Creates a new [`Checkbox`].
-///
-/// [`Checkbox`]: widget::Checkbox
-pub fn checkbox<'a, Message, Renderer>(
- label: impl Into<String>,
- is_checked: bool,
- f: impl Fn(bool) -> Message + 'a,
-) -> widget::Checkbox<'a, Message, Renderer>
-where
- Renderer: crate::text::Renderer,
- Renderer::Theme: widget::checkbox::StyleSheet + widget::text::StyleSheet,
-{
- widget::Checkbox::new(label, is_checked, f)
-}
-
-/// Creates a new [`Radio`].
-///
-/// [`Radio`]: widget::Radio
-pub fn radio<Message, Renderer, V>(
- label: impl Into<String>,
- value: V,
- selected: Option<V>,
- on_click: impl FnOnce(V) -> Message,
-) -> widget::Radio<Message, Renderer>
-where
- Message: Clone,
- Renderer: crate::text::Renderer,
- Renderer::Theme: widget::radio::StyleSheet,
- V: Copy + Eq,
-{
- widget::Radio::new(label, value, selected, on_click)
-}
-
-/// Creates a new [`Toggler`].
-///
-/// [`Toggler`]: widget::Toggler
-pub fn toggler<'a, Message, Renderer>(
- label: impl Into<Option<String>>,
- is_checked: bool,
- f: impl Fn(bool) -> Message + 'a,
-) -> widget::Toggler<'a, Message, Renderer>
-where
- Renderer: crate::text::Renderer,
- Renderer::Theme: widget::toggler::StyleSheet,
-{
- widget::Toggler::new(label, is_checked, f)
-}
-
-/// Creates a new [`TextInput`].
-///
-/// [`TextInput`]: widget::TextInput
-pub fn text_input<'a, Message, Renderer>(
- placeholder: &str,
- value: &str,
-) -> widget::TextInput<'a, Message, Renderer>
-where
- Message: Clone,
- Renderer: crate::text::Renderer,
- Renderer::Theme: widget::text_input::StyleSheet,
-{
- widget::TextInput::new(placeholder, value)
-}
-
-/// Creates a new [`Slider`].
-///
-/// [`Slider`]: widget::Slider
-pub fn slider<'a, T, Message, Renderer>(
- range: std::ops::RangeInclusive<T>,
- value: T,
- on_change: impl Fn(T) -> Message + 'a,
-) -> widget::Slider<'a, T, Message, Renderer>
-where
- T: Copy + From<u8> + std::cmp::PartialOrd,
- Message: Clone,
- Renderer: crate::Renderer,
- Renderer::Theme: widget::slider::StyleSheet,
-{
- widget::Slider::new(range, value, on_change)
-}
-
-/// Creates a new [`VerticalSlider`].
-///
-/// [`VerticalSlider`]: widget::VerticalSlider
-pub fn vertical_slider<'a, T, Message, Renderer>(
- range: std::ops::RangeInclusive<T>,
- value: T,
- on_change: impl Fn(T) -> Message + 'a,
-) -> widget::VerticalSlider<'a, T, Message, Renderer>
-where
- T: Copy + From<u8> + std::cmp::PartialOrd,
- Message: Clone,
- Renderer: crate::Renderer,
- Renderer::Theme: widget::slider::StyleSheet,
-{
- widget::VerticalSlider::new(range, value, on_change)
-}
-
-/// Creates a new [`PickList`].
-///
-/// [`PickList`]: widget::PickList
-pub fn pick_list<'a, Message, Renderer, T>(
- options: impl Into<Cow<'a, [T]>>,
- selected: Option<T>,
- on_selected: impl Fn(T) -> Message + 'a,
-) -> widget::PickList<'a, T, Message, Renderer>
-where
- T: ToString + Eq + 'static,
- [T]: ToOwned<Owned = Vec<T>>,
- Renderer: crate::text::Renderer,
- Renderer::Theme: widget::pick_list::StyleSheet
- + widget::scrollable::StyleSheet
- + overlay::menu::StyleSheet
- + widget::container::StyleSheet,
- <Renderer::Theme as overlay::menu::StyleSheet>::Style:
- From<<Renderer::Theme as widget::pick_list::StyleSheet>::Style>,
-{
- widget::PickList::new(options, selected, on_selected)
-}
-
-/// Creates a new [`Image`].
-///
-/// [`Image`]: widget::Image
-pub fn image<Handle>(handle: impl Into<Handle>) -> widget::Image<Handle> {
- widget::Image::new(handle.into())
-}
-
-/// Creates a new horizontal [`Space`] with the given [`Length`].
-///
-/// [`Space`]: widget::Space
-pub fn horizontal_space(width: impl Into<Length>) -> widget::Space {
- widget::Space::with_width(width)
-}
-
-/// Creates a new vertical [`Space`] with the given [`Length`].
-///
-/// [`Space`]: widget::Space
-pub fn vertical_space(height: impl Into<Length>) -> widget::Space {
- widget::Space::with_height(height)
-}
-
-/// Creates a horizontal [`Rule`] with the given height.
-///
-/// [`Rule`]: widget::Rule
-pub fn horizontal_rule<Renderer>(
- height: impl Into<Pixels>,
-) -> widget::Rule<Renderer>
-where
- Renderer: crate::Renderer,
- Renderer::Theme: widget::rule::StyleSheet,
-{
- widget::Rule::horizontal(height)
-}
-
-/// Creates a vertical [`Rule`] with the given width.
-///
-/// [`Rule`]: widget::Rule
-pub fn vertical_rule<Renderer>(
- width: impl Into<Pixels>,
-) -> widget::Rule<Renderer>
-where
- Renderer: crate::Renderer,
- Renderer::Theme: widget::rule::StyleSheet,
-{
- widget::Rule::vertical(width)
-}
-
-/// Creates a new [`ProgressBar`].
-///
-/// It expects:
-/// * an inclusive range of possible values, and
-/// * the current value of the [`ProgressBar`].
-///
-/// [`ProgressBar`]: widget::ProgressBar
-pub fn progress_bar<Renderer>(
- range: RangeInclusive<f32>,
- value: f32,
-) -> widget::ProgressBar<Renderer>
-where
- Renderer: crate::Renderer,
- Renderer::Theme: widget::progress_bar::StyleSheet,
-{
- widget::ProgressBar::new(range, value)
-}
-
-/// Creates a new [`Svg`] widget from the given [`Handle`].
-///
-/// [`Svg`]: widget::Svg
-/// [`Handle`]: widget::svg::Handle
-pub fn svg<Renderer>(
- handle: impl Into<widget::svg::Handle>,
-) -> widget::Svg<Renderer>
-where
- Renderer: crate::svg::Renderer,
- Renderer::Theme: widget::svg::StyleSheet,
-{
- widget::Svg::new(handle)
-}
-
-/// A container intercepting mouse events.
-pub fn mouse_area<'a, Message, Renderer>(
- widget: impl Into<Element<'a, Message, Renderer>>,
-) -> widget::MouseArea<'a, Message, Renderer>
-where
- Renderer: crate::Renderer,
-{
- widget::MouseArea::new(widget)
-}
diff --git a/native/src/widget/operation.rs b/native/src/widget/operation.rs
deleted file mode 100644
index 53688a21..00000000
--- a/native/src/widget/operation.rs
+++ /dev/null
@@ -1,112 +0,0 @@
-//! 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;
-
-/// 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(...)"),
- }
- }
-}
-
-/// Produces an [`Operation`] that applies the given [`Operation`] to the
-/// children of a container with the given [`Id`].
-pub fn scoped<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/window.rs b/native/src/window.rs
deleted file mode 100644
index 1ae89dba..00000000
--- a/native/src/window.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-//! Build window-based GUI applications.
-mod action;
-mod event;
-mod mode;
-mod redraw_request;
-mod user_attention;
-
-pub mod icon;
-
-pub use action::Action;
-pub use event::Event;
-pub use icon::Icon;
-pub use mode::Mode;
-pub use redraw_request::RedrawRequest;
-pub use user_attention::UserAttention;
-
-use crate::subscription::{self, Subscription};
-use crate::time::Instant;
-
-/// Subscribes to the frames of the window of the running application.
-///
-/// The resulting [`Subscription`] will produce items at a rate equal to the
-/// refresh rate of the window. Note that this rate may be variable, as it is
-/// normally managed by the graphics driver and/or the OS.
-///
-/// In any case, this [`Subscription`] is useful to smoothly draw application-driven
-/// animations without missing any frames.
-pub fn frames() -> Subscription<Instant> {
- subscription::raw_events(|event, _status| match event {
- crate::Event::Window(Event::RedrawRequested(at)) => Some(at),
- _ => None,
- })
-}
diff --git a/native/src/clipboard.rs b/runtime/src/clipboard.rs
index c9105bc0..bc450912 100644
--- a/native/src/clipboard.rs
+++ b/runtime/src/clipboard.rs
@@ -1,30 +1,9 @@
//! Access the clipboard.
-use iced_futures::MaybeSend;
+use crate::command::{self, Command};
+use crate::futures::MaybeSend;
use std::fmt;
-/// 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) {}
-}
-
/// A clipboard action to be performed by some [`Command`].
///
/// [`Command`]: crate::Command
@@ -60,3 +39,15 @@ impl<T> fmt::Debug for Action<T> {
}
}
}
+
+/// Read the current contents of the clipboard.
+pub fn read<Message>(
+ f: impl Fn(Option<String>) -> Message + 'static,
+) -> Command<Message> {
+ Command::single(command::Action::Clipboard(Action::Read(Box::new(f))))
+}
+
+/// Write the given contents to the clipboard.
+pub fn write<Message>(contents: String) -> Command<Message> {
+ Command::single(command::Action::Clipboard(Action::Write(contents)))
+}
diff --git a/native/src/command.rs b/runtime/src/command.rs
index ca9d0b64..cd4c51ff 100644
--- a/native/src/command.rs
+++ b/runtime/src/command.rs
@@ -3,35 +3,39 @@ mod action;
pub use action::Action;
-use crate::widget;
-
-use iced_futures::MaybeSend;
+use crate::core::widget;
+use crate::futures::MaybeSend;
use std::fmt;
use std::future::Future;
/// A set of asynchronous actions to be performed by some runtime.
#[must_use = "`Command` must be returned to runtime to take effect"]
-pub struct Command<T>(iced_futures::Command<Action<T>>);
+pub struct Command<T>(Internal<Action<T>>);
+
+#[derive(Debug)]
+enum Internal<T> {
+ None,
+ Single(T),
+ Batch(Vec<T>),
+}
impl<T> Command<T> {
/// Creates an empty [`Command`].
///
/// In other words, a [`Command`] that does nothing.
pub const fn none() -> Self {
- Self(iced_futures::Command::none())
+ Self(Internal::None)
}
/// Creates a [`Command`] that performs a single [`Action`].
pub const fn single(action: Action<T>) -> Self {
- Self(iced_futures::Command::single(action))
+ Self(Internal::Single(action))
}
/// Creates a [`Command`] that performs a [`widget::Operation`].
pub fn widget(operation: impl widget::Operation<T> + 'static) -> Self {
- Self(iced_futures::Command::single(Action::Widget(
- widget::Action::new(operation),
- )))
+ Self::single(Action::Widget(Box::new(operation)))
}
/// Creates a [`Command`] that performs the action of the given future.
@@ -49,9 +53,17 @@ impl<T> Command<T> {
///
/// Once this command is run, all the commands will be executed at once.
pub fn batch(commands: impl IntoIterator<Item = Command<T>>) -> Self {
- Self(iced_futures::Command::batch(
- commands.into_iter().map(|Command(command)| command),
- ))
+ let mut batch = Vec::new();
+
+ for Command(command) in commands {
+ match command {
+ Internal::None => {}
+ Internal::Single(command) => batch.push(command),
+ Internal::Batch(commands) => batch.extend(commands),
+ }
+ }
+
+ Self(Internal::Batch(batch))
}
/// Applies a transformation to the result of a [`Command`].
@@ -63,16 +75,27 @@ impl<T> Command<T> {
T: 'static,
A: 'static,
{
- let Command(command) = self;
-
- Command(command.map(move |action| action.map(f.clone())))
+ match self.0 {
+ Internal::None => Command::none(),
+ Internal::Single(action) => Command::single(action.map(f)),
+ Internal::Batch(batch) => Command(Internal::Batch(
+ batch
+ .into_iter()
+ .map(|action| action.map(f.clone()))
+ .collect(),
+ )),
+ }
}
/// Returns all of the actions of the [`Command`].
pub fn actions(self) -> Vec<Action<T>> {
let Command(command) = self;
- command.actions()
+ match command {
+ Internal::None => Vec::new(),
+ Internal::Single(action) => vec![action],
+ Internal::Batch(batch) => batch,
+ }
}
}
diff --git a/native/src/command/action.rs b/runtime/src/command/action.rs
index a51b8c21..6c74f0ef 100644
--- a/native/src/command/action.rs
+++ b/runtime/src/command/action.rs
@@ -1,10 +1,12 @@
use crate::clipboard;
+use crate::core::widget;
+use crate::font;
use crate::system;
-use crate::widget;
use crate::window;
use iced_futures::MaybeSend;
+use std::borrow::Cow;
use std::fmt;
/// An action that a [`Command`] can perform.
@@ -26,7 +28,16 @@ pub enum Action<T> {
System(system::Action<T>),
/// Run a widget action.
- Widget(widget::Action<T>),
+ Widget(Box<dyn widget::Operation<T>>),
+
+ /// Load a font from its bytes.
+ LoadFont {
+ /// The bytes of the font to load.
+ bytes: Cow<'static, [u8]>,
+
+ /// The message to produce when the font has been loaded.
+ tagger: Box<dyn Fn(Result<(), font::Error>) -> T>,
+ },
}
impl<T> Action<T> {
@@ -48,7 +59,13 @@ impl<T> Action<T> {
Self::Clipboard(action) => Action::Clipboard(action.map(f)),
Self::Window(window) => Action::Window(window.map(f)),
Self::System(system) => Action::System(system.map(f)),
- Self::Widget(widget) => Action::Widget(widget.map(f)),
+ Self::Widget(operation) => {
+ Action::Widget(Box::new(widget::operation::map(operation, f)))
+ }
+ Self::LoadFont { bytes, tagger } => Action::LoadFont {
+ bytes,
+ tagger: Box::new(move |result| f(tagger(result))),
+ },
}
}
}
@@ -63,6 +80,7 @@ impl<T> fmt::Debug for Action<T> {
Self::Window(action) => write!(f, "Action::Window({action:?})"),
Self::System(action) => write!(f, "Action::System({action:?})"),
Self::Widget(_action) => write!(f, "Action::Widget"),
+ Self::LoadFont { .. } => write!(f, "Action::LoadFont"),
}
}
}
diff --git a/native/src/debug/basic.rs b/runtime/src/debug/basic.rs
index 92f614da..32f725a1 100644
--- a/native/src/debug/basic.rs
+++ b/runtime/src/debug/basic.rs
@@ -1,5 +1,5 @@
#![allow(missing_docs)]
-use crate::time;
+use crate::core::time;
use std::collections::VecDeque;
diff --git a/native/src/debug/null.rs b/runtime/src/debug/null.rs
index 2db0eebb..2db0eebb 100644
--- a/native/src/debug/null.rs
+++ b/runtime/src/debug/null.rs
diff --git a/native/src/keyboard.rs b/runtime/src/keyboard.rs
index 012538e3..012538e3 100644
--- a/native/src/keyboard.rs
+++ b/runtime/src/keyboard.rs
diff --git a/native/src/lib.rs b/runtime/src/lib.rs
index dc77950c..d3b84c7d 100644
--- a/native/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -42,32 +42,16 @@
clippy::useless_conversion
)]
#![forbid(unsafe_code, rust_2018_idioms)]
-#![allow(clippy::inherent_to_string, clippy::type_complexity)]
#![cfg_attr(docsrs, feature(doc_cfg))]
pub mod clipboard;
pub mod command;
-pub mod event;
-pub mod image;
+pub mod font;
pub mod keyboard;
-pub mod layout;
-pub mod mouse;
-pub mod overlay;
pub mod program;
-pub mod renderer;
-pub mod subscription;
-pub mod svg;
pub mod system;
-pub mod text;
-pub mod touch;
pub mod user_interface;
-pub mod widget;
pub mod window;
-mod element;
-mod hasher;
-mod runtime;
-mod shell;
-
// We disable debug capabilities on release builds unless the `debug` feature
// is explicitly enabled.
#[cfg(feature = "debug")]
@@ -77,32 +61,11 @@ mod debug;
#[path = "debug/null.rs"]
mod debug;
-pub use iced_core::alignment;
-pub use iced_core::time;
-pub use iced_core::{
- color, Alignment, Background, Color, ContentFit, Font, Length, Padding,
- Pixels, Point, Rectangle, Size, Vector,
-};
-pub use iced_futures::{executor, futures};
-pub use iced_style::application;
-pub use iced_style::theme;
-
-#[doc(no_inline)]
-pub use executor::Executor;
+pub use iced_core as core;
+pub use iced_futures as futures;
-pub use clipboard::Clipboard;
pub use command::Command;
pub use debug::Debug;
-pub use element::Element;
-pub use event::Event;
-pub use hasher::Hasher;
-pub use layout::Layout;
-pub use overlay::Overlay;
+pub use font::Font;
pub use program::Program;
-pub use renderer::Renderer;
-pub use runtime::Runtime;
-pub use shell::Shell;
-pub use subscription::Subscription;
-pub use theme::Theme;
pub use user_interface::UserInterface;
-pub use widget::Widget;
diff --git a/native/src/program.rs b/runtime/src/program.rs
index c71c237f..44585cc5 100644
--- a/native/src/program.rs
+++ b/runtime/src/program.rs
@@ -1,5 +1,8 @@
//! Build interactive programs using The Elm Architecture.
-use crate::{Command, Element, Renderer};
+use crate::Command;
+
+use iced_core::text;
+use iced_core::{Element, Renderer};
mod state;
@@ -8,7 +11,7 @@ pub use state::State;
/// The core of a user interface application following The Elm Architecture.
pub trait Program: Sized {
/// The graphics backend to use to draw the [`Program`].
- type Renderer: Renderer;
+ type Renderer: Renderer + text::Renderer;
/// The type of __messages__ your [`Program`] will produce.
type Message: std::fmt::Debug + Send;
diff --git a/native/src/program/state.rs b/runtime/src/program/state.rs
index 8ae1cacb..2fa9934d 100644
--- a/native/src/program/state.rs
+++ b/runtime/src/program/state.rs
@@ -1,9 +1,9 @@
-use crate::application;
-use crate::event::{self, Event};
-use crate::mouse;
-use crate::renderer;
+use crate::core::event::{self, Event};
+use crate::core::mouse;
+use crate::core::renderer;
+use crate::core::{Clipboard, Point, Size};
use crate::user_interface::{self, UserInterface};
-use crate::{Clipboard, Command, Debug, Point, Program, Size};
+use crate::{Command, Debug, Program};
/// The execution state of a [`Program`]. It leverages caching, event
/// processing, and rendering primitive storage.
@@ -22,7 +22,6 @@ where
impl<P> State<P>
where
P: Program + 'static,
- <P::Renderer as crate::Renderer>::Theme: application::StyleSheet,
{
/// Creates a new [`State`] with the provided [`Program`], initializing its
/// primitive with the given logical bounds and renderer.
@@ -91,7 +90,7 @@ where
bounds: Size,
cursor_position: Point,
renderer: &mut P::Renderer,
- theme: &<P::Renderer as crate::Renderer>::Theme,
+ theme: &<P::Renderer as iced_core::Renderer>::Theme,
style: &renderer::Style,
clipboard: &mut dyn Clipboard,
debug: &mut Debug,
@@ -182,10 +181,7 @@ fn build_user_interface<'a, P: Program>(
renderer: &mut P::Renderer,
size: Size,
debug: &mut Debug,
-) -> UserInterface<'a, P::Message, P::Renderer>
-where
- <P::Renderer as crate::Renderer>::Theme: application::StyleSheet,
-{
+) -> UserInterface<'a, P::Message, P::Renderer> {
debug.view_started();
let view = program.view();
debug.view_finished();
diff --git a/native/src/system.rs b/runtime/src/system.rs
index 61c8ff29..61c8ff29 100644
--- a/native/src/system.rs
+++ b/runtime/src/system.rs
diff --git a/native/src/system/action.rs b/runtime/src/system/action.rs
index dea9536f..dea9536f 100644
--- a/native/src/system/action.rs
+++ b/runtime/src/system/action.rs
diff --git a/native/src/system/information.rs b/runtime/src/system/information.rs
index 93e7a5a4..93e7a5a4 100644
--- a/native/src/system/information.rs
+++ b/runtime/src/system/information.rs
diff --git a/native/src/user_interface.rs b/runtime/src/user_interface.rs
index e5c90bbb..d9206134 100644
--- a/native/src/user_interface.rs
+++ b/runtime/src/user_interface.rs
@@ -1,14 +1,12 @@
//! Implement your own event loop to drive a user interface.
-use crate::application;
-use crate::event::{self, Event};
-use crate::layout;
-use crate::mouse;
-use crate::renderer;
-use crate::widget;
-use crate::window;
-use crate::{
- Clipboard, Element, Layout, Point, Rectangle, Shell, Size, Vector,
-};
+use crate::core::event::{self, Event};
+use crate::core::layout;
+use crate::core::mouse;
+use crate::core::renderer;
+use crate::core::widget;
+use crate::core::window;
+use crate::core::{Clipboard, Point, Rectangle, Size, Vector};
+use crate::core::{Element, Layout, Shell};
/// A set of interactive graphical elements with a specific [`Layout`].
///
@@ -18,11 +16,10 @@ use crate::{
/// charge of using this type in your system in any way you want.
///
/// # Example
-/// The [`integration_opengl`] & [`integration_wgpu`] examples use a
-/// [`UserInterface`] to integrate Iced in an existing graphical application.
+/// The [`integration`] example uses a [`UserInterface`] to integrate Iced in an
+/// existing graphical application.
///
-/// [`integration_opengl`]: https://github.com/iced-rs/iced/tree/0.9/examples/integration_opengl
-/// [`integration_wgpu`]: https://github.com/iced-rs/iced/tree/0.9/examples/integration_wgpu
+/// [`integration`]: https://github.com/iced-rs/iced/tree/0.9/examples/integration
#[allow(missing_debug_implementations)]
pub struct UserInterface<'a, Message, Renderer> {
root: Element<'a, Message, Renderer>,
@@ -34,8 +31,7 @@ pub struct UserInterface<'a, Message, Renderer> {
impl<'a, Message, Renderer> UserInterface<'a, Message, Renderer>
where
- Renderer: crate::Renderer,
- Renderer::Theme: application::StyleSheet,
+ Renderer: crate::core::Renderer,
{
/// Builds a user interface for an [`Element`].
///
@@ -48,24 +44,21 @@ where
/// is naive way to set up our application loop:
///
/// ```no_run
- /// use iced_native::Size;
- /// use iced_native::user_interface::{self, UserInterface};
- /// use iced_wgpu::Renderer;
- ///
/// # mod iced_wgpu {
- /// # pub use iced_native::renderer::Null as Renderer;
+ /// # pub use iced_runtime::core::renderer::Null as Renderer;
/// # }
/// #
- /// # use iced_native::widget::Column;
- /// #
/// # pub struct Counter;
/// #
/// # impl Counter {
/// # pub fn new() -> Self { Counter }
- /// # pub fn view(&self) -> Column<(), Renderer> {
- /// # Column::new()
- /// # }
+ /// # pub fn view(&self) -> iced_core::Element<(), Renderer> { unimplemented!() }
+ /// # pub fn update(&mut self, _: ()) {}
/// # }
+ /// use iced_runtime::core::Size;
+ /// use iced_runtime::user_interface::{self, UserInterface};
+ /// use iced_wgpu::Renderer;
+ ///
/// // Initialization
/// let mut counter = Counter::new();
/// let mut cache = user_interface::Cache::new();
@@ -124,25 +117,21 @@ where
/// completing [the previous example](#example):
///
/// ```no_run
- /// use iced_native::{clipboard, Size, Point};
- /// use iced_native::user_interface::{self, UserInterface};
- /// use iced_wgpu::Renderer;
- ///
/// # mod iced_wgpu {
- /// # pub use iced_native::renderer::Null as Renderer;
+ /// # pub use iced_runtime::core::renderer::Null as Renderer;
/// # }
/// #
- /// # use iced_native::widget::Column;
- /// #
/// # pub struct Counter;
/// #
/// # impl Counter {
/// # pub fn new() -> Self { Counter }
- /// # pub fn view(&self) -> Column<(), Renderer> {
- /// # Column::new()
- /// # }
- /// # pub fn update(&mut self, message: ()) {}
+ /// # pub fn view(&self) -> iced_core::Element<(), Renderer> { unimplemented!() }
+ /// # pub fn update(&mut self, _: ()) {}
/// # }
+ /// use iced_runtime::core::{clipboard, Size, Point};
+ /// use iced_runtime::user_interface::{self, UserInterface};
+ /// use iced_wgpu::Renderer;
+ ///
/// let mut counter = Counter::new();
/// let mut cache = user_interface::Cache::new();
/// let mut renderer = Renderer::new();
@@ -357,27 +346,24 @@ where
/// [completing the last example](#example-1):
///
/// ```no_run
- /// use iced_native::clipboard;
- /// use iced_native::renderer;
- /// use iced_native::user_interface::{self, UserInterface};
- /// use iced_native::{Size, Point, Theme};
- /// use iced_wgpu::Renderer;
- ///
/// # mod iced_wgpu {
- /// # pub use iced_native::renderer::Null as Renderer;
+ /// # pub use iced_runtime::core::renderer::Null as Renderer;
+ /// # pub type Theme = ();
/// # }
/// #
- /// # use iced_native::widget::Column;
- /// #
/// # pub struct Counter;
/// #
/// # impl Counter {
/// # pub fn new() -> Self { Counter }
- /// # pub fn view(&self) -> Column<(), Renderer> {
- /// # Column::new()
- /// # }
- /// # pub fn update(&mut self, message: ()) {}
+ /// # pub fn view(&self) -> Element<(), Renderer> { unimplemented!() }
+ /// # pub fn update(&mut self, _: ()) {}
/// # }
+ /// use iced_runtime::core::clipboard;
+ /// use iced_runtime::core::renderer;
+ /// use iced_runtime::core::{Element, Size, Point};
+ /// use iced_runtime::user_interface::{self, UserInterface};
+ /// use iced_wgpu::{Renderer, Theme};
+ ///
/// let mut counter = Counter::new();
/// let mut cache = user_interface::Cache::new();
/// let mut renderer = Renderer::new();
@@ -386,6 +372,7 @@ where
/// let mut clipboard = clipboard::Null;
/// let mut events = Vec::new();
/// let mut messages = Vec::new();
+ /// let mut theme = Theme::default();
///
/// loop {
/// // Obtain system events...
@@ -407,7 +394,7 @@ where
/// );
///
/// // Draw the user interface
- /// let mouse_cursor = user_interface.draw(&mut renderer, &Theme::default(), &renderer::Style::default(), cursor_position);
+ /// let mouse_cursor = user_interface.draw(&mut renderer, &theme, &renderer::Style::default(), cursor_position);
///
/// cache = user_interface.into_cache();
///
diff --git a/native/src/window/action.rs b/runtime/src/window/action.rs
index 095a8eec..83b71c75 100644
--- a/native/src/window/action.rs
+++ b/runtime/src/window/action.rs
@@ -1,6 +1,6 @@
-use crate::window::{Icon, Mode, UserAttention};
+use crate::core::window::{Icon, Mode, UserAttention};
+use crate::futures::MaybeSend;
-use iced_futures::MaybeSend;
use std::fmt;
/// An operation to be performed on some window.
diff --git a/native/src/widget/button.rs b/widget/src/button.rs
index 39387173..7eee69cb 100644
--- a/native/src/widget/button.rs
+++ b/widget/src/button.rs
@@ -1,15 +1,15 @@
//! Allow your users to perform actions by pressing a button.
//!
//! A [`Button`] has some local [`State`].
-use crate::event::{self, Event};
-use crate::layout;
-use crate::mouse;
-use crate::overlay;
-use crate::renderer;
-use crate::touch;
-use crate::widget::tree::{self, Tree};
-use crate::widget::Operation;
-use crate::{
+use crate::core::event::{self, Event};
+use crate::core::layout;
+use crate::core::mouse;
+use crate::core::overlay;
+use crate::core::renderer;
+use crate::core::touch;
+use crate::core::widget::tree::{self, Tree};
+use crate::core::widget::Operation;
+use crate::core::{
Background, Clipboard, Color, Element, Layout, Length, Padding, Point,
Rectangle, Shell, Vector, Widget,
};
@@ -18,9 +18,9 @@ pub use iced_style::button::{Appearance, StyleSheet};
/// A generic widget that produces a message when pressed.
///
-/// ```
+/// ```no_run
/// # type Button<'a, Message> =
-/// # iced_native::widget::Button<'a, Message, iced_native::renderer::Null>;
+/// # iced_widget::Button<'a, Message, iced_widget::renderer::Renderer<iced_widget::style::Theme>>;
/// #
/// #[derive(Clone)]
/// enum Message {
@@ -35,7 +35,7 @@ pub use iced_style::button::{Appearance, StyleSheet};
///
/// ```
/// # type Button<'a, Message> =
-/// # iced_native::widget::Button<'a, Message, iced_native::renderer::Null>;
+/// # iced_widget::Button<'a, Message, iced_widget::renderer::Renderer<iced_widget::style::Theme>>;
/// #
/// #[derive(Clone)]
/// enum Message {
@@ -51,9 +51,9 @@ pub use iced_style::button::{Appearance, StyleSheet};
/// }
/// ```
#[allow(missing_debug_implementations)]
-pub struct Button<'a, Message, Renderer>
+pub struct Button<'a, Message, Renderer = crate::Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
content: Element<'a, Message, Renderer>,
@@ -66,7 +66,7 @@ where
impl<'a, Message, Renderer> Button<'a, Message, Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
/// Creates a new [`Button`] with the given content.
@@ -121,7 +121,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>
for Button<'a, Message, Renderer>
where
Message: 'a + Clone,
- Renderer: 'a + crate::Renderer,
+ Renderer: 'a + crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
fn tag(&self) -> tree::Tag {
@@ -279,7 +279,7 @@ impl<'a, Message, Renderer> From<Button<'a, Message, Renderer>>
for Element<'a, Message, Renderer>
where
Message: Clone + 'a,
- Renderer: crate::Renderer + 'a,
+ Renderer: crate::core::Renderer + 'a,
Renderer::Theme: StyleSheet,
{
fn from(button: Button<'a, Message, Renderer>) -> Self {
@@ -355,7 +355,7 @@ pub fn update<'a, Message: Clone>(
}
/// Draws a [`Button`].
-pub fn draw<'a, Renderer: crate::Renderer>(
+pub fn draw<'a, Renderer: crate::core::Renderer>(
renderer: &mut Renderer,
bounds: Rectangle,
cursor_position: Point,
diff --git a/native/src/widget/checkbox.rs b/widget/src/checkbox.rs
index ad05a8e7..7d43bb4a 100644
--- a/native/src/widget/checkbox.rs
+++ b/widget/src/checkbox.rs
@@ -1,16 +1,17 @@
//! Show toggle controls using checkboxes.
-use crate::alignment;
-use crate::event::{self, Event};
-use crate::layout;
-use crate::mouse;
-use crate::renderer;
-use crate::text;
-use crate::touch;
-use crate::widget::{self, Row, Text, Tree};
-use crate::{
+use crate::core::alignment;
+use crate::core::event::{self, Event};
+use crate::core::layout;
+use crate::core::mouse;
+use crate::core::renderer;
+use crate::core::text;
+use crate::core::touch;
+use crate::core::widget::Tree;
+use crate::core::{
Alignment, Clipboard, Element, Layout, Length, Pixels, Point, Rectangle,
Shell, Widget,
};
+use crate::{Row, Text};
pub use iced_style::checkbox::{Appearance, StyleSheet};
@@ -18,8 +19,9 @@ pub use iced_style::checkbox::{Appearance, StyleSheet};
///
/// # Example
///
-/// ```
-/// # type Checkbox<'a, Message> = iced_native::widget::Checkbox<'a, Message, iced_native::renderer::Null>;
+/// ```no_run
+/// # type Checkbox<'a, Message> =
+/// # iced_widget::Checkbox<'a, Message, iced_widget::renderer::Renderer<iced_widget::style::Theme>>;
/// #
/// pub enum Message {
/// CheckboxToggled(bool),
@@ -32,10 +34,10 @@ pub use iced_style::checkbox::{Appearance, StyleSheet};
///
/// ![Checkbox drawn by `iced_wgpu`](https://github.com/iced-rs/iced/blob/7760618fb112074bc40b148944521f312152012a/docs/images/checkbox.png?raw=true)
#[allow(missing_debug_implementations)]
-pub struct Checkbox<'a, Message, Renderer>
+pub struct Checkbox<'a, Message, Renderer = crate::Renderer>
where
Renderer: text::Renderer,
- Renderer::Theme: StyleSheet + widget::text::StyleSheet,
+ Renderer::Theme: StyleSheet + crate::text::StyleSheet,
{
is_checked: bool,
on_toggle: Box<dyn Fn(bool) -> Message + 'a>,
@@ -44,7 +46,9 @@ where
size: f32,
spacing: f32,
text_size: Option<f32>,
- font: Renderer::Font,
+ text_line_height: text::LineHeight,
+ text_shaping: text::Shaping,
+ font: Option<Renderer::Font>,
icon: Icon<Renderer::Font>,
style: <Renderer::Theme as StyleSheet>::Style,
}
@@ -52,7 +56,7 @@ where
impl<'a, Message, Renderer> Checkbox<'a, Message, Renderer>
where
Renderer: text::Renderer,
- Renderer::Theme: StyleSheet + widget::text::StyleSheet,
+ Renderer::Theme: StyleSheet + crate::text::StyleSheet,
{
/// The default size of a [`Checkbox`].
const DEFAULT_SIZE: f32 = 20.0;
@@ -80,11 +84,15 @@ where
size: Self::DEFAULT_SIZE,
spacing: Self::DEFAULT_SPACING,
text_size: None,
- font: Renderer::Font::default(),
+ text_line_height: text::LineHeight::default(),
+ text_shaping: text::Shaping::Basic,
+ font: None,
icon: Icon {
font: Renderer::ICON_FONT,
code_point: Renderer::CHECKMARK_ICON,
size: None,
+ line_height: text::LineHeight::default(),
+ shaping: text::Shaping::Basic,
},
style: Default::default(),
}
@@ -114,11 +122,26 @@ where
self
}
+ /// Sets the text [`LineHeight`] of the [`Checkbox`].
+ pub fn text_line_height(
+ mut self,
+ line_height: impl Into<text::LineHeight>,
+ ) -> Self {
+ self.text_line_height = line_height.into();
+ self
+ }
+
+ /// Sets the [`text::Shaping`] strategy of the [`Checkbox`].
+ pub fn text_shaping(mut self, shaping: text::Shaping) -> Self {
+ self.text_shaping = shaping;
+ self
+ }
+
/// Sets the [`Font`] of the text of the [`Checkbox`].
///
/// [`Font`]: crate::text::Renderer::Font
- pub fn font(mut self, font: Renderer::Font) -> Self {
- self.font = font;
+ pub fn font(mut self, font: impl Into<Renderer::Font>) -> Self {
+ self.font = Some(font.into());
self
}
@@ -142,7 +165,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>
for Checkbox<'a, Message, Renderer>
where
Renderer: text::Renderer,
- Renderer::Theme: StyleSheet + widget::text::StyleSheet,
+ Renderer::Theme: StyleSheet + crate::text::StyleSheet,
{
fn width(&self) -> Length {
self.width
@@ -164,12 +187,14 @@ where
.push(Row::new().width(self.size).height(self.size))
.push(
Text::new(&self.label)
- .font(self.font.clone())
+ .font(self.font.unwrap_or_else(|| renderer.default_font()))
.width(self.width)
.size(
self.text_size
.unwrap_or_else(|| renderer.default_size()),
- ),
+ )
+ .line_height(self.text_line_height)
+ .shaping(self.text_shaping),
)
.layout(renderer, limits)
}
@@ -255,14 +280,17 @@ where
font,
code_point,
size,
+ line_height,
+ shaping,
} = &self.icon;
- let size = size.map(f32::from).unwrap_or(bounds.height * 0.7);
+ let size = size.unwrap_or(bounds.height * 0.7);
if self.is_checked {
renderer.fill_text(text::Text {
content: &code_point.to_string(),
- font: font.clone(),
+ font: *font,
size,
+ line_height: *line_height,
bounds: Rectangle {
x: bounds.center_x(),
y: bounds.center_y(),
@@ -271,6 +299,7 @@ where
color: custom_style.icon_color,
horizontal_alignment: alignment::Horizontal::Center,
vertical_alignment: alignment::Vertical::Center,
+ shaping: *shaping,
});
}
}
@@ -278,18 +307,20 @@ where
{
let label_layout = children.next().unwrap();
- widget::text::draw(
+ crate::text::draw(
renderer,
style,
label_layout,
&self.label,
self.text_size,
- self.font.clone(),
- widget::text::Appearance {
+ self.text_line_height,
+ self.font,
+ crate::text::Appearance {
color: custom_style.text_color,
},
alignment::Horizontal::Left,
alignment::Vertical::Center,
+ self.text_shaping,
);
}
}
@@ -300,7 +331,7 @@ impl<'a, Message, Renderer> From<Checkbox<'a, Message, Renderer>>
where
Message: 'a,
Renderer: 'a + text::Renderer,
- Renderer::Theme: StyleSheet + widget::text::StyleSheet,
+ Renderer::Theme: StyleSheet + crate::text::StyleSheet,
{
fn from(
checkbox: Checkbox<'a, Message, Renderer>,
@@ -318,4 +349,8 @@ pub struct Icon<Font> {
pub code_point: char,
/// Font size of the content.
pub size: Option<f32>,
+ /// The line height of the icon.
+ pub line_height: text::LineHeight,
+ /// The shaping strategy of the icon.
+ pub shaping: text::Shaping,
}
diff --git a/native/src/widget/column.rs b/widget/src/column.rs
index ebe579d5..8f363ec6 100644
--- a/native/src/widget/column.rs
+++ b/widget/src/column.rs
@@ -1,18 +1,18 @@
//! Distribute content vertically.
-use crate::event::{self, Event};
-use crate::layout;
-use crate::mouse;
-use crate::overlay;
-use crate::renderer;
-use crate::widget::{Operation, Tree};
-use crate::{
+use crate::core::event::{self, Event};
+use crate::core::layout;
+use crate::core::mouse;
+use crate::core::overlay;
+use crate::core::renderer;
+use crate::core::widget::{Operation, Tree};
+use crate::core::{
Alignment, Clipboard, Element, Layout, Length, Padding, Pixels, Point,
Rectangle, Shell, Widget,
};
/// A container that distributes its contents vertically.
#[allow(missing_debug_implementations)]
-pub struct Column<'a, Message, Renderer> {
+pub struct Column<'a, Message, Renderer = crate::Renderer> {
spacing: f32,
padding: Padding,
width: Length,
@@ -102,7 +102,7 @@ impl<'a, Message, Renderer> Default for Column<'a, Message, Renderer> {
impl<'a, Message, Renderer> Widget<Message, Renderer>
for Column<'a, Message, Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
{
fn children(&self) -> Vec<Tree> {
self.children.iter().map(Tree::new).collect()
@@ -256,7 +256,7 @@ impl<'a, Message, Renderer> From<Column<'a, Message, Renderer>>
for Element<'a, Message, Renderer>
where
Message: 'a,
- Renderer: crate::Renderer + 'a,
+ Renderer: crate::core::Renderer + 'a,
{
fn from(column: Column<'a, Message, Renderer>) -> Self {
Self::new(column)
diff --git a/native/src/widget/container.rs b/widget/src/container.rs
index b77bf50d..9d932772 100644
--- a/native/src/widget/container.rs
+++ b/widget/src/container.rs
@@ -1,12 +1,12 @@
//! Decorate content and apply alignment.
-use crate::alignment::{self, Alignment};
-use crate::event::{self, Event};
-use crate::layout;
-use crate::mouse;
-use crate::overlay;
-use crate::renderer;
-use crate::widget::{self, Operation, Tree};
-use crate::{
+use crate::core::alignment::{self, Alignment};
+use crate::core::event::{self, Event};
+use crate::core::layout;
+use crate::core::mouse;
+use crate::core::overlay;
+use crate::core::renderer;
+use crate::core::widget::{self, Operation, Tree};
+use crate::core::{
Background, Clipboard, Color, Element, Layout, Length, Padding, Pixels,
Point, Rectangle, Shell, Widget,
};
@@ -17,9 +17,9 @@ pub use iced_style::container::{Appearance, StyleSheet};
///
/// It is normally used for alignment purposes.
#[allow(missing_debug_implementations)]
-pub struct Container<'a, Message, Renderer>
+pub struct Container<'a, Message, Renderer = crate::Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
id: Option<Id>,
@@ -36,7 +36,7 @@ where
impl<'a, Message, Renderer> Container<'a, Message, Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
/// Creates an empty [`Container`].
@@ -131,7 +131,7 @@ where
impl<'a, Message, Renderer> Widget<Message, Renderer>
for Container<'a, Message, Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
fn children(&self) -> Vec<Tree> {
@@ -276,7 +276,7 @@ impl<'a, Message, Renderer> From<Container<'a, Message, Renderer>>
for Element<'a, Message, Renderer>
where
Message: 'a,
- Renderer: 'a + crate::Renderer,
+ Renderer: 'a + crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
fn from(
@@ -326,7 +326,7 @@ pub fn draw_background<Renderer>(
appearance: &Appearance,
bounds: Rectangle,
) where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
{
if appearance.background.is_some() || appearance.border_width > 0.0 {
renderer.fill_quad(
diff --git a/native/src/widget/image.rs b/widget/src/image.rs
index 73257a74..abcb6ef2 100644
--- a/native/src/widget/image.rs
+++ b/widget/src/image.rs
@@ -2,16 +2,18 @@
pub mod viewer;
pub use viewer::Viewer;
-use crate::image;
-use crate::layout;
-use crate::renderer;
-use crate::widget::Tree;
-use crate::{
+use crate::core::image;
+use crate::core::layout;
+use crate::core::renderer;
+use crate::core::widget::Tree;
+use crate::core::{
ContentFit, Element, Layout, Length, Point, Rectangle, Size, Vector, Widget,
};
use std::hash::Hash;
+pub use image::Handle;
+
/// Creates a new [`Viewer`] with the given image `Handle`.
pub fn viewer<Handle>(handle: Handle) -> Viewer<Handle> {
Viewer::new(handle)
@@ -21,9 +23,8 @@ pub fn viewer<Handle>(handle: Handle) -> Viewer<Handle> {
///
/// # Example
///
-/// ```
-/// # use iced_native::widget::Image;
-/// # use iced_native::image;
+/// ```no_run
+/// # use iced_widget::image::{self, Image};
/// #
/// let image = Image::<image::Handle>::new("resources/ferris.png");
/// ```
diff --git a/native/src/widget/image/viewer.rs b/widget/src/image/viewer.rs
index 1f8d5d7a..0d60d818 100644
--- a/native/src/widget/image/viewer.rs
+++ b/widget/src/image/viewer.rs
@@ -1,11 +1,11 @@
//! Zoom and pan on an image.
-use crate::event::{self, Event};
-use crate::image;
-use crate::layout;
-use crate::mouse;
-use crate::renderer;
-use crate::widget::tree::{self, Tree};
-use crate::{
+use crate::core::event::{self, Event};
+use crate::core::image;
+use crate::core::layout;
+use crate::core::mouse;
+use crate::core::renderer;
+use crate::core::widget::tree::{self, Tree};
+use crate::core::{
Clipboard, Element, Layout, Length, Pixels, Point, Rectangle, Shell, Size,
Vector, Widget,
};
diff --git a/native/src/widget/mouse_area.rs b/widget/src/mouse_area.rs
index 69cfddbf..0232c494 100644
--- a/native/src/widget/mouse_area.rs
+++ b/widget/src/mouse_area.rs
@@ -1,13 +1,13 @@
//! A container for capturing mouse events.
-use crate::event::{self, Event};
-use crate::layout;
-use crate::mouse;
-use crate::overlay;
-use crate::renderer;
-use crate::touch;
-use crate::widget::{tree, Operation, Tree};
-use crate::{
+use crate::core::event::{self, Event};
+use crate::core::layout;
+use crate::core::mouse;
+use crate::core::overlay;
+use crate::core::renderer;
+use crate::core::touch;
+use crate::core::widget::{tree, Operation, Tree};
+use crate::core::{
Clipboard, Element, Layout, Length, Point, Rectangle, Shell, Widget,
};
@@ -91,7 +91,7 @@ impl<'a, Message, Renderer> MouseArea<'a, Message, Renderer> {
impl<'a, Message, Renderer> Widget<Message, Renderer>
for MouseArea<'a, Message, Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: renderer::Renderer,
Message: Clone,
{
fn tag(&self) -> tree::Tag {
@@ -222,7 +222,7 @@ impl<'a, Message, Renderer> From<MouseArea<'a, Message, Renderer>>
for Element<'a, Message, Renderer>
where
Message: 'a + Clone,
- Renderer: 'a + crate::Renderer,
+ Renderer: 'a + renderer::Renderer,
{
fn from(
area: MouseArea<'a, Message, Renderer>,
diff --git a/native/src/overlay/menu.rs b/widget/src/overlay/menu.rs
index d93a3b56..0acc6f79 100644
--- a/native/src/overlay/menu.rs
+++ b/widget/src/overlay/menu.rs
@@ -1,25 +1,25 @@
//! Build and show dropdown menus.
-use crate::alignment;
-use crate::event::{self, Event};
-use crate::layout;
-use crate::mouse;
-use crate::overlay;
-use crate::renderer;
-use crate::text::{self, Text};
-use crate::touch;
-use crate::widget::container::{self, Container};
-use crate::widget::scrollable::{self, Scrollable};
-use crate::widget::Tree;
-use crate::{
- Clipboard, Color, Element, Layout, Length, Padding, Pixels, Point,
- Rectangle, Shell, Size, Vector, Widget,
+use crate::container::{self, Container};
+use crate::core::alignment;
+use crate::core::event::{self, Event};
+use crate::core::layout::{self, Layout};
+use crate::core::mouse;
+use crate::core::overlay;
+use crate::core::renderer;
+use crate::core::text::{self, Text};
+use crate::core::touch;
+use crate::core::widget::Tree;
+use crate::core::{
+ Clipboard, Color, Length, Padding, Pixels, Point, Rectangle, Size, Vector,
};
+use crate::core::{Element, Shell, Widget};
+use crate::scrollable::{self, Scrollable};
pub use iced_style::menu::{Appearance, StyleSheet};
/// A list of selectable options.
#[allow(missing_debug_implementations)]
-pub struct Menu<'a, T, Renderer>
+pub struct Menu<'a, T, Renderer = crate::Renderer>
where
Renderer: text::Renderer,
Renderer::Theme: StyleSheet,
@@ -31,7 +31,9 @@ where
width: f32,
padding: Padding,
text_size: Option<f32>,
- font: Renderer::Font,
+ text_line_height: text::LineHeight,
+ text_shaping: text::Shaping,
+ font: Option<Renderer::Font>,
style: <Renderer::Theme as StyleSheet>::Style,
}
@@ -58,7 +60,9 @@ where
width: 0.0,
padding: Padding::ZERO,
text_size: None,
- font: Default::default(),
+ text_line_height: text::LineHeight::default(),
+ text_shaping: text::Shaping::Basic,
+ font: None,
style: Default::default(),
}
}
@@ -81,9 +85,24 @@ where
self
}
+ /// Sets the text [`LineHeight`] of the [`Menu`].
+ pub fn text_line_height(
+ mut self,
+ line_height: impl Into<text::LineHeight>,
+ ) -> Self {
+ self.text_line_height = line_height.into();
+ self
+ }
+
+ /// Sets the [`text::Shaping`] strategy of the [`Menu`].
+ pub fn text_shaping(mut self, shaping: text::Shaping) -> Self {
+ self.text_shaping = shaping;
+ self
+ }
+
/// Sets the font of the [`Menu`].
- pub fn font(mut self, font: Renderer::Font) -> Self {
- self.font = font;
+ pub fn font(mut self, font: impl Into<Renderer::Font>) -> Self {
+ self.font = Some(font.into());
self
}
@@ -137,7 +156,7 @@ impl Default for State {
struct Overlay<'a, Message, Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet + container::StyleSheet,
{
state: &'a mut Tree,
@@ -168,6 +187,8 @@ where
padding,
font,
text_size,
+ text_line_height,
+ text_shaping,
style,
} = menu;
@@ -177,6 +198,8 @@ where
last_selection,
font,
text_size,
+ text_line_height,
+ text_shaping,
padding,
style: style.clone(),
}));
@@ -193,7 +216,7 @@ where
}
}
-impl<'a, Message, Renderer> crate::Overlay<Message, Renderer>
+impl<'a, Message, Renderer> crate::core::Overlay<Message, Renderer>
for Overlay<'a, Message, Renderer>
where
Renderer: text::Renderer,
@@ -311,7 +334,9 @@ where
last_selection: &'a mut Option<T>,
padding: Padding,
text_size: Option<f32>,
- font: Renderer::Font,
+ text_line_height: text::LineHeight,
+ text_shaping: text::Shaping,
+ font: Option<Renderer::Font>,
style: <Renderer::Theme as StyleSheet>::Style,
}
@@ -341,10 +366,13 @@ where
let text_size =
self.text_size.unwrap_or_else(|| renderer.default_size());
+ let text_line_height =
+ self.text_line_height.to_absolute(Pixels(text_size));
+
let size = {
let intrinsic = Size::new(
0.0,
- (text_size + self.padding.vertical())
+ (f32::from(text_line_height) + self.padding.vertical())
* self.options.len() as f32,
);
@@ -384,9 +412,12 @@ where
.text_size
.unwrap_or_else(|| renderer.default_size());
+ let option_height = f32::from(
+ self.text_line_height.to_absolute(Pixels(text_size)),
+ ) + self.padding.vertical();
+
*self.hovered_option = Some(
- ((cursor_position.y - bounds.y)
- / (text_size + self.padding.vertical()))
+ ((cursor_position.y - bounds.y) / option_height)
as usize,
);
}
@@ -399,9 +430,12 @@ where
.text_size
.unwrap_or_else(|| renderer.default_size());
+ let option_height = f32::from(
+ self.text_line_height.to_absolute(Pixels(text_size)),
+ ) + self.padding.vertical();
+
*self.hovered_option = Some(
- ((cursor_position.y - bounds.y)
- / (text_size + self.padding.vertical()))
+ ((cursor_position.y - bounds.y) / option_height)
as usize,
);
@@ -450,12 +484,13 @@ where
let text_size =
self.text_size.unwrap_or_else(|| renderer.default_size());
- let option_height = (text_size + self.padding.vertical()) as usize;
+ let option_height =
+ f32::from(self.text_line_height.to_absolute(Pixels(text_size)))
+ + self.padding.vertical();
let offset = viewport.y - bounds.y;
- let start = (offset / option_height as f32) as usize;
- let end =
- ((offset + viewport.height) / option_height as f32).ceil() as usize;
+ let start = (offset / option_height) as usize;
+ let end = ((offset + viewport.height) / option_height).ceil() as usize;
let visible_options = &self.options[start..end.min(self.options.len())];
@@ -465,9 +500,9 @@ where
let bounds = Rectangle {
x: bounds.x,
- y: bounds.y + (option_height * i) as f32,
+ y: bounds.y + (option_height * i as f32),
width: bounds.width,
- height: text_size + self.padding.vertical(),
+ height: option_height,
};
if is_selected {
@@ -495,7 +530,8 @@ where
..bounds
},
size: text_size,
- font: self.font.clone(),
+ line_height: self.text_line_height,
+ font: self.font.unwrap_or_else(|| renderer.default_font()),
color: if is_selected {
appearance.selected_text_color
} else {
@@ -503,6 +539,7 @@ where
},
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Center,
+ shaping: self.text_shaping,
});
}
}
diff --git a/native/src/widget/pane_grid.rs b/widget/src/pane_grid.rs
index 06ece7f4..67145e8e 100644
--- a/native/src/widget/pane_grid.rs
+++ b/widget/src/pane_grid.rs
@@ -30,18 +30,18 @@ pub use split::Split;
pub use state::State;
pub use title_bar::TitleBar;
-pub use iced_style::pane_grid::{Line, StyleSheet};
-
-use crate::event::{self, Event};
-use crate::layout;
-use crate::mouse;
-use crate::overlay::{self, Group};
-use crate::renderer;
-use crate::touch;
-use crate::widget;
-use crate::widget::container;
-use crate::widget::tree::{self, Tree};
-use crate::{
+pub use crate::style::pane_grid::{Line, StyleSheet};
+
+use crate::container;
+use crate::core::event::{self, Event};
+use crate::core::layout;
+use crate::core::mouse;
+use crate::core::overlay::{self, Group};
+use crate::core::renderer;
+use crate::core::touch;
+use crate::core::widget;
+use crate::core::widget::tree::{self, Tree};
+use crate::core::{
Clipboard, Color, Element, Layout, Length, Pixels, Point, Rectangle, Shell,
Size, Vector, Widget,
};
@@ -67,11 +67,11 @@ use crate::{
///
/// ## Example
///
-/// ```
-/// # use iced_native::widget::{pane_grid, text};
+/// ```no_run
+/// # use iced_widget::{pane_grid, text};
/// #
/// # type PaneGrid<'a, Message> =
-/// # iced_native::widget::PaneGrid<'a, Message, iced_native::renderer::Null>;
+/// # iced_widget::PaneGrid<'a, Message, iced_widget::renderer::Renderer<iced_widget::style::Theme>>;
/// #
/// enum PaneState {
/// SomePane,
@@ -96,9 +96,9 @@ use crate::{
/// .on_resize(10, Message::PaneResized);
/// ```
#[allow(missing_debug_implementations)]
-pub struct PaneGrid<'a, Message, Renderer>
+pub struct PaneGrid<'a, Message, Renderer = crate::Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet + container::StyleSheet,
{
contents: Contents<'a, Content<'a, Message, Renderer>>,
@@ -113,7 +113,7 @@ where
impl<'a, Message, Renderer> PaneGrid<'a, Message, Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet + container::StyleSheet,
{
/// Creates a [`PaneGrid`] with the given [`State`] and view function.
@@ -232,7 +232,7 @@ where
impl<'a, Message, Renderer> Widget<Message, Renderer>
for PaneGrid<'a, Message, Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet + container::StyleSheet,
{
fn tag(&self) -> tree::Tag {
@@ -468,7 +468,7 @@ impl<'a, Message, Renderer> From<PaneGrid<'a, Message, Renderer>>
for Element<'a, Message, Renderer>
where
Message: 'a,
- Renderer: 'a + crate::Renderer,
+ Renderer: 'a + crate::core::Renderer,
Renderer::Theme: StyleSheet + container::StyleSheet,
{
fn from(
@@ -755,7 +755,7 @@ pub fn draw<Renderer, T>(
&Rectangle,
),
) where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
let picked_pane = action.picked_pane();
diff --git a/native/src/widget/pane_grid/axis.rs b/widget/src/pane_grid/axis.rs
index 02bde064..a3049230 100644
--- a/native/src/widget/pane_grid/axis.rs
+++ b/widget/src/pane_grid/axis.rs
@@ -1,4 +1,4 @@
-use crate::Rectangle;
+use crate::core::Rectangle;
/// A fixed reference line for the measurement of coordinates.
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
diff --git a/native/src/widget/pane_grid/configuration.rs b/widget/src/pane_grid/configuration.rs
index 7d68fb46..ddbc3bc2 100644
--- a/native/src/widget/pane_grid/configuration.rs
+++ b/widget/src/pane_grid/configuration.rs
@@ -1,4 +1,4 @@
-use crate::widget::pane_grid::Axis;
+use crate::pane_grid::Axis;
/// The arrangement of a [`PaneGrid`].
///
diff --git a/native/src/widget/pane_grid/content.rs b/widget/src/pane_grid/content.rs
index c9b0df07..035ef05b 100644
--- a/native/src/widget/pane_grid/content.rs
+++ b/widget/src/pane_grid/content.rs
@@ -1,20 +1,20 @@
-use crate::event::{self, Event};
-use crate::layout;
-use crate::mouse;
-use crate::overlay;
-use crate::renderer;
-use crate::widget::container;
-use crate::widget::pane_grid::{Draggable, TitleBar};
-use crate::widget::{self, Tree};
-use crate::{Clipboard, Element, Layout, Point, Rectangle, Shell, Size};
+use crate::container;
+use crate::core::event::{self, Event};
+use crate::core::layout;
+use crate::core::mouse;
+use crate::core::overlay;
+use crate::core::renderer;
+use crate::core::widget::{self, Tree};
+use crate::core::{Clipboard, Element, Layout, Point, Rectangle, Shell, Size};
+use crate::pane_grid::{Draggable, TitleBar};
/// The content of a [`Pane`].
///
/// [`Pane`]: crate::widget::pane_grid::Pane
#[allow(missing_debug_implementations)]
-pub struct Content<'a, Message, Renderer>
+pub struct Content<'a, Message, Renderer = crate::Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: container::StyleSheet,
{
title_bar: Option<TitleBar<'a, Message, Renderer>>,
@@ -24,7 +24,7 @@ where
impl<'a, Message, Renderer> Content<'a, Message, Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: container::StyleSheet,
{
/// Creates a new [`Content`] with the provided body.
@@ -57,7 +57,7 @@ where
impl<'a, Message, Renderer> Content<'a, Message, Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: container::StyleSheet,
{
pub(super) fn state(&self) -> Tree {
@@ -342,7 +342,7 @@ where
impl<'a, Message, Renderer> Draggable for &Content<'a, Message, Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: container::StyleSheet,
{
fn can_be_dragged_at(
@@ -364,7 +364,7 @@ where
impl<'a, T, Message, Renderer> From<T> for Content<'a, Message, Renderer>
where
T: Into<Element<'a, Message, Renderer>>,
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: container::StyleSheet,
{
fn from(element: T) -> Self {
diff --git a/native/src/widget/pane_grid/direction.rs b/widget/src/pane_grid/direction.rs
index b31a8737..b31a8737 100644
--- a/native/src/widget/pane_grid/direction.rs
+++ b/widget/src/pane_grid/direction.rs
diff --git a/native/src/widget/pane_grid/draggable.rs b/widget/src/pane_grid/draggable.rs
index 6044871d..a9274dad 100644
--- a/native/src/widget/pane_grid/draggable.rs
+++ b/widget/src/pane_grid/draggable.rs
@@ -1,4 +1,4 @@
-use crate::{Layout, Point};
+use crate::core::{Layout, Point};
/// A pane that can be dragged.
pub trait Draggable {
diff --git a/native/src/widget/pane_grid/node.rs b/widget/src/pane_grid/node.rs
index cc304b96..3976acd8 100644
--- a/native/src/widget/pane_grid/node.rs
+++ b/widget/src/pane_grid/node.rs
@@ -1,5 +1,5 @@
-use crate::widget::pane_grid::{Axis, Pane, Split};
-use crate::{Rectangle, Size};
+use crate::core::{Rectangle, Size};
+use crate::pane_grid::{Axis, Pane, Split};
use std::collections::BTreeMap;
diff --git a/native/src/widget/pane_grid/pane.rs b/widget/src/pane_grid/pane.rs
index d6fbab83..d6fbab83 100644
--- a/native/src/widget/pane_grid/pane.rs
+++ b/widget/src/pane_grid/pane.rs
diff --git a/native/src/widget/pane_grid/split.rs b/widget/src/pane_grid/split.rs
index 8132272a..8132272a 100644
--- a/native/src/widget/pane_grid/split.rs
+++ b/widget/src/pane_grid/split.rs
diff --git a/native/src/widget/pane_grid/state.rs b/widget/src/pane_grid/state.rs
index c4ae0a0e..a6e2ec7f 100644
--- a/native/src/widget/pane_grid/state.rs
+++ b/widget/src/pane_grid/state.rs
@@ -1,10 +1,8 @@
//! The state of a [`PaneGrid`].
//!
//! [`PaneGrid`]: crate::widget::PaneGrid
-use crate::widget::pane_grid::{
- Axis, Configuration, Direction, Node, Pane, Split,
-};
-use crate::{Point, Size};
+use crate::core::{Point, Size};
+use crate::pane_grid::{Axis, Configuration, Direction, Node, Pane, Split};
use std::collections::HashMap;
diff --git a/native/src/widget/pane_grid/title_bar.rs b/widget/src/pane_grid/title_bar.rs
index 107078ef..2129937b 100644
--- a/native/src/widget/pane_grid/title_bar.rs
+++ b/widget/src/pane_grid/title_bar.rs
@@ -1,11 +1,11 @@
-use crate::event::{self, Event};
-use crate::layout;
-use crate::mouse;
-use crate::overlay;
-use crate::renderer;
-use crate::widget::container;
-use crate::widget::{self, Tree};
-use crate::{
+use crate::container;
+use crate::core::event::{self, Event};
+use crate::core::layout;
+use crate::core::mouse;
+use crate::core::overlay;
+use crate::core::renderer;
+use crate::core::widget::{self, Tree};
+use crate::core::{
Clipboard, Element, Layout, Padding, Point, Rectangle, Shell, Size,
};
@@ -13,9 +13,9 @@ use crate::{
///
/// [`Pane`]: crate::widget::pane_grid::Pane
#[allow(missing_debug_implementations)]
-pub struct TitleBar<'a, Message, Renderer>
+pub struct TitleBar<'a, Message, Renderer = crate::Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: container::StyleSheet,
{
content: Element<'a, Message, Renderer>,
@@ -27,7 +27,7 @@ where
impl<'a, Message, Renderer> TitleBar<'a, Message, Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: container::StyleSheet,
{
/// Creates a new [`TitleBar`] with the given content.
@@ -84,7 +84,7 @@ where
impl<'a, Message, Renderer> TitleBar<'a, Message, Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: container::StyleSheet,
{
pub(super) fn state(&self) -> Tree {
diff --git a/native/src/widget/pick_list.rs b/widget/src/pick_list.rs
index 17528db4..8c445dda 100644
--- a/native/src/widget/pick_list.rs
+++ b/widget/src/pick_list.rs
@@ -1,28 +1,29 @@
//! Display a dropdown list of selectable values.
-use crate::alignment;
-use crate::event::{self, Event};
-use crate::keyboard;
-use crate::layout;
-use crate::mouse;
-use crate::overlay;
-use crate::overlay::menu::{self, Menu};
-use crate::renderer;
-use crate::text::{self, Text};
-use crate::touch;
-use crate::widget::container;
-use crate::widget::scrollable;
-use crate::widget::tree::{self, Tree};
-use crate::{
+use crate::container;
+use crate::core::alignment;
+use crate::core::event::{self, Event};
+use crate::core::keyboard;
+use crate::core::layout;
+use crate::core::mouse;
+use crate::core::overlay;
+use crate::core::renderer;
+use crate::core::text::{self, Text};
+use crate::core::touch;
+use crate::core::widget::tree::{self, Tree};
+use crate::core::{
Clipboard, Element, Layout, Length, Padding, Pixels, Point, Rectangle,
Shell, Size, Widget,
};
+use crate::overlay::menu::{self, Menu};
+use crate::scrollable;
+
use std::borrow::Cow;
-pub use iced_style::pick_list::{Appearance, StyleSheet};
+pub use crate::style::pick_list::{Appearance, StyleSheet};
/// A widget for selecting a single value from a list of options.
#[allow(missing_debug_implementations)]
-pub struct PickList<'a, T, Message, Renderer>
+pub struct PickList<'a, T, Message, Renderer = crate::Renderer>
where
[T]: ToOwned<Owned = Vec<T>>,
Renderer: text::Renderer,
@@ -35,7 +36,9 @@ where
width: Length,
padding: Padding,
text_size: Option<f32>,
- font: Renderer::Font,
+ text_line_height: text::LineHeight,
+ text_shaping: text::Shaping,
+ font: Option<Renderer::Font>,
handle: Handle<Renderer::Font>,
style: <Renderer::Theme as StyleSheet>::Style,
}
@@ -70,7 +73,9 @@ where
width: Length::Shrink,
padding: Self::DEFAULT_PADDING,
text_size: None,
- font: Default::default(),
+ text_line_height: text::LineHeight::default(),
+ text_shaping: text::Shaping::Basic,
+ font: None,
handle: Default::default(),
style: Default::default(),
}
@@ -100,9 +105,24 @@ where
self
}
+ /// Sets the text [`LineHeight`] of the [`PickList`].
+ pub fn text_line_height(
+ mut self,
+ line_height: impl Into<text::LineHeight>,
+ ) -> Self {
+ self.text_line_height = line_height.into();
+ self
+ }
+
+ /// Sets the [`text::Shaping`] strategy of the [`PickList`].
+ pub fn text_shaping(mut self, shaping: text::Shaping) -> Self {
+ self.text_shaping = shaping;
+ self
+ }
+
/// Sets the font of the [`PickList`].
- pub fn font(mut self, font: Renderer::Font) -> Self {
- self.font = font;
+ pub fn font(mut self, font: impl Into<Renderer::Font>) -> Self {
+ self.font = Some(font.into());
self
}
@@ -163,7 +183,9 @@ where
self.width,
self.padding,
self.text_size,
- &self.font,
+ self.text_line_height,
+ self.text_shaping,
+ self.font,
self.placeholder.as_deref(),
&self.options,
)
@@ -212,6 +234,7 @@ where
cursor_position: Point,
_viewport: &Rectangle,
) {
+ let font = self.font.unwrap_or_else(|| renderer.default_font());
draw(
renderer,
theme,
@@ -219,7 +242,9 @@ where
cursor_position,
self.padding,
self.text_size,
- &self.font,
+ self.text_line_height,
+ self.text_shaping,
+ font,
self.placeholder.as_deref(),
self.selected.as_ref(),
&self.handle,
@@ -232,7 +257,7 @@ where
&'b mut self,
tree: &'b mut Tree,
layout: Layout<'_>,
- _renderer: &Renderer,
+ renderer: &Renderer,
) -> Option<overlay::Element<'b, Message, Renderer>> {
let state = tree.state.downcast_mut::<State<T>>();
@@ -241,7 +266,8 @@ where
state,
self.padding,
self.text_size,
- self.font.clone(),
+ self.text_shaping,
+ self.font.unwrap_or_else(|| renderer.default_font()),
&self.options,
self.style.clone(),
)
@@ -334,6 +360,10 @@ pub struct Icon<Font> {
pub code_point: char,
/// Font size of the content.
pub size: Option<f32>,
+ /// Line height of the content.
+ pub line_height: text::LineHeight,
+ /// The shaping strategy of the icon.
+ pub shaping: text::Shaping,
}
/// Computes the layout of a [`PickList`].
@@ -343,7 +373,9 @@ pub fn layout<Renderer, T>(
width: Length,
padding: Padding,
text_size: Option<f32>,
- font: &Renderer::Font,
+ text_line_height: text::LineHeight,
+ text_shaping: text::Shaping,
+ font: Option<Renderer::Font>,
placeholder: Option<&str>,
options: &[T],
) -> layout::Node
@@ -359,11 +391,11 @@ where
let max_width = match width {
Length::Shrink => {
let measure = |label: &str| -> f32 {
- let (width, _) = renderer.measure(
+ let width = renderer.measure_width(
label,
text_size,
- font.clone(),
- Size::new(f32::INFINITY, f32::INFINITY),
+ font.unwrap_or_else(|| renderer.default_font()),
+ text_shaping,
);
width.round()
@@ -383,8 +415,10 @@ where
};
let size = {
- let intrinsic =
- Size::new(max_width + text_size + padding.left, text_size);
+ let intrinsic = Size::new(
+ max_width + text_size + padding.left,
+ f32::from(text_line_height.to_absolute(Pixels(text_size))),
+ );
limits.resolve(intrinsic).pad(padding)
};
@@ -513,6 +547,7 @@ pub fn overlay<'a, T, Message, Renderer>(
state: &'a mut State<T>,
padding: Padding,
text_size: Option<f32>,
+ text_shaping: text::Shaping,
font: Renderer::Font,
options: &'a [T],
style: <Renderer::Theme as StyleSheet>::Style,
@@ -540,6 +575,7 @@ where
.width(bounds.width)
.padding(padding)
.font(font)
+ .text_shaping(text_shaping)
.style(style);
if let Some(text_size) = text_size {
@@ -560,7 +596,9 @@ pub fn draw<'a, T, Renderer>(
cursor_position: Point,
padding: Padding,
text_size: Option<f32>,
- font: &Renderer::Font,
+ text_line_height: text::LineHeight,
+ text_shaping: text::Shaping,
+ font: Renderer::Font,
placeholder: Option<&str>,
selected: Option<&T>,
handle: &Handle<Renderer::Font>,
@@ -592,40 +630,60 @@ pub fn draw<'a, T, Renderer>(
);
let handle = match handle {
- Handle::Arrow { size } => {
- Some((Renderer::ICON_FONT, Renderer::ARROW_DOWN_ICON, *size))
- }
+ Handle::Arrow { size } => Some((
+ Renderer::ICON_FONT,
+ Renderer::ARROW_DOWN_ICON,
+ *size,
+ text::LineHeight::default(),
+ text::Shaping::Basic,
+ )),
Handle::Static(Icon {
font,
code_point,
size,
- }) => Some((font.clone(), *code_point, *size)),
+ line_height,
+ shaping,
+ }) => Some((*font, *code_point, *size, *line_height, *shaping)),
Handle::Dynamic { open, closed } => {
if state().is_open {
- Some((open.font.clone(), open.code_point, open.size))
+ Some((
+ open.font,
+ open.code_point,
+ open.size,
+ open.line_height,
+ open.shaping,
+ ))
} else {
- Some((closed.font.clone(), closed.code_point, closed.size))
+ Some((
+ closed.font,
+ closed.code_point,
+ closed.size,
+ closed.line_height,
+ closed.shaping,
+ ))
}
}
Handle::None => None,
};
- if let Some((font, code_point, size)) = handle {
+ if let Some((font, code_point, size, line_height, shaping)) = handle {
let size = size.unwrap_or_else(|| renderer.default_size());
renderer.fill_text(Text {
content: &code_point.to_string(),
size,
+ line_height,
font,
color: style.handle_color,
bounds: Rectangle {
x: bounds.x + bounds.width - padding.horizontal(),
- y: bounds.center_y() - size / 2.0,
- height: size,
+ y: bounds.center_y(),
+ height: f32::from(line_height.to_absolute(Pixels(size))),
..bounds
},
horizontal_alignment: alignment::Horizontal::Right,
- vertical_alignment: alignment::Vertical::Top,
+ vertical_alignment: alignment::Vertical::Center,
+ shaping,
});
}
@@ -637,7 +695,8 @@ pub fn draw<'a, T, Renderer>(
renderer.fill_text(Text {
content: label,
size: text_size,
- font: font.clone(),
+ line_height: text_line_height,
+ font,
color: if is_selected {
style.text_color
} else {
@@ -645,12 +704,15 @@ pub fn draw<'a, T, Renderer>(
},
bounds: Rectangle {
x: bounds.x + padding.left,
- y: bounds.center_y() - text_size / 2.0,
+ y: bounds.center_y(),
width: bounds.width - padding.horizontal(),
- height: text_size,
+ height: f32::from(
+ text_line_height.to_absolute(Pixels(text_size)),
+ ),
},
horizontal_alignment: alignment::Horizontal::Left,
- vertical_alignment: alignment::Vertical::Top,
+ vertical_alignment: alignment::Vertical::Center,
+ shaping: text_shaping,
});
}
}
diff --git a/native/src/widget/progress_bar.rs b/widget/src/progress_bar.rs
index dd46fa76..ef0d87d5 100644
--- a/native/src/widget/progress_bar.rs
+++ b/widget/src/progress_bar.rs
@@ -1,8 +1,10 @@
//! Provide progress feedback to your users.
-use crate::layout;
-use crate::renderer;
-use crate::widget::Tree;
-use crate::{Color, Element, Layout, Length, Point, Rectangle, Size, Widget};
+use crate::core::layout;
+use crate::core::renderer;
+use crate::core::widget::Tree;
+use crate::core::{
+ Color, Element, Layout, Length, Point, Rectangle, Size, Widget,
+};
use std::ops::RangeInclusive;
@@ -11,8 +13,10 @@ pub use iced_style::progress_bar::{Appearance, StyleSheet};
/// A bar that displays progress.
///
/// # Example
-/// ```
-/// # type ProgressBar = iced_native::widget::ProgressBar<iced_native::renderer::Null>;
+/// ```no_run
+/// # type ProgressBar =
+/// # iced_widget::ProgressBar<iced_widget::renderer::Renderer<iced_widget::style::Theme>>;
+/// #
/// let value = 50.0;
///
/// ProgressBar::new(0.0..=100.0, value);
@@ -20,9 +24,9 @@ pub use iced_style::progress_bar::{Appearance, StyleSheet};
///
/// ![Progress bar drawn with `iced_wgpu`](https://user-images.githubusercontent.com/18618951/71662391-a316c200-2d51-11ea-9cef-52758cab85e3.png)
#[allow(missing_debug_implementations)]
-pub struct ProgressBar<Renderer>
+pub struct ProgressBar<Renderer = crate::Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
range: RangeInclusive<f32>,
@@ -34,7 +38,7 @@ where
impl<Renderer> ProgressBar<Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
/// The default height of a [`ProgressBar`].
@@ -79,7 +83,7 @@ where
impl<Message, Renderer> Widget<Message, Renderer> for ProgressBar<Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
fn width(&self) -> Length {
@@ -157,7 +161,7 @@ impl<'a, Message, Renderer> From<ProgressBar<Renderer>>
for Element<'a, Message, Renderer>
where
Message: 'a,
- Renderer: 'a + crate::Renderer,
+ Renderer: 'a + crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
fn from(
diff --git a/native/src/widget/radio.rs b/widget/src/radio.rs
index 3ca041bf..9dad1e22 100644
--- a/native/src/widget/radio.rs
+++ b/widget/src/radio.rs
@@ -1,27 +1,28 @@
//! Create choices using radio buttons.
-use crate::alignment;
-use crate::event::{self, Event};
-use crate::layout;
-use crate::mouse;
-use crate::renderer;
-use crate::text;
-use crate::touch;
-use crate::widget::{self, Row, Text, Tree};
-use crate::{
+use crate::core::alignment;
+use crate::core::event::{self, Event};
+use crate::core::layout;
+use crate::core::mouse;
+use crate::core::renderer;
+use crate::core::text;
+use crate::core::touch;
+use crate::core::widget::Tree;
+use crate::core::{
Alignment, Clipboard, Color, Element, Layout, Length, Pixels, Point,
Rectangle, Shell, Widget,
};
+use crate::{Row, Text};
pub use iced_style::radio::{Appearance, StyleSheet};
/// A circular button representing a choice.
///
/// # Example
-/// ```
+/// ```no_run
/// # type Radio<Message> =
-/// # iced_native::widget::Radio<Message, iced_native::renderer::Null>;
+/// # iced_widget::Radio<Message, iced_widget::renderer::Renderer<iced_widget::style::Theme>>;
/// #
-/// # use iced_native::column;
+/// # use iced_widget::column;
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// pub enum Choice {
/// A,
@@ -68,7 +69,7 @@ pub use iced_style::radio::{Appearance, StyleSheet};
/// let content = column![a, b, c, all];
/// ```
#[allow(missing_debug_implementations)]
-pub struct Radio<Message, Renderer>
+pub struct Radio<Message, Renderer = crate::Renderer>
where
Renderer: text::Renderer,
Renderer::Theme: StyleSheet,
@@ -80,7 +81,9 @@ where
size: f32,
spacing: f32,
text_size: Option<f32>,
- font: Renderer::Font,
+ text_line_height: text::LineHeight,
+ text_shaping: text::Shaping,
+ font: Option<Renderer::Font>,
style: <Renderer::Theme as StyleSheet>::Style,
}
@@ -122,7 +125,9 @@ where
size: Self::DEFAULT_SIZE,
spacing: Self::DEFAULT_SPACING, //15
text_size: None,
- font: Default::default(),
+ text_line_height: text::LineHeight::default(),
+ text_shaping: text::Shaping::Basic,
+ font: None,
style: Default::default(),
}
}
@@ -151,9 +156,24 @@ where
self
}
+ /// Sets the text [`LineHeight`] of the [`Radio`] button.
+ pub fn text_line_height(
+ mut self,
+ line_height: impl Into<text::LineHeight>,
+ ) -> Self {
+ self.text_line_height = line_height.into();
+ self
+ }
+
+ /// Sets the [`text::Shaping`] strategy of the [`Radio`] button.
+ pub fn text_shaping(mut self, shaping: text::Shaping) -> Self {
+ self.text_shaping = shaping;
+ self
+ }
+
/// Sets the text font of the [`Radio`] button.
- pub fn font(mut self, font: Renderer::Font) -> Self {
- self.font = font;
+ pub fn font(mut self, font: impl Into<Renderer::Font>) -> Self {
+ self.font = Some(font.into());
self
}
@@ -171,7 +191,7 @@ impl<Message, Renderer> Widget<Message, Renderer> for Radio<Message, Renderer>
where
Message: Clone,
Renderer: text::Renderer,
- Renderer::Theme: StyleSheet + widget::text::StyleSheet,
+ Renderer::Theme: StyleSheet + crate::text::StyleSheet,
{
fn width(&self) -> Length {
self.width
@@ -191,9 +211,16 @@ where
.spacing(self.spacing)
.align_items(Alignment::Center)
.push(Row::new().width(self.size).height(self.size))
- .push(Text::new(&self.label).width(self.width).size(
- self.text_size.unwrap_or_else(|| renderer.default_size()),
- ))
+ .push(
+ Text::new(&self.label)
+ .width(self.width)
+ .size(
+ self.text_size
+ .unwrap_or_else(|| renderer.default_size()),
+ )
+ .line_height(self.text_line_height)
+ .shaping(self.text_shaping),
+ )
.layout(renderer, limits)
}
@@ -296,18 +323,20 @@ where
{
let label_layout = children.next().unwrap();
- widget::text::draw(
+ crate::text::draw(
renderer,
style,
label_layout,
&self.label,
self.text_size,
- self.font.clone(),
- widget::text::Appearance {
+ self.text_line_height,
+ self.font,
+ crate::text::Appearance {
color: custom_style.text_color,
},
alignment::Horizontal::Left,
alignment::Vertical::Center,
+ self.text_shaping,
);
}
}
@@ -318,7 +347,7 @@ impl<'a, Message, Renderer> From<Radio<Message, Renderer>>
where
Message: 'a + Clone,
Renderer: 'a + text::Renderer,
- Renderer::Theme: StyleSheet + widget::text::StyleSheet,
+ Renderer::Theme: StyleSheet + crate::text::StyleSheet,
{
fn from(radio: Radio<Message, Renderer>) -> Element<'a, Message, Renderer> {
Element::new(radio)
diff --git a/native/src/widget/row.rs b/widget/src/row.rs
index 286c1c2d..3ce363f8 100644
--- a/native/src/widget/row.rs
+++ b/widget/src/row.rs
@@ -1,18 +1,18 @@
//! Distribute content horizontally.
-use crate::event::{self, Event};
-use crate::layout::{self, Layout};
-use crate::mouse;
-use crate::overlay;
-use crate::renderer;
-use crate::widget::{Operation, Tree};
-use crate::{
+use crate::core::event::{self, Event};
+use crate::core::layout::{self, Layout};
+use crate::core::mouse;
+use crate::core::overlay;
+use crate::core::renderer;
+use crate::core::widget::{Operation, Tree};
+use crate::core::{
Alignment, Clipboard, Element, Length, Padding, Pixels, Point, Rectangle,
Shell, Widget,
};
/// A container that distributes its contents horizontally.
#[allow(missing_debug_implementations)]
-pub struct Row<'a, Message, Renderer> {
+pub struct Row<'a, Message, Renderer = crate::Renderer> {
spacing: f32,
padding: Padding,
width: Length,
@@ -94,7 +94,7 @@ impl<'a, Message, Renderer> Default for Row<'a, Message, Renderer> {
impl<'a, Message, Renderer> Widget<Message, Renderer>
for Row<'a, Message, Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
{
fn children(&self) -> Vec<Tree> {
self.children.iter().map(Tree::new).collect()
@@ -245,7 +245,7 @@ impl<'a, Message, Renderer> From<Row<'a, Message, Renderer>>
for Element<'a, Message, Renderer>
where
Message: 'a,
- Renderer: crate::Renderer + 'a,
+ Renderer: crate::core::Renderer + 'a,
{
fn from(row: Row<'a, Message, Renderer>) -> Self {
Self::new(row)
diff --git a/native/src/widget/rule.rs b/widget/src/rule.rs
index 1ab6a0d3..3749d7ce 100644
--- a/native/src/widget/rule.rs
+++ b/widget/src/rule.rs
@@ -1,18 +1,18 @@
//! Display a horizontal or vertical rule for dividing content.
-use crate::layout;
-use crate::renderer;
-use crate::widget::Tree;
-use crate::{
+use crate::core::layout;
+use crate::core::renderer;
+use crate::core::widget::Tree;
+use crate::core::{
Color, Element, Layout, Length, Pixels, Point, Rectangle, Size, Widget,
};
-pub use iced_style::rule::{Appearance, FillMode, StyleSheet};
+pub use crate::style::rule::{Appearance, FillMode, StyleSheet};
/// Display a horizontal or vertical rule for dividing content.
#[allow(missing_debug_implementations)]
-pub struct Rule<Renderer>
+pub struct Rule<Renderer = crate::Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
width: Length,
@@ -23,7 +23,7 @@ where
impl<Renderer> Rule<Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
/// Creates a horizontal [`Rule`] with the given height.
@@ -58,7 +58,7 @@ where
impl<Message, Renderer> Widget<Message, Renderer> for Rule<Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
fn width(&self) -> Length {
@@ -138,7 +138,7 @@ impl<'a, Message, Renderer> From<Rule<Renderer>>
for Element<'a, Message, Renderer>
where
Message: 'a,
- Renderer: 'a + crate::Renderer,
+ Renderer: 'a + crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
fn from(rule: Rule<Renderer>) -> Element<'a, Message, Renderer> {
diff --git a/native/src/widget/scrollable.rs b/widget/src/scrollable.rs
index e35a4f96..fd51a6a8 100644
--- a/native/src/widget/scrollable.rs
+++ b/widget/src/scrollable.rs
@@ -1,35 +1,29 @@
//! Navigate an endless amount of content with a scrollbar.
-use crate::event::{self, Event};
-use crate::keyboard;
-use crate::layout;
-use crate::mouse;
-use crate::overlay;
-use crate::renderer;
-use crate::touch;
-use crate::widget;
-use crate::widget::operation::{self, Operation};
-use crate::widget::tree::{self, Tree};
-use crate::{
- Background, Clipboard, Color, Command, Element, Layout, Length, Pixels,
- Point, Rectangle, Shell, Size, Vector, Widget,
+use crate::core::event::{self, Event};
+use crate::core::keyboard;
+use crate::core::layout;
+use crate::core::mouse;
+use crate::core::overlay;
+use crate::core::renderer;
+use crate::core::touch;
+use crate::core::widget;
+use crate::core::widget::operation::{self, Operation};
+use crate::core::widget::tree::{self, Tree};
+use crate::core::{
+ Background, Clipboard, Color, Element, Layout, Length, Pixels, Point,
+ Rectangle, Shell, Size, Vector, Widget,
};
+use crate::runtime::Command;
-pub use iced_style::scrollable::StyleSheet;
+pub use crate::style::scrollable::{Scrollbar, Scroller, StyleSheet};
pub use operation::scrollable::{AbsoluteOffset, RelativeOffset};
-pub mod style {
- //! The styles of a [`Scrollable`].
- //!
- //! [`Scrollable`]: crate::widget::Scrollable
- pub use iced_style::scrollable::{Scrollbar, Scroller};
-}
-
/// A widget that can vertically display an infinite amount of content with a
/// scrollbar.
#[allow(missing_debug_implementations)]
-pub struct Scrollable<'a, Message, Renderer>
+pub struct Scrollable<'a, Message, Renderer = crate::Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
id: Option<Id>,
@@ -44,7 +38,7 @@ where
impl<'a, Message, Renderer> Scrollable<'a, Message, Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
/// Creates a new [`Scrollable`].
@@ -157,7 +151,7 @@ impl Properties {
impl<'a, Message, Renderer> Widget<Message, Renderer>
for Scrollable<'a, Message, Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
fn tag(&self) -> tree::Tag {
@@ -349,7 +343,7 @@ impl<'a, Message, Renderer> From<Scrollable<'a, Message, Renderer>>
for Element<'a, Message, Renderer>
where
Message: 'a,
- Renderer: 'a + crate::Renderer,
+ Renderer: 'a + crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
fn from(
@@ -768,7 +762,7 @@ pub fn draw<Renderer>(
style: &<Renderer::Theme as StyleSheet>::Style,
draw_content: impl FnOnce(&mut Renderer, Layout<'_>, Point, &Rectangle),
) where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
let bounds = layout.bounds();
@@ -814,8 +808,8 @@ pub fn draw<Renderer>(
let draw_scrollbar =
|renderer: &mut Renderer,
- style: style::Scrollbar,
- scrollbar: &Scrollbar| {
+ style: Scrollbar,
+ scrollbar: &internals::Scrollbar| {
//track
if style.background.is_some()
|| (style.border_color != Color::TRANSPARENT
@@ -1139,8 +1133,8 @@ impl State {
#[derive(Debug)]
/// State of both [`Scrollbar`]s.
struct Scrollbars {
- y: Option<Scrollbar>,
- x: Option<Scrollbar>,
+ y: Option<internals::Scrollbar>,
+ x: Option<internals::Scrollbar>,
}
impl Scrollbars {
@@ -1210,10 +1204,10 @@ impl Scrollbars {
height: scroller_height,
};
- Some(Scrollbar {
+ Some(internals::Scrollbar {
total_bounds: total_scrollbar_bounds,
bounds: scrollbar_bounds,
- scroller: Scroller {
+ scroller: internals::Scroller {
bounds: scroller_bounds,
},
})
@@ -1270,10 +1264,10 @@ impl Scrollbars {
height: scroller_width,
};
- Some(Scrollbar {
+ Some(internals::Scrollbar {
total_bounds: total_scrollbar_bounds,
bounds: scrollbar_bounds,
- scroller: Scroller {
+ scroller: internals::Scroller {
bounds: scroller_bounds,
},
})
@@ -1335,64 +1329,68 @@ impl Scrollbars {
}
}
-/// The scrollbar of a [`Scrollable`].
-#[derive(Debug, Copy, Clone)]
-struct Scrollbar {
- /// The total bounds of the [`Scrollbar`], including the scrollbar, the scroller,
- /// and the scrollbar margin.
- total_bounds: Rectangle,
+pub(super) mod internals {
+ use crate::core::{Point, Rectangle};
- /// The bounds of just the [`Scrollbar`].
- bounds: Rectangle,
+ /// The scrollbar of a [`Scrollable`].
+ #[derive(Debug, Copy, Clone)]
+ pub struct Scrollbar {
+ /// The total bounds of the [`Scrollbar`], including the scrollbar, the scroller,
+ /// and the scrollbar margin.
+ pub total_bounds: Rectangle,
- /// The state of this scrollbar's [`Scroller`].
- scroller: Scroller,
-}
+ /// The bounds of just the [`Scrollbar`].
+ pub bounds: Rectangle,
-impl Scrollbar {
- /// Returns whether the mouse is over the scrollbar or not.
- fn is_mouse_over(&self, cursor_position: Point) -> bool {
- self.total_bounds.contains(cursor_position)
+ /// The state of this scrollbar's [`Scroller`].
+ pub scroller: Scroller,
}
- /// Returns the y-axis scrolled percentage from the cursor position.
- fn scroll_percentage_y(
- &self,
- grabbed_at: f32,
- cursor_position: Point,
- ) -> f32 {
- if cursor_position.x < 0.0 && cursor_position.y < 0.0 {
- // cursor position is unavailable! Set to either end or beginning of scrollbar depending
- // on where the thumb currently is in the track
- (self.scroller.bounds.y / self.total_bounds.height).round()
- } else {
- (cursor_position.y
- - self.bounds.y
- - self.scroller.bounds.height * grabbed_at)
- / (self.bounds.height - self.scroller.bounds.height)
+ impl Scrollbar {
+ /// Returns whether the mouse is over the scrollbar or not.
+ pub fn is_mouse_over(&self, cursor_position: Point) -> bool {
+ self.total_bounds.contains(cursor_position)
}
- }
- /// Returns the x-axis scrolled percentage from the cursor position.
- fn scroll_percentage_x(
- &self,
- grabbed_at: f32,
- cursor_position: Point,
- ) -> f32 {
- if cursor_position.x < 0.0 && cursor_position.y < 0.0 {
- (self.scroller.bounds.x / self.total_bounds.width).round()
- } else {
- (cursor_position.x
- - self.bounds.x
- - self.scroller.bounds.width * grabbed_at)
- / (self.bounds.width - self.scroller.bounds.width)
+ /// Returns the y-axis scrolled percentage from the cursor position.
+ pub fn scroll_percentage_y(
+ &self,
+ grabbed_at: f32,
+ cursor_position: Point,
+ ) -> f32 {
+ if cursor_position.x < 0.0 && cursor_position.y < 0.0 {
+ // cursor position is unavailable! Set to either end or beginning of scrollbar depending
+ // on where the thumb currently is in the track
+ (self.scroller.bounds.y / self.total_bounds.height).round()
+ } else {
+ (cursor_position.y
+ - self.bounds.y
+ - self.scroller.bounds.height * grabbed_at)
+ / (self.bounds.height - self.scroller.bounds.height)
+ }
+ }
+
+ /// Returns the x-axis scrolled percentage from the cursor position.
+ pub fn scroll_percentage_x(
+ &self,
+ grabbed_at: f32,
+ cursor_position: Point,
+ ) -> f32 {
+ if cursor_position.x < 0.0 && cursor_position.y < 0.0 {
+ (self.scroller.bounds.x / self.total_bounds.width).round()
+ } else {
+ (cursor_position.x
+ - self.bounds.x
+ - self.scroller.bounds.width * grabbed_at)
+ / (self.bounds.width - self.scroller.bounds.width)
+ }
}
}
-}
-/// The handle of a [`Scrollbar`].
-#[derive(Debug, Clone, Copy)]
-struct Scroller {
- /// The bounds of the [`Scroller`].
- bounds: Rectangle,
+ /// The handle of a [`Scrollbar`].
+ #[derive(Debug, Clone, Copy)]
+ pub struct Scroller {
+ /// The bounds of the [`Scroller`].
+ pub bounds: Rectangle,
+ }
}
diff --git a/native/src/widget/slider.rs b/widget/src/slider.rs
index cfb0a8fe..18a49665 100644
--- a/native/src/widget/slider.rs
+++ b/widget/src/slider.rs
@@ -1,13 +1,13 @@
//! Display an interactive selector of a single value from a range of values.
//!
//! A [`Slider`] has some local [`State`].
-use crate::event::{self, Event};
-use crate::layout;
-use crate::mouse;
-use crate::renderer;
-use crate::touch;
-use crate::widget::tree::{self, Tree};
-use crate::{
+use crate::core::event::{self, Event};
+use crate::core::layout;
+use crate::core::mouse;
+use crate::core::renderer;
+use crate::core::touch;
+use crate::core::widget::tree::{self, Tree};
+use crate::core::{
Clipboard, Color, Element, Layout, Length, Pixels, Point, Rectangle, Shell,
Size, Widget,
};
@@ -27,11 +27,9 @@ pub use iced_style::slider::{
/// to 1 unit.
///
/// # Example
-/// ```
-/// # use iced_native::widget::slider;
-/// # use iced_native::renderer::Null;
-/// #
-/// # type Slider<'a, T, Message> = slider::Slider<'a, T, Message, Null>;
+/// ```no_run
+/// # type Slider<'a, T, Message> =
+/// # iced_widget::Slider<'a, Message, T, iced_widget::renderer::Renderer<iced_widget::style::Theme>>;
/// #
/// #[derive(Clone)]
/// pub enum Message {
@@ -45,9 +43,9 @@ pub use iced_style::slider::{
///
/// ![Slider drawn by Coffee's renderer](https://github.com/hecrj/coffee/blob/bda9818f823dfcb8a7ad0ff4940b4d4b387b5208/images/ui/slider.png?raw=true)
#[allow(missing_debug_implementations)]
-pub struct Slider<'a, T, Message, Renderer>
+pub struct Slider<'a, T, Message, Renderer = crate::Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
range: RangeInclusive<T>,
@@ -64,7 +62,7 @@ impl<'a, T, Message, Renderer> Slider<'a, T, Message, Renderer>
where
T: Copy + From<u8> + std::cmp::PartialOrd,
Message: Clone,
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
/// The default height of a [`Slider`].
@@ -150,7 +148,7 @@ impl<'a, T, Message, Renderer> Widget<Message, Renderer>
where
T: Copy + Into<f64> + num_traits::FromPrimitive,
Message: Clone,
- Renderer: crate::Renderer,
+ Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
fn tag(&self) -> tree::Tag {
@@ -247,7 +245,7 @@ impl<'a, T, Message, Renderer> From<Slider<'a, T, Message, Renderer>>
where
T: 'a + Copy + Into<f64> + num_traits::FromPrimitive,
Message: 'a + Clone,
- Renderer: 'a + crate::Renderer,
+ Renderer: 'a + crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
fn from(
@@ -356,7 +354,7 @@ pub fn draw<T, R>(
style: &<R::Theme as StyleSheet>::Style,
) where
T: Into<f64> + Copy,
- R: crate::Renderer,
+ R: crate::core::Renderer,
R::Theme: StyleSheet,
{
let bounds = layout.bounds();
diff --git a/native/src/widget/space.rs b/widget/src/space.rs
index a6fc977e..e1e09d5a 100644
--- a/native/src/widget/space.rs
+++ b/widget/src/space.rs
@@ -1,8 +1,9 @@
//! Distribute content vertically.
-use crate::layout;
-use crate::renderer;
-use crate::widget::Tree;
-use crate::{Element, Layout, Length, Point, Rectangle, Size, Widget};
+use crate::core;
+use crate::core::layout;
+use crate::core::renderer;
+use crate::core::widget::Tree;
+use crate::core::{Element, Layout, Length, Point, Rectangle, Size, Widget};
/// An amount of empty space.
///
@@ -41,7 +42,7 @@ impl Space {
impl<Message, Renderer> Widget<Message, Renderer> for Space
where
- Renderer: crate::Renderer,
+ Renderer: core::Renderer,
{
fn width(&self) -> Length {
self.width
@@ -76,7 +77,7 @@ where
impl<'a, Message, Renderer> From<Space> for Element<'a, Message, Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: core::Renderer,
Message: 'a,
{
fn from(space: Space) -> Element<'a, Message, Renderer> {
diff --git a/native/src/widget/svg.rs b/widget/src/svg.rs
index f5ed0a6c..89017fcf 100644
--- a/native/src/widget/svg.rs
+++ b/widget/src/svg.rs
@@ -1,15 +1,15 @@
//! Display vector graphics in your application.
-use crate::layout;
-use crate::renderer;
-use crate::svg;
-use crate::widget::Tree;
-use crate::{
+use crate::core::layout;
+use crate::core::renderer;
+use crate::core::svg;
+use crate::core::widget::Tree;
+use crate::core::{
ContentFit, Element, Layout, Length, Point, Rectangle, Size, Vector, Widget,
};
use std::path::PathBuf;
-pub use iced_style::svg::{Appearance, StyleSheet};
+pub use crate::style::svg::{Appearance, StyleSheet};
pub use svg::Handle;
/// A vector graphics image.
@@ -19,7 +19,7 @@ pub use svg::Handle;
/// [`Svg`] images can have a considerable rendering cost when resized,
/// specially when they are complex.
#[allow(missing_debug_implementations)]
-pub struct Svg<Renderer>
+pub struct Svg<Renderer = crate::Renderer>
where
Renderer: svg::Renderer,
Renderer::Theme: StyleSheet,
diff --git a/native/src/widget/text_input.rs b/widget/src/text_input.rs
index 6113cf94..bbc07dac 100644
--- a/native/src/widget/text_input.rs
+++ b/widget/src/text_input.rs
@@ -11,31 +11,34 @@ pub use value::Value;
use editor::Editor;
-use crate::alignment;
-use crate::event::{self, Event};
-use crate::keyboard;
-use crate::layout;
-use crate::mouse::{self, click};
-use crate::renderer;
-use crate::text::{self, Text};
-use crate::time::{Duration, Instant};
-use crate::touch;
-use crate::widget;
-use crate::widget::operation::{self, Operation};
-use crate::widget::tree::{self, Tree};
-use crate::window;
-use crate::{
- Clipboard, Color, Command, Element, Layout, Length, Padding, Pixels, Point,
+use crate::core::alignment;
+use crate::core::event::{self, Event};
+use crate::core::keyboard;
+use crate::core::layout;
+use crate::core::mouse::{self, click};
+use crate::core::renderer;
+use crate::core::text::{self, Text};
+use crate::core::time::{Duration, Instant};
+use crate::core::touch;
+use crate::core::widget;
+use crate::core::widget::operation::{self, Operation};
+use crate::core::widget::tree::{self, Tree};
+use crate::core::window;
+use crate::core::{
+ Clipboard, Color, Element, Layout, Length, Padding, Pixels, Point,
Rectangle, Shell, Size, Vector, Widget,
};
+use crate::runtime::Command;
pub use iced_style::text_input::{Appearance, StyleSheet};
/// A field that can be filled with text.
///
/// # Example
-/// ```
-/// # pub type TextInput<'a, Message> = iced_native::widget::TextInput<'a, Message, iced_native::renderer::Null>;
+/// ```no_run
+/// # pub type TextInput<'a, Message> =
+/// # iced_widget::TextInput<'a, Message, iced_widget::renderer::Renderer<iced_widget::style::Theme>>;
+/// #
/// #[derive(Debug, Clone)]
/// enum Message {
/// TextInputChanged(String),
@@ -52,7 +55,7 @@ pub use iced_style::text_input::{Appearance, StyleSheet};
/// ```
/// ![Text input drawn by `iced_wgpu`](https://github.com/iced-rs/iced/blob/7760618fb112074bc40b148944521f312152012a/docs/images/text_input.png?raw=true)
#[allow(missing_debug_implementations)]
-pub struct TextInput<'a, Message, Renderer>
+pub struct TextInput<'a, Message, Renderer = crate::Renderer>
where
Renderer: text::Renderer,
Renderer::Theme: StyleSheet,
@@ -61,10 +64,11 @@ where
placeholder: String,
value: Value,
is_secure: bool,
- font: Renderer::Font,
+ font: Option<Renderer::Font>,
width: Length,
padding: Padding,
size: Option<f32>,
+ line_height: text::LineHeight,
on_input: Option<Box<dyn Fn(String) -> Message + 'a>>,
on_paste: Option<Box<dyn Fn(String) -> Message + 'a>>,
on_submit: Option<Message>,
@@ -89,10 +93,11 @@ where
placeholder: String::from(placeholder),
value: Value::new(value),
is_secure: false,
- font: Default::default(),
+ font: None,
width: Length::Fill,
padding: Padding::new(5.0),
size: None,
+ line_height: text::LineHeight::default(),
on_input: None,
on_paste: None,
on_submit: None,
@@ -146,7 +151,7 @@ where
///
/// [`Font`]: text::Renderer::Font
pub fn font(mut self, font: Renderer::Font) -> Self {
- self.font = font;
+ self.font = Some(font);
self
}
@@ -174,6 +179,15 @@ where
self
}
+ /// Sets the [`LineHeight`] of the [`TextInput`].
+ pub fn line_height(
+ mut self,
+ line_height: impl Into<text::LineHeight>,
+ ) -> Self {
+ self.line_height = line_height.into();
+ self
+ }
+
/// Sets the style of the [`TextInput`].
pub fn style(
mut self,
@@ -205,7 +219,8 @@ where
value.unwrap_or(&self.value),
&self.placeholder,
self.size,
- &self.font,
+ self.line_height,
+ self.font,
self.on_input.is_none(),
self.is_secure,
self.icon.as_ref(),
@@ -260,6 +275,7 @@ where
self.width,
self.padding,
self.size,
+ self.line_height,
self.icon.as_ref(),
)
}
@@ -296,7 +312,8 @@ where
shell,
&mut self.value,
self.size,
- &self.font,
+ self.line_height,
+ self.font,
self.is_secure,
self.on_input.as_deref(),
self.on_paste.as_deref(),
@@ -324,7 +341,8 @@ where
&self.value,
&self.placeholder,
self.size,
- &self.font,
+ self.line_height,
+ self.font,
self.on_input.is_none(),
self.is_secure,
self.icon.as_ref(),
@@ -444,15 +462,18 @@ pub fn layout<Renderer>(
width: Length,
padding: Padding,
size: Option<f32>,
+ line_height: text::LineHeight,
icon: Option<&Icon<Renderer::Font>>,
) -> layout::Node
where
Renderer: text::Renderer,
{
let text_size = size.unwrap_or_else(|| renderer.default_size());
-
let padding = padding.fit(Size::ZERO, limits.max());
- let limits = limits.width(width).pad(padding).height(text_size);
+ let limits = limits
+ .width(width)
+ .pad(padding)
+ .height(line_height.to_absolute(Pixels(text_size)));
let text_bounds = limits.resolve(Size::ZERO);
@@ -460,7 +481,8 @@ where
let icon_width = renderer.measure_width(
&icon.code_point.to_string(),
icon.size.unwrap_or_else(|| renderer.default_size()),
- icon.font.clone(),
+ icon.font,
+ text::Shaping::Advanced,
);
let mut text_node = layout::Node::new(
@@ -512,7 +534,8 @@ pub fn update<'a, Message, Renderer>(
shell: &mut Shell<'_, Message>,
value: &mut Value,
size: Option<f32>,
- font: &Renderer::Font,
+ line_height: text::LineHeight,
+ font: Option<Renderer::Font>,
is_secure: bool,
on_input: Option<&dyn Fn(String) -> Message>,
on_paste: Option<&dyn Fn(String) -> Message>,
@@ -562,8 +585,9 @@ where
find_cursor_position(
renderer,
text_layout.bounds(),
- font.clone(),
+ font,
size,
+ line_height,
&value,
state,
target,
@@ -590,8 +614,9 @@ where
let position = find_cursor_position(
renderer,
text_layout.bounds(),
- font.clone(),
+ font,
size,
+ line_height,
value,
state,
target,
@@ -639,8 +664,9 @@ where
let position = find_cursor_position(
renderer,
text_layout.bounds(),
- font.clone(),
+ font,
size,
+ line_height,
&value,
state,
target,
@@ -923,7 +949,8 @@ pub fn draw<Renderer>(
value: &Value,
placeholder: &str,
size: Option<f32>,
- font: &Renderer::Font,
+ line_height: text::LineHeight,
+ font: Option<Renderer::Font>,
is_disabled: bool,
is_secure: bool,
icon: Option<&Icon<Renderer::Font>>,
@@ -968,7 +995,8 @@ pub fn draw<Renderer>(
renderer.fill_text(Text {
content: &icon.code_point.to_string(),
size: icon.size.unwrap_or_else(|| renderer.default_size()),
- font: icon.font.clone(),
+ line_height: text::LineHeight::default(),
+ font: icon.font,
color: appearance.icon_color,
bounds: Rectangle {
y: text_bounds.center_y(),
@@ -976,10 +1004,12 @@ pub fn draw<Renderer>(
},
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Center,
+ shaping: text::Shaping::Advanced,
});
}
let text = value.to_string();
+ let font = font.unwrap_or_else(|| renderer.default_font());
let size = size.unwrap_or_else(|| renderer.default_size());
let (cursor, offset) = if let Some(focus) = &state.is_focused {
@@ -992,7 +1022,7 @@ pub fn draw<Renderer>(
value,
size,
position,
- font.clone(),
+ font,
);
let is_cursor_visible = ((focus.now - focus.updated_at)
@@ -1033,7 +1063,7 @@ pub fn draw<Renderer>(
value,
size,
left,
- font.clone(),
+ font,
);
let (right_position, right_offset) =
@@ -1043,7 +1073,7 @@ pub fn draw<Renderer>(
value,
size,
right,
- font.clone(),
+ font,
);
let width = right_position - left_position;
@@ -1078,12 +1108,15 @@ pub fn draw<Renderer>(
let text_width = renderer.measure_width(
if text.is_empty() { placeholder } else { &text },
size,
- font.clone(),
+ font,
+ text::Shaping::Advanced,
);
let render = |renderer: &mut Renderer| {
if let Some((cursor, color)) = cursor {
renderer.fill_quad(cursor, color);
+ } else {
+ renderer.with_translation(Vector::ZERO, |_| {});
}
renderer.fill_text(Text {
@@ -1095,15 +1128,17 @@ pub fn draw<Renderer>(
} else {
theme.value_color(style)
},
- font: font.clone(),
+ font,
bounds: Rectangle {
y: text_bounds.center_y(),
width: f32::INFINITY,
..text_bounds
},
size,
+ line_height,
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Center,
+ shaping: text::Shaping::Advanced,
});
};
@@ -1250,7 +1285,7 @@ impl operation::TextInput for State {
}
mod platform {
- use crate::keyboard;
+ use crate::core::keyboard;
pub fn is_jump_modifier_pressed(modifiers: keyboard::Modifiers) -> bool {
if cfg!(target_os = "macos") {
@@ -1308,8 +1343,12 @@ where
{
let text_before_cursor = value.until(cursor_index).to_string();
- let text_value_width =
- renderer.measure_width(&text_before_cursor, size, font);
+ let text_value_width = renderer.measure_width(
+ &text_before_cursor,
+ size,
+ font,
+ text::Shaping::Advanced,
+ );
let offset = ((text_value_width + 5.0) - text_bounds.width).max(0.0);
@@ -1321,8 +1360,9 @@ where
fn find_cursor_position<Renderer>(
renderer: &Renderer,
text_bounds: Rectangle,
- font: Renderer::Font,
+ font: Option<Renderer::Font>,
size: Option<f32>,
+ line_height: text::LineHeight,
value: &Value,
state: &State,
x: f32,
@@ -1330,21 +1370,32 @@ fn find_cursor_position<Renderer>(
where
Renderer: text::Renderer,
{
+ let font = font.unwrap_or_else(|| renderer.default_font());
let size = size.unwrap_or_else(|| renderer.default_size());
- let offset =
- offset(renderer, text_bounds, font.clone(), size, value, state);
+ let offset = offset(renderer, text_bounds, font, size, value, state);
+ let value = value.to_string();
- renderer
+ let char_offset = renderer
.hit_test(
- &value.to_string(),
+ &value,
size,
+ line_height,
font,
Size::INFINITY,
+ text::Shaping::Advanced,
Point::new(x + offset, text_bounds.height / 2.0),
true,
)
- .map(text::Hit::cursor)
+ .map(text::Hit::cursor)?;
+
+ Some(
+ unicode_segmentation::UnicodeSegmentation::graphemes(
+ &value[..char_offset],
+ true,
+ )
+ .count(),
+ )
}
const CURSOR_BLINK_INTERVAL_MILLIS: u128 = 500;
diff --git a/native/src/widget/text_input/cursor.rs b/widget/src/text_input/cursor.rs
index 4f3b159b..9680dfd7 100644
--- a/native/src/widget/text_input/cursor.rs
+++ b/widget/src/text_input/cursor.rs
@@ -1,5 +1,5 @@
//! Track the cursor of a text input.
-use crate::widget::text_input::Value;
+use crate::text_input::Value;
/// The cursor of a text input.
#[derive(Debug, Copy, Clone)]
diff --git a/native/src/widget/text_input/editor.rs b/widget/src/text_input/editor.rs
index d53fa8d9..f1fd641f 100644
--- a/native/src/widget/text_input/editor.rs
+++ b/widget/src/text_input/editor.rs
@@ -1,4 +1,4 @@
-use crate::widget::text_input::{Cursor, Value};
+use crate::text_input::{Cursor, Value};
pub struct Editor<'a> {
value: &'a mut Value,
diff --git a/native/src/widget/text_input/value.rs b/widget/src/text_input/value.rs
index cf4da562..cf4da562 100644
--- a/native/src/widget/text_input/value.rs
+++ b/widget/src/text_input/value.rs
diff --git a/native/src/widget/toggler.rs b/widget/src/toggler.rs
index a434af65..b1ba65c9 100644
--- a/native/src/widget/toggler.rs
+++ b/widget/src/toggler.rs
@@ -1,24 +1,26 @@
//! Show toggle controls using togglers.
-use crate::alignment;
-use crate::event;
-use crate::layout;
-use crate::mouse;
-use crate::renderer;
-use crate::text;
-use crate::widget::{self, Row, Text, Tree};
-use crate::{
+use crate::core::alignment;
+use crate::core::event;
+use crate::core::layout;
+use crate::core::mouse;
+use crate::core::renderer;
+use crate::core::text;
+use crate::core::widget::Tree;
+use crate::core::{
Alignment, Clipboard, Element, Event, Layout, Length, Pixels, Point,
Rectangle, Shell, Widget,
};
+use crate::{Row, Text};
-pub use iced_style::toggler::{Appearance, StyleSheet};
+pub use crate::style::toggler::{Appearance, StyleSheet};
/// A toggler widget.
///
/// # Example
///
-/// ```
-/// # type Toggler<'a, Message> = iced_native::widget::Toggler<'a, Message, iced_native::renderer::Null>;
+/// ```no_run
+/// # type Toggler<'a, Message> =
+/// # iced_widget::Toggler<'a, Message, iced_widget::renderer::Renderer<iced_widget::style::Theme>>;
/// #
/// pub enum Message {
/// TogglerToggled(bool),
@@ -29,7 +31,7 @@ pub use iced_style::toggler::{Appearance, StyleSheet};
/// Toggler::new(String::from("Toggle me!"), is_toggled, |b| Message::TogglerToggled(b));
/// ```
#[allow(missing_debug_implementations)]
-pub struct Toggler<'a, Message, Renderer>
+pub struct Toggler<'a, Message, Renderer = crate::Renderer>
where
Renderer: text::Renderer,
Renderer::Theme: StyleSheet,
@@ -40,9 +42,11 @@ where
width: Length,
size: f32,
text_size: Option<f32>,
+ text_line_height: text::LineHeight,
text_alignment: alignment::Horizontal,
+ text_shaping: text::Shaping,
spacing: f32,
- font: Renderer::Font,
+ font: Option<Renderer::Font>,
style: <Renderer::Theme as StyleSheet>::Style,
}
@@ -77,9 +81,11 @@ where
width: Length::Fill,
size: Self::DEFAULT_SIZE,
text_size: None,
+ text_line_height: text::LineHeight::default(),
text_alignment: alignment::Horizontal::Left,
+ text_shaping: text::Shaping::Basic,
spacing: 0.0,
- font: Renderer::Font::default(),
+ font: None,
style: Default::default(),
}
}
@@ -102,12 +108,27 @@ where
self
}
+ /// Sets the text [`LineHeight`] of the [`Toggler`].
+ pub fn text_line_height(
+ mut self,
+ line_height: impl Into<text::LineHeight>,
+ ) -> Self {
+ self.text_line_height = line_height.into();
+ self
+ }
+
/// Sets the horizontal alignment of the text of the [`Toggler`]
pub fn text_alignment(mut self, alignment: alignment::Horizontal) -> Self {
self.text_alignment = alignment;
self
}
+ /// Sets the [`text::Shaping`] strategy of the [`Toggler`].
+ pub fn text_shaping(mut self, shaping: text::Shaping) -> Self {
+ self.text_shaping = shaping;
+ self
+ }
+
/// Sets the spacing between the [`Toggler`] and the text.
pub fn spacing(mut self, spacing: impl Into<Pixels>) -> Self {
self.spacing = spacing.into().0;
@@ -117,8 +138,8 @@ where
/// Sets the [`Font`] of the text of the [`Toggler`]
///
/// [`Font`]: crate::text::Renderer::Font
- pub fn font(mut self, font: Renderer::Font) -> Self {
- self.font = font;
+ pub fn font(mut self, font: impl Into<Renderer::Font>) -> Self {
+ self.font = Some(font.into());
self
}
@@ -136,7 +157,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>
for Toggler<'a, Message, Renderer>
where
Renderer: text::Renderer,
- Renderer::Theme: StyleSheet + widget::text::StyleSheet,
+ Renderer::Theme: StyleSheet + crate::text::StyleSheet,
{
fn width(&self) -> Length {
self.width
@@ -160,12 +181,14 @@ where
row = row.push(
Text::new(label)
.horizontal_alignment(self.text_alignment)
- .font(self.font.clone())
+ .font(self.font.unwrap_or_else(|| renderer.default_font()))
.width(self.width)
.size(
self.text_size
.unwrap_or_else(|| renderer.default_size()),
- ),
+ )
+ .line_height(self.text_line_height)
+ .shaping(self.text_shaping),
);
}
@@ -237,16 +260,18 @@ where
if let Some(label) = &self.label {
let label_layout = children.next().unwrap();
- crate::widget::text::draw(
+ crate::text::draw(
renderer,
style,
label_layout,
label,
self.text_size,
- self.font.clone(),
+ self.text_line_height,
+ self.font,
Default::default(),
self.text_alignment,
alignment::Vertical::Center,
+ self.text_shaping,
);
}
@@ -314,7 +339,7 @@ impl<'a, Message, Renderer> From<Toggler<'a, Message, Renderer>>
where
Message: 'a,
Renderer: 'a + text::Renderer,
- Renderer::Theme: StyleSheet + widget::text::StyleSheet,
+ Renderer::Theme: StyleSheet + crate::text::StyleSheet,
{
fn from(
toggler: Toggler<'a, Message, Renderer>,
diff --git a/native/src/widget/tooltip.rs b/widget/src/tooltip.rs
index 2a24c055..084650d1 100644
--- a/native/src/widget/tooltip.rs
+++ b/widget/src/tooltip.rs
@@ -1,26 +1,27 @@
//! Display a widget over another.
-use crate::event;
-use crate::layout;
-use crate::mouse;
-use crate::renderer;
-use crate::text;
-use crate::widget;
-use crate::widget::container;
-use crate::widget::overlay;
-use crate::widget::{Text, Tree};
-use crate::{
- Clipboard, Element, Event, Layout, Length, Padding, Pixels, Point,
- Rectangle, Shell, Size, Vector, Widget,
+use crate::container;
+use crate::core;
+use crate::core::event::{self, Event};
+use crate::core::layout::{self, Layout};
+use crate::core::mouse;
+use crate::core::overlay;
+use crate::core::renderer;
+use crate::core::text;
+use crate::core::widget::Tree;
+use crate::core::{
+ Clipboard, Element, Length, Padding, Pixels, Point, Rectangle, Shell, Size,
+ Vector, Widget,
};
+use crate::Text;
use std::borrow::Cow;
/// An element to display a widget over another.
#[allow(missing_debug_implementations)]
-pub struct Tooltip<'a, Message, Renderer: text::Renderer>
+pub struct Tooltip<'a, Message, Renderer = crate::Renderer>
where
Renderer: text::Renderer,
- Renderer::Theme: container::StyleSheet + widget::text::StyleSheet,
+ Renderer::Theme: container::StyleSheet + crate::text::StyleSheet,
{
content: Element<'a, Message, Renderer>,
tooltip: Text<'a, Renderer>,
@@ -34,7 +35,7 @@ where
impl<'a, Message, Renderer> Tooltip<'a, Message, Renderer>
where
Renderer: text::Renderer,
- Renderer::Theme: container::StyleSheet + widget::text::StyleSheet,
+ Renderer::Theme: container::StyleSheet + crate::text::StyleSheet,
{
/// The default padding of a [`Tooltip`] drawn by this renderer.
const DEFAULT_PADDING: f32 = 5.0;
@@ -104,7 +105,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>
for Tooltip<'a, Message, Renderer>
where
Renderer: text::Renderer,
- Renderer::Theme: container::StyleSheet + widget::text::StyleSheet,
+ Renderer::Theme: container::StyleSheet + crate::text::StyleSheet,
{
fn children(&self) -> Vec<Tree> {
vec![Tree::new(&self.content)]
@@ -239,7 +240,7 @@ impl<'a, Message, Renderer> From<Tooltip<'a, Message, Renderer>>
where
Message: 'a,
Renderer: 'a + text::Renderer,
- Renderer::Theme: container::StyleSheet + widget::text::StyleSheet,
+ Renderer::Theme: container::StyleSheet + crate::text::StyleSheet,
{
fn from(
tooltip: Tooltip<'a, Message, Renderer>,
@@ -285,7 +286,7 @@ pub fn draw<Renderer>(
&Rectangle,
),
) where
- Renderer: crate::Renderer,
+ Renderer: core::Renderer,
Renderer::Theme: container::StyleSheet,
{
use container::StyleSheet;
diff --git a/native/src/widget/vertical_slider.rs b/widget/src/vertical_slider.rs
index cb2de480..2635611d 100644
--- a/native/src/widget/vertical_slider.rs
+++ b/widget/src/vertical_slider.rs
@@ -3,13 +3,18 @@
//! A [`VerticalSlider`] has some local [`State`].
use std::ops::RangeInclusive;
-pub use iced_style::slider::{Appearance, Handle, HandleShape, StyleSheet};
-
-use crate::event::{self, Event};
-use crate::widget::tree::{self, Tree};
-use crate::{
- layout, mouse, renderer, touch, Clipboard, Color, Element, Layout, Length,
- Pixels, Point, Rectangle, Shell, Size, Widget,
+pub use crate::style::slider::{Appearance, Handle, HandleShape, StyleSheet};
+
+use crate::core;
+use crate::core::event::{self, Event};
+use crate::core::layout::{self, Layout};
+use crate::core::mouse;
+use crate::core::renderer;
+use crate::core::touch;
+use crate::core::widget::tree::{self, Tree};
+use crate::core::{
+ Clipboard, Color, Element, Length, Pixels, Point, Rectangle, Shell, Size,
+ Widget,
};
/// An vertical bar and a handle that selects a single value from a range of
@@ -21,11 +26,9 @@ use crate::{
/// to 1 unit.
///
/// # Example
-/// ```
-/// # use iced_native::widget::vertical_slider;
-/// # use iced_native::renderer::Null;
-/// #
-/// # type VerticalSlider<'a, T, Message> = vertical_slider::VerticalSlider<'a, T, Message, Null>;
+/// ```no_run
+/// # type VerticalSlider<'a, T, Message> =
+/// # iced_widget::VerticalSlider<'a, T, Message, iced_widget::renderer::Renderer<iced_widget::style::Theme>>;
/// #
/// #[derive(Clone)]
/// pub enum Message {
@@ -37,9 +40,9 @@ use crate::{
/// VerticalSlider::new(0.0..=100.0, value, Message::SliderChanged);
/// ```
#[allow(missing_debug_implementations)]
-pub struct VerticalSlider<'a, T, Message, Renderer>
+pub struct VerticalSlider<'a, T, Message, Renderer = crate::Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: core::Renderer,
Renderer::Theme: StyleSheet,
{
range: RangeInclusive<T>,
@@ -56,7 +59,7 @@ impl<'a, T, Message, Renderer> VerticalSlider<'a, T, Message, Renderer>
where
T: Copy + From<u8> + std::cmp::PartialOrd,
Message: Clone,
- Renderer: crate::Renderer,
+ Renderer: core::Renderer,
Renderer::Theme: StyleSheet,
{
/// The default width of a [`VerticalSlider`].
@@ -142,7 +145,7 @@ impl<'a, T, Message, Renderer> Widget<Message, Renderer>
where
T: Copy + Into<f64> + num_traits::FromPrimitive,
Message: Clone,
- Renderer: crate::Renderer,
+ Renderer: core::Renderer,
Renderer::Theme: StyleSheet,
{
fn tag(&self) -> tree::Tag {
@@ -239,7 +242,7 @@ impl<'a, T, Message, Renderer> From<VerticalSlider<'a, T, Message, Renderer>>
where
T: 'a + Copy + Into<f64> + num_traits::FromPrimitive,
Message: 'a + Clone,
- Renderer: 'a + crate::Renderer,
+ Renderer: 'a + core::Renderer,
Renderer::Theme: StyleSheet,
{
fn from(
@@ -349,7 +352,7 @@ pub fn draw<T, R>(
style: &<R::Theme as StyleSheet>::Style,
) where
T: Into<f64> + Copy,
- R: crate::Renderer,
+ R: core::Renderer,
R::Theme: StyleSheet,
{
let bounds = layout.bounds();