summaryrefslogtreecommitdiffstats
path: root/core/src
diff options
context:
space:
mode:
Diffstat (limited to 'core/src')
-rw-r--r--core/src/element.rs4
-rw-r--r--core/src/image.rs4
-rw-r--r--core/src/renderer.rs33
-rw-r--r--core/src/renderer/null.rs58
-rw-r--r--core/src/size.rs2
-rw-r--r--core/src/svg.rs9
-rw-r--r--core/src/widget/text.rs117
7 files changed, 148 insertions, 79 deletions
diff --git a/core/src/element.rs b/core/src/element.rs
index 989eaa3b..7d918a2e 100644
--- a/core/src/element.rs
+++ b/core/src/element.rs
@@ -95,7 +95,7 @@ impl<'a, Message, Theme, Renderer> Element<'a, Message, Theme, Renderer> {
///
/// ```no_run
/// # mod iced {
- /// # pub type Element<'a, Message> = iced_core::Element<'a, Message, iced_core::Theme, iced_core::renderer::Null>;
+ /// # pub type Element<'a, Message> = iced_core::Element<'a, Message, iced_core::Theme, ()>;
/// #
/// # pub mod widget {
/// # pub fn row<'a, Message>(iter: impl IntoIterator<Item = super::Element<'a, Message>>) -> super::Element<'a, Message> {
@@ -109,7 +109,7 @@ impl<'a, Message, Theme, Renderer> Element<'a, Message, Theme, Renderer> {
/// # pub enum Message {}
/// # pub struct Counter;
/// #
- /// # pub type Element<'a, Message> = iced_core::Element<'a, Message, iced_core::Theme, iced_core::renderer::Null>;
+ /// # pub type Element<'a, Message> = iced_core::Element<'a, Message, iced_core::Theme, ()>;
/// #
/// # impl Counter {
/// # pub fn view(&self) -> Element<Message> {
diff --git a/core/src/image.rs b/core/src/image.rs
index e5fdcd83..32b95f03 100644
--- a/core/src/image.rs
+++ b/core/src/image.rs
@@ -186,11 +186,11 @@ pub trait Renderer: crate::Renderer {
type Handle: Clone + Hash;
/// Returns the dimensions of an image for the given [`Handle`].
- fn dimensions(&self, handle: &Self::Handle) -> Size<u32>;
+ fn measure_image(&self, handle: &Self::Handle) -> Size<u32>;
/// Draws an image with the given [`Handle`] and inside the provided
/// `bounds`.
- fn draw(
+ fn draw_image(
&mut self,
handle: Self::Handle,
filter_method: FilterMethod,
diff --git a/core/src/renderer.rs b/core/src/renderer.rs
index 1139b41c..6712314e 100644
--- a/core/src/renderer.rs
+++ b/core/src/renderer.rs
@@ -2,26 +2,47 @@
#[cfg(debug_assertions)]
mod null;
-#[cfg(debug_assertions)]
-pub use null::Null;
-
use crate::{
Background, Border, Color, Rectangle, Shadow, Size, Transformation, Vector,
};
/// A component that can be used by widgets to draw themselves on a screen.
-pub trait Renderer: Sized {
+pub trait Renderer {
+ /// Starts recording a new layer.
+ fn start_layer(&mut self);
+
+ /// Ends recording a new layer.
+ ///
+ /// The new layer will clip its contents to the provided `bounds`.
+ fn end_layer(&mut self, bounds: Rectangle);
+
/// Draws the primitives recorded in the given closure in a new layer.
///
/// The layer will clip its contents to the provided `bounds`.
- fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self));
+ fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self)) {
+ self.start_layer();
+ f(self);
+ self.end_layer(bounds);
+ }
+
+ /// Starts recording with a new [`Transformation`].
+ fn start_transformation(&mut self);
+
+ /// Ends recording a new layer.
+ ///
+ /// The new layer will clip its contents to the provided `bounds`.
+ fn end_transformation(&mut self, transformation: Transformation);
/// Applies a [`Transformation`] to the primitives recorded in the given closure.
fn with_transformation(
&mut self,
transformation: Transformation,
f: impl FnOnce(&mut Self),
- );
+ ) {
+ self.start_transformation();
+ f(self);
+ self.end_transformation(transformation);
+ }
/// Applies a translation to the primitives recorded in the given closure.
fn with_translation(
diff --git a/core/src/renderer/null.rs b/core/src/renderer/null.rs
index 83688ff7..c26ce1a5 100644
--- a/core/src/renderer/null.rs
+++ b/core/src/renderer/null.rs
@@ -1,5 +1,7 @@
use crate::alignment;
+use crate::image;
use crate::renderer::{self, Renderer};
+use crate::svg;
use crate::text::{self, Text};
use crate::{
Background, Color, Font, Pixels, Point, Rectangle, Size, Transformation,
@@ -7,28 +9,14 @@ use crate::{
use std::borrow::Cow;
-/// A renderer that does nothing.
-///
-/// It can be useful if you are writing tests!
-#[derive(Debug, Clone, Copy, Default)]
-pub struct Null;
+impl Renderer for () {
+ fn start_layer(&mut self) {}
-impl Null {
- /// Creates a new [`Null`] renderer.
- pub fn new() -> Null {
- Null
- }
-}
+ fn end_layer(&mut self, _bounds: Rectangle) {}
-impl Renderer for Null {
- fn with_layer(&mut self, _bounds: Rectangle, _f: impl FnOnce(&mut Self)) {}
+ fn start_transformation(&mut self) {}
- fn with_transformation(
- &mut self,
- _transformation: Transformation,
- _f: impl FnOnce(&mut Self),
- ) {
- }
+ fn end_transformation(&mut self, _transformation: Transformation) {}
fn clear(&mut self) {}
@@ -40,7 +28,7 @@ impl Renderer for Null {
}
}
-impl text::Renderer for Null {
+impl text::Renderer for () {
type Font = Font;
type Paragraph = ();
type Editor = ();
@@ -174,3 +162,33 @@ impl text::Editor for () {
) {
}
}
+
+impl image::Renderer for () {
+ type Handle = ();
+
+ fn measure_image(&self, _handle: &Self::Handle) -> Size<u32> {
+ Size::default()
+ }
+
+ fn draw_image(
+ &mut self,
+ _handle: Self::Handle,
+ _filter_method: image::FilterMethod,
+ _bounds: Rectangle,
+ ) {
+ }
+}
+
+impl svg::Renderer for () {
+ fn measure_svg(&self, _handle: &svg::Handle) -> Size<u32> {
+ Size::default()
+ }
+
+ fn draw_svg(
+ &mut self,
+ _handle: svg::Handle,
+ _color: Option<Color>,
+ _bounds: Rectangle,
+ ) {
+ }
+}
diff --git a/core/src/size.rs b/core/src/size.rs
index 267fc90e..55db759d 100644
--- a/core/src/size.rs
+++ b/core/src/size.rs
@@ -1,7 +1,7 @@
use crate::Vector;
/// An amount of space in 2 dimensions.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct Size<T = f32> {
/// The width.
pub width: T,
diff --git a/core/src/svg.rs b/core/src/svg.rs
index d63e3c95..ab207cca 100644
--- a/core/src/svg.rs
+++ b/core/src/svg.rs
@@ -91,8 +91,13 @@ impl std::fmt::Debug for Data {
/// [renderer]: crate::renderer
pub trait Renderer: crate::Renderer {
/// Returns the default dimensions of an SVG for the given [`Handle`].
- fn dimensions(&self, handle: &Handle) -> Size<u32>;
+ fn measure_svg(&self, handle: &Handle) -> Size<u32>;
/// Draws an SVG with the given [`Handle`], an optional [`Color`] filter, and inside the provided `bounds`.
- fn draw(&mut self, handle: Handle, color: Option<Color>, bounds: Rectangle);
+ fn draw_svg(
+ &mut self,
+ handle: Handle,
+ color: Option<Color>,
+ bounds: Rectangle,
+ );
}
diff --git a/core/src/widget/text.rs b/core/src/widget/text.rs
index 66e2d066..12f6956a 100644
--- a/core/src/widget/text.rs
+++ b/core/src/widget/text.rs
@@ -18,6 +18,7 @@ pub use text::{LineHeight, Shaping};
#[allow(missing_debug_implementations)]
pub struct Text<'a, Theme, Renderer>
where
+ Theme: Catalog,
Renderer: text::Renderer,
{
content: Cow<'a, str>,
@@ -29,18 +30,16 @@ where
vertical_alignment: alignment::Vertical,
font: Option<Renderer::Font>,
shaping: Shaping,
- style: Style<'a, Theme>,
+ class: Theme::Class<'a>,
}
impl<'a, Theme, Renderer> Text<'a, Theme, Renderer>
where
+ Theme: Catalog,
Renderer: text::Renderer,
{
/// Create a new fragment of [`Text`] with the given contents.
- pub fn new(content: impl Into<Cow<'a, str>>) -> Self
- where
- Theme: DefaultStyle + 'a,
- {
+ pub fn new(content: impl Into<Cow<'a, str>>) -> Self {
Text {
content: content.into(),
size: None,
@@ -51,7 +50,7 @@ where
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
shaping: Shaping::Basic,
- style: Box::new(Theme::default_style),
+ class: Theme::default(),
}
}
@@ -75,25 +74,6 @@ where
self
}
- /// Sets the style of the [`Text`].
- pub fn style(mut self, style: impl Fn(&Theme) -> Appearance + 'a) -> Self {
- self.style = Box::new(style);
- self
- }
-
- /// Sets the [`Color`] of the [`Text`].
- pub fn color(self, color: impl Into<Color>) -> Self {
- self.color_maybe(Some(color))
- }
-
- /// Sets the [`Color`] of the [`Text`], if `Some`.
- pub fn color_maybe(mut self, color: Option<impl Into<Color>>) -> Self {
- let color = color.map(Into::into);
-
- self.style = Box::new(move |_theme| Appearance { color });
- self
- }
-
/// Sets the width of the [`Text`] boundaries.
pub fn width(mut self, width: impl Into<Length>) -> Self {
self.width = width.into();
@@ -129,6 +109,42 @@ where
self.shaping = shaping;
self
}
+
+ /// Sets the style of the [`Text`].
+ #[must_use]
+ pub fn style(mut self, style: impl Fn(&Theme) -> Style + 'a) -> Self
+ where
+ Theme::Class<'a>: From<StyleFn<'a, Theme>>,
+ {
+ self.class = (Box::new(style) as StyleFn<'a, Theme>).into();
+ self
+ }
+
+ /// Sets the [`Color`] of the [`Text`].
+ pub fn color(self, color: impl Into<Color>) -> Self
+ where
+ Theme::Class<'a>: From<StyleFn<'a, Theme>>,
+ {
+ self.color_maybe(Some(color))
+ }
+
+ /// Sets the [`Color`] of the [`Text`], if `Some`.
+ pub fn color_maybe(self, color: Option<impl Into<Color>>) -> Self
+ where
+ Theme::Class<'a>: From<StyleFn<'a, Theme>>,
+ {
+ let color = color.map(Into::into);
+
+ self.style(move |_theme| Style { color })
+ }
+
+ /// Sets the style class of the [`Text`].
+ #[cfg(feature = "advanced")]
+ #[must_use]
+ pub fn class(mut self, class: impl Into<Theme::Class<'a>>) -> Self {
+ self.class = class.into();
+ self
+ }
}
/// The internal state of a [`Text`] widget.
@@ -138,6 +154,7 @@ pub struct State<P: Paragraph>(P);
impl<'a, Message, Theme, Renderer> Widget<Message, Theme, Renderer>
for Text<'a, Theme, Renderer>
where
+ Theme: Catalog,
Renderer: text::Renderer,
{
fn tag(&self) -> tree::Tag {
@@ -182,15 +199,15 @@ where
tree: &Tree,
renderer: &mut Renderer,
theme: &Theme,
- style: &renderer::Style,
+ defaults: &renderer::Style,
layout: Layout<'_>,
_cursor_position: mouse::Cursor,
viewport: &Rectangle,
) {
let state = tree.state.downcast_ref::<State<Renderer::Paragraph>>();
- let appearance = (self.style)(theme);
+ let style = theme.style(&self.class);
- draw(renderer, style, layout, state, appearance, viewport);
+ draw(renderer, defaults, layout, state, style, viewport);
}
}
@@ -250,7 +267,7 @@ pub fn draw<Renderer>(
style: &renderer::Style,
layout: Layout<'_>,
state: &State<Renderer::Paragraph>,
- appearance: Appearance,
+ appearance: Style,
viewport: &Rectangle,
) where
Renderer: text::Renderer,
@@ -281,7 +298,7 @@ pub fn draw<Renderer>(
impl<'a, Message, Theme, Renderer> From<Text<'a, Theme, Renderer>>
for Element<'a, Message, Theme, Renderer>
where
- Theme: 'a,
+ Theme: Catalog + 'a,
Renderer: text::Renderer + 'a,
{
fn from(
@@ -293,7 +310,7 @@ where
impl<'a, Theme, Renderer> From<&'a str> for Text<'a, Theme, Renderer>
where
- Theme: DefaultStyle + 'a,
+ Theme: Catalog + 'a,
Renderer: text::Renderer,
{
fn from(content: &'a str) -> Self {
@@ -304,7 +321,7 @@ where
impl<'a, Message, Theme, Renderer> From<&'a str>
for Element<'a, Message, Theme, Renderer>
where
- Theme: DefaultStyle + 'a,
+ Theme: Catalog + 'a,
Renderer: text::Renderer + 'a,
{
fn from(content: &'a str) -> Self {
@@ -314,30 +331,38 @@ where
/// The appearance of some text.
#[derive(Debug, Clone, Copy, Default)]
-pub struct Appearance {
+pub struct Style {
/// The [`Color`] of the text.
///
/// The default, `None`, means using the inherited color.
pub color: Option<Color>,
}
-/// The style of some [`Text`].
-pub type Style<'a, Theme> = Box<dyn Fn(&Theme) -> Appearance + 'a>;
+/// The theme catalog of a [`Text`].
+pub trait Catalog: Sized {
+ /// The item class of this [`Catalog`].
+ type Class<'a>;
-/// The default style of some [`Text`].
-pub trait DefaultStyle {
- /// Returns the default style of some [`Text`].
- fn default_style(&self) -> Appearance;
+ /// The default class produced by this [`Catalog`].
+ fn default<'a>() -> Self::Class<'a>;
+
+ /// The [`Style`] of a class with the given status.
+ fn style(&self, item: &Self::Class<'_>) -> Style;
}
-impl DefaultStyle for Theme {
- fn default_style(&self) -> Appearance {
- Appearance::default()
+/// A styling function for a [`Text`].
+///
+/// This is just a boxed closure: `Fn(&Theme, Status) -> Style`.
+pub type StyleFn<'a, Theme> = Box<dyn Fn(&Theme) -> Style + 'a>;
+
+impl Catalog for Theme {
+ type Class<'a> = StyleFn<'a, Self>;
+
+ fn default<'a>() -> Self::Class<'a> {
+ Box::new(|_theme| Style::default())
}
-}
-impl DefaultStyle for Color {
- fn default_style(&self) -> Appearance {
- Appearance { color: Some(*self) }
+ fn style(&self, class: &Self::Class<'_>) -> Style {
+ class(self)
}
}