summaryrefslogtreecommitdiffstats
path: root/native
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón <hector0193@gmail.com>2022-07-09 02:28:52 +0200
committerLibravatar GitHub <noreply@github.com>2022-07-09 02:28:52 +0200
commite053e25d2ccb17f7a162685a106a8bbd915a873f (patch)
tree5304f3ea2712e8889c7278ec5e57418f484d8f6c /native
parent66eb6263003c1bbedd1fd14d6b12f172d20a6211 (diff)
parent7105db97a53d90adf429091298f31c90974d8f08 (diff)
downloadiced-e053e25d2ccb17f7a162685a106a8bbd915a873f.tar.gz
iced-e053e25d2ccb17f7a162685a106a8bbd915a873f.tar.bz2
iced-e053e25d2ccb17f7a162685a106a8bbd915a873f.zip
Merge pull request #1362 from iced-rs/theming
Theming
Diffstat (limited to 'native')
-rw-r--r--native/src/element.rs24
-rw-r--r--native/src/lib.rs3
-rw-r--r--native/src/overlay.rs1
-rw-r--r--native/src/overlay/element.rs8
-rw-r--r--native/src/overlay/menu.rs79
-rw-r--r--native/src/program/state.rs14
-rw-r--r--native/src/renderer.rs3
-rw-r--r--native/src/renderer/null.rs4
-rw-r--r--native/src/user_interface.rs16
-rw-r--r--native/src/widget.rs1
-rw-r--r--native/src/widget/button.rs44
-rw-r--r--native/src/widget/checkbox.rs37
-rw-r--r--native/src/widget/column.rs10
-rw-r--r--native/src/widget/container.rs37
-rw-r--r--native/src/widget/image.rs1
-rw-r--r--native/src/widget/image/viewer.rs1
-rw-r--r--native/src/widget/pane_grid.rs50
-rw-r--r--native/src/widget/pane_grid/content.rs35
-rw-r--r--native/src/widget/pane_grid/title_bar.rs23
-rw-r--r--native/src/widget/pick_list.rs51
-rw-r--r--native/src/widget/progress_bar.rs39
-rw-r--r--native/src/widget/radio.rs46
-rw-r--r--native/src/widget/row.rs10
-rw-r--r--native/src/widget/rule.rs38
-rw-r--r--native/src/widget/scrollable.rs39
-rw-r--r--native/src/widget/slider.rs53
-rw-r--r--native/src/widget/space.rs1
-rw-r--r--native/src/widget/svg.rs1
-rw-r--r--native/src/widget/text.rs68
-rw-r--r--native/src/widget/text_input.rs54
-rw-r--r--native/src/widget/toggler.rs37
-rw-r--r--native/src/widget/tooltip.rs40
32 files changed, 602 insertions, 266 deletions
diff --git a/native/src/element.rs b/native/src/element.rs
index 119b7892..425bddc2 100644
--- a/native/src/element.rs
+++ b/native/src/element.rs
@@ -244,13 +244,20 @@ where
pub fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
viewport: &Rectangle,
) {
- self.widget
- .draw(renderer, style, layout, cursor_position, viewport)
+ self.widget.draw(
+ renderer,
+ theme,
+ style,
+ layout,
+ cursor_position,
+ viewport,
+ )
}
/// Returns the current [`mouse::Interaction`] of the [`Element`].
@@ -350,13 +357,20 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
viewport: &Rectangle,
) {
- self.widget
- .draw(renderer, style, layout, cursor_position, viewport)
+ self.widget.draw(
+ renderer,
+ theme,
+ style,
+ layout,
+ cursor_position,
+ viewport,
+ )
}
fn mouse_interaction(
@@ -444,6 +458,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
@@ -471,6 +486,7 @@ where
self.element.widget.draw(
renderer,
+ theme,
style,
layout,
cursor_position,
diff --git a/native/src/lib.rs b/native/src/lib.rs
index db60976f..2d0dd6ec 100644
--- a/native/src/lib.rs
+++ b/native/src/lib.rs
@@ -76,6 +76,8 @@ pub use iced_core::{
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;
@@ -93,5 +95,6 @@ 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/overlay.rs b/native/src/overlay.rs
index 86878f6a..792d2905 100644
--- a/native/src/overlay.rs
+++ b/native/src/overlay.rs
@@ -34,6 +34,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
diff --git a/native/src/overlay/element.rs b/native/src/overlay/element.rs
index 24c0fe01..de2e1f37 100644
--- a/native/src/overlay/element.rs
+++ b/native/src/overlay/element.rs
@@ -94,11 +94,13 @@ where
pub fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
) {
- self.overlay.draw(renderer, style, layout, cursor_position)
+ self.overlay
+ .draw(renderer, theme, style, layout, cursor_position)
}
}
@@ -173,10 +175,12 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
) {
- self.content.draw(renderer, style, layout, cursor_position)
+ self.content
+ .draw(renderer, theme, style, layout, cursor_position)
}
}
diff --git a/native/src/overlay/menu.rs b/native/src/overlay/menu.rs
index 13fa7beb..979a13c3 100644
--- a/native/src/overlay/menu.rs
+++ b/native/src/overlay/menu.rs
@@ -7,18 +7,22 @@ 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::Container;
use crate::{
Clipboard, Color, Element, Layout, Length, Padding, Point, Rectangle,
Shell, Size, Vector, Widget,
};
-pub use iced_style::menu::Style;
+pub use iced_style::menu::{Appearance, StyleSheet};
/// A list of selectable options.
#[allow(missing_debug_implementations)]
-pub struct Menu<'a, T, Renderer: text::Renderer> {
+pub struct Menu<'a, T, Renderer>
+where
+ Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet,
+{
state: &'a mut State,
options: &'a [T],
hovered_option: &'a mut Option<usize>,
@@ -27,13 +31,15 @@ pub struct Menu<'a, T, Renderer: text::Renderer> {
padding: Padding,
text_size: Option<u16>,
font: Renderer::Font,
- style: Style,
+ style: <Renderer::Theme as StyleSheet>::Style,
}
impl<'a, T, Renderer> Menu<'a, T, Renderer>
where
T: ToString + Clone,
Renderer: text::Renderer + 'a,
+ Renderer::Theme:
+ StyleSheet + container::StyleSheet + scrollable::StyleSheet,
{
/// Creates a new [`Menu`] with the given [`State`], a list of options, and
/// the message to produced when an option is selected.
@@ -81,7 +87,10 @@ where
}
/// Sets the style of the [`Menu`].
- pub fn style(mut self, style: impl Into<Style>) -> Self {
+ pub fn style(
+ mut self,
+ style: impl Into<<Renderer::Theme as StyleSheet>::Style>,
+ ) -> Self {
self.style = style.into();
self
}
@@ -117,17 +126,24 @@ impl State {
}
}
-struct Overlay<'a, Message, Renderer: text::Renderer> {
+struct Overlay<'a, Message, Renderer>
+where
+ Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet + container::StyleSheet,
+{
container: Container<'a, Message, Renderer>,
width: u16,
target_height: f32,
- style: Style,
+ style: <Renderer::Theme as StyleSheet>::Style,
}
-impl<'a, Message, Renderer: text::Renderer> Overlay<'a, Message, Renderer>
+impl<'a, Message, Renderer> Overlay<'a, Message, Renderer>
where
Message: 'a,
Renderer: 'a,
+ Renderer: text::Renderer,
+ Renderer::Theme:
+ StyleSheet + container::StyleSheet + scrollable::StyleSheet,
{
pub fn new<T>(menu: Menu<'a, T, Renderer>, target_height: f32) -> Self
where
@@ -153,9 +169,8 @@ where
font,
text_size,
padding,
- style: style.clone(),
- }))
- .padding(1);
+ style,
+ }));
Self {
container,
@@ -170,6 +185,7 @@ impl<'a, Message, Renderer> crate::Overlay<Message, Renderer>
for Overlay<'a, Message, Renderer>
where
Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet + container::StyleSheet,
{
fn layout(
&self,
@@ -241,35 +257,50 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
) {
+ let appearance = theme.appearance(self.style);
let bounds = layout.bounds();
renderer.fill_quad(
renderer::Quad {
- bounds,
- border_color: self.style.border_color,
- border_width: self.style.border_width,
+ bounds: Rectangle {
+ width: bounds.width - 1.0,
+ ..bounds
+ },
+ border_color: appearance.border_color,
+ border_width: appearance.border_width,
border_radius: 0.0,
},
- self.style.background,
+ appearance.background,
);
- self.container
- .draw(renderer, style, layout, cursor_position, &bounds);
+ self.container.draw(
+ renderer,
+ theme,
+ style,
+ layout,
+ cursor_position,
+ &bounds,
+ );
}
}
-struct List<'a, T, Renderer: text::Renderer> {
+struct List<'a, T, Renderer>
+where
+ Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet,
+{
options: &'a [T],
hovered_option: &'a mut Option<usize>,
last_selection: &'a mut Option<T>,
padding: Padding,
text_size: Option<u16>,
font: Renderer::Font,
- style: Style,
+ style: <Renderer::Theme as StyleSheet>::Style,
}
impl<'a, T, Message, Renderer> Widget<Message, Renderer>
@@ -277,6 +308,7 @@ impl<'a, T, Message, Renderer> Widget<Message, Renderer>
where
T: Clone + ToString,
Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet,
{
fn width(&self) -> Length {
Length::Fill
@@ -389,11 +421,13 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
_style: &renderer::Style,
layout: Layout<'_>,
_cursor_position: Point,
viewport: &Rectangle,
) {
+ let appearance = theme.appearance(self.style);
let bounds = layout.bounds();
let text_size = self.text_size.unwrap_or(renderer.default_size());
@@ -425,7 +459,7 @@ where
border_width: 0.0,
border_radius: 0.0,
},
- self.style.selected_background,
+ appearance.selected_background,
);
}
@@ -440,9 +474,9 @@ where
size: f32::from(text_size),
font: self.font.clone(),
color: if is_selected {
- self.style.selected_text_color
+ appearance.selected_text_color
} else {
- self.style.text_color
+ appearance.text_color
},
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Center,
@@ -457,6 +491,7 @@ where
T: ToString + Clone,
Message: 'a,
Renderer: 'a + text::Renderer,
+ Renderer::Theme: StyleSheet,
{
fn into(self) -> Element<'a, Message, Renderer> {
Element::new(self)
diff --git a/native/src/program/state.rs b/native/src/program/state.rs
index cb87a628..7ec2a04f 100644
--- a/native/src/program/state.rs
+++ b/native/src/program/state.rs
@@ -1,4 +1,6 @@
+use crate::application;
use crate::mouse;
+use crate::renderer;
use crate::user_interface::{self, UserInterface};
use crate::{Clipboard, Command, Debug, Event, Point, Program, Size};
@@ -19,6 +21,7 @@ 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.
@@ -86,6 +89,8 @@ where
bounds: Size,
cursor_position: Point,
renderer: &mut P::Renderer,
+ theme: &<P::Renderer as crate::Renderer>::Theme,
+ style: &renderer::Style,
clipboard: &mut dyn Clipboard,
debug: &mut Debug,
) -> Option<Command<P::Message>> {
@@ -115,7 +120,7 @@ where
if messages.is_empty() {
debug.draw_started();
self.mouse_interaction =
- user_interface.draw(renderer, cursor_position);
+ user_interface.draw(renderer, theme, style, cursor_position);
debug.draw_finished();
self.cache = Some(user_interface.into_cache());
@@ -147,7 +152,7 @@ where
debug.draw_started();
self.mouse_interaction =
- user_interface.draw(renderer, cursor_position);
+ user_interface.draw(renderer, theme, style, cursor_position);
debug.draw_finished();
self.cache = Some(user_interface.into_cache());
@@ -163,7 +168,10 @@ fn build_user_interface<'a, P: Program>(
renderer: &mut P::Renderer,
size: Size,
debug: &mut Debug,
-) -> UserInterface<'a, P::Message, P::Renderer> {
+) -> UserInterface<'a, P::Message, P::Renderer>
+where
+ <P::Renderer as crate::Renderer>::Theme: application::StyleSheet,
+{
debug.view_started();
let view = program.view();
debug.view_finished();
diff --git a/native/src/renderer.rs b/native/src/renderer.rs
index 73d2f401..a7305a55 100644
--- a/native/src/renderer.rs
+++ b/native/src/renderer.rs
@@ -9,6 +9,9 @@ use crate::{Background, Color, Element, Rectangle, Vector};
/// A component that can be used by widgets to draw themselves on a screen.
pub trait Renderer: Sized {
+ /// The supported theme of the [`Renderer`].
+ type Theme;
+
/// Lays out the elements of a user interface.
///
/// You should override this if you need to perform any operations before or
diff --git a/native/src/renderer/null.rs b/native/src/renderer/null.rs
index a5b2f277..c591f4e2 100644
--- a/native/src/renderer/null.rs
+++ b/native/src/renderer/null.rs
@@ -1,6 +1,6 @@
use crate::renderer::{self, Renderer};
use crate::text::{self, Text};
-use crate::{Background, Font, Point, Rectangle, Size, Vector};
+use crate::{Background, Font, Point, Rectangle, Size, Theme, Vector};
/// A renderer that does nothing.
///
@@ -16,6 +16,8 @@ impl Null {
}
impl Renderer for Null {
+ type Theme = Theme;
+
fn with_layer(&mut self, _bounds: Rectangle, _f: impl FnOnce(&mut Self)) {}
fn with_translation(
diff --git a/native/src/user_interface.rs b/native/src/user_interface.rs
index 2f2dc110..97a004e7 100644
--- a/native/src/user_interface.rs
+++ b/native/src/user_interface.rs
@@ -1,4 +1,5 @@
//! Implement your own event loop to drive a user interface.
+use crate::application;
use crate::event::{self, Event};
use crate::layout;
use crate::mouse;
@@ -28,6 +29,7 @@ pub struct UserInterface<'a, Message, Renderer> {
impl<'a, Message, Renderer> UserInterface<'a, Message, Renderer>
where
Renderer: crate::Renderer,
+ Renderer::Theme: application::StyleSheet,
{
/// Builds a user interface for an [`Element`].
///
@@ -301,8 +303,10 @@ where
/// [completing the last example](#example-1):
///
/// ```no_run
- /// use iced_native::{clipboard, Size, Point};
+ /// 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 {
@@ -349,7 +353,7 @@ where
/// );
///
/// // Draw the user interface
- /// let mouse_cursor = user_interface.draw(&mut renderer, cursor_position);
+ /// let mouse_cursor = user_interface.draw(&mut renderer, &Theme::default(), &renderer::Style::default(), cursor_position);
///
/// cache = user_interface.into_cache();
///
@@ -364,6 +368,8 @@ where
pub fn draw(
&mut self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
+ style: &renderer::Style,
cursor_position: Point,
) -> mouse::Interaction {
// TODO: Move to shell level (?)
@@ -395,7 +401,8 @@ where
self.root.widget.draw(
renderer,
- &renderer::Style::default(),
+ theme,
+ style,
Layout::new(&self.base),
base_cursor,
&viewport,
@@ -436,7 +443,8 @@ where
renderer.with_layer(overlay_bounds, |renderer| {
overlay.draw(
renderer,
- &renderer::Style::default(),
+ theme,
+ style,
Layout::new(layout),
cursor_position,
);
diff --git a/native/src/widget.rs b/native/src/widget.rs
index 8417dad1..9fe96e33 100644
--- a/native/src/widget.rs
+++ b/native/src/widget.rs
@@ -125,6 +125,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs
index b03d9f27..d4e88424 100644
--- a/native/src/widget/button.rs
+++ b/native/src/widget/button.rs
@@ -12,7 +12,7 @@ use crate::{
Rectangle, Shell, Vector, Widget,
};
-pub use iced_style::button::{Style, StyleSheet};
+pub use iced_style::button::{Appearance, StyleSheet};
/// A generic widget that produces a message when pressed.
///
@@ -55,20 +55,25 @@ pub use iced_style::button::{Style, StyleSheet};
/// }
/// ```
#[allow(missing_debug_implementations)]
-pub struct Button<'a, Message, Renderer> {
+pub struct Button<'a, Message, Renderer>
+where
+ Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet,
+{
state: &'a mut State,
content: Element<'a, Message, Renderer>,
on_press: Option<Message>,
width: Length,
height: Length,
padding: Padding,
- style_sheet: Box<dyn StyleSheet + 'a>,
+ style: <Renderer::Theme as StyleSheet>::Style,
}
impl<'a, Message, Renderer> Button<'a, Message, Renderer>
where
Message: Clone,
Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet,
{
/// Creates a new [`Button`] with some local [`State`] and the given
/// content.
@@ -83,7 +88,7 @@ where
width: Length::Shrink,
height: Length::Shrink,
padding: Padding::new(5),
- style_sheet: Default::default(),
+ style: Default::default(),
}
}
@@ -112,12 +117,12 @@ where
self
}
- /// Sets the style of the [`Button`].
+ /// Sets the style of this [`Button`].
pub fn style(
mut self,
- style_sheet: impl Into<Box<dyn StyleSheet + 'a>>,
+ style: <Renderer::Theme as StyleSheet>::Style,
) -> Self {
- self.style_sheet = style_sheet.into();
+ self.style = style;
self
}
}
@@ -195,23 +200,29 @@ pub fn draw<'a, Renderer: crate::Renderer>(
bounds: Rectangle,
cursor_position: Point,
is_enabled: bool,
- style_sheet: &dyn StyleSheet,
+ style_sheet: &dyn StyleSheet<
+ Style = <Renderer::Theme as StyleSheet>::Style,
+ >,
+ style: <Renderer::Theme as StyleSheet>::Style,
state: impl FnOnce() -> &'a State,
-) -> Style {
+) -> Appearance
+where
+ Renderer::Theme: StyleSheet,
+{
let is_mouse_over = bounds.contains(cursor_position);
let styling = if !is_enabled {
- style_sheet.disabled()
+ style_sheet.disabled(style)
} else if is_mouse_over {
let state = state();
if state.is_pressed {
- style_sheet.pressed()
+ style_sheet.pressed(style)
} else {
- style_sheet.hovered()
+ style_sheet.hovered(style)
}
} else {
- style_sheet.active()
+ style_sheet.active(style)
};
if styling.background.is_some() || styling.border_width > 0.0 {
@@ -287,6 +298,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>
where
Message: Clone,
Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet,
{
fn width(&self) -> Length {
self.width
@@ -354,6 +366,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
_style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
@@ -367,12 +380,14 @@ where
bounds,
cursor_position,
self.on_press.is_some(),
- self.style_sheet.as_ref(),
+ theme,
+ self.style,
|| &self.state,
);
self.content.draw(
renderer,
+ theme,
&renderer::Style {
text_color: styling.text_color,
},
@@ -397,6 +412,7 @@ impl<'a, Message, Renderer> From<Button<'a, Message, Renderer>>
where
Message: 'a + Clone,
Renderer: 'a + crate::Renderer,
+ Renderer::Theme: StyleSheet,
{
fn from(
button: Button<'a, Message, Renderer>,
diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs
index b6d920df..9e7f183a 100644
--- a/native/src/widget/checkbox.rs
+++ b/native/src/widget/checkbox.rs
@@ -12,7 +12,7 @@ use crate::{
Widget,
};
-pub use iced_style::checkbox::{Style, StyleSheet};
+pub use iced_style::checkbox::{Appearance, StyleSheet};
/// A box that can be checked.
///
@@ -32,7 +32,11 @@ pub use iced_style::checkbox::{Style, 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: text::Renderer> {
+pub struct Checkbox<'a, Message, Renderer>
+where
+ Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet + widget::text::StyleSheet,
+{
is_checked: bool,
on_toggle: Box<dyn Fn(bool) -> Message + 'a>,
label: String,
@@ -41,10 +45,14 @@ pub struct Checkbox<'a, Message, Renderer: text::Renderer> {
spacing: u16,
text_size: Option<u16>,
font: Renderer::Font,
- style_sheet: Box<dyn StyleSheet + 'a>,
+ style: <Renderer::Theme as StyleSheet>::Style,
}
-impl<'a, Message, Renderer: text::Renderer> Checkbox<'a, Message, Renderer> {
+impl<'a, Message, Renderer> Checkbox<'a, Message, Renderer>
+where
+ Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet + widget::text::StyleSheet,
+{
/// The default size of a [`Checkbox`].
const DEFAULT_SIZE: u16 = 20;
@@ -72,7 +80,7 @@ impl<'a, Message, Renderer: text::Renderer> Checkbox<'a, Message, Renderer> {
spacing: Self::DEFAULT_SPACING,
text_size: None,
font: Renderer::Font::default(),
- style_sheet: Default::default(),
+ style: Default::default(),
}
}
@@ -111,9 +119,9 @@ impl<'a, Message, Renderer: text::Renderer> Checkbox<'a, Message, Renderer> {
/// Sets the style of the [`Checkbox`].
pub fn style(
mut self,
- style_sheet: impl Into<Box<dyn StyleSheet + 'a>>,
+ style: impl Into<<Renderer::Theme as StyleSheet>::Style>,
) -> Self {
- self.style_sheet = style_sheet.into();
+ self.style = style.into();
self
}
}
@@ -122,6 +130,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>
for Checkbox<'a, Message, Renderer>
where
Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet + widget::text::StyleSheet,
{
fn width(&self) -> Length {
self.width
@@ -197,6 +206,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
@@ -208,9 +218,9 @@ where
let mut children = layout.children();
let custom_style = if is_mouse_over {
- self.style_sheet.hovered(self.is_checked)
+ theme.hovered(self.style, self.is_checked)
} else {
- self.style_sheet.active(self.is_checked)
+ theme.active(self.style, self.is_checked)
};
{
@@ -252,9 +262,11 @@ where
style,
label_layout,
&self.label,
- self.font.clone(),
self.text_size,
- custom_style.text_color,
+ self.font.clone(),
+ widget::text::Appearance {
+ color: custom_style.text_color,
+ },
alignment::Horizontal::Left,
alignment::Vertical::Center,
);
@@ -265,8 +277,9 @@ where
impl<'a, Message, Renderer> From<Checkbox<'a, Message, Renderer>>
for Element<'a, Message, Renderer>
where
- Renderer: 'a + text::Renderer,
Message: 'a,
+ Renderer: 'a + text::Renderer,
+ Renderer::Theme: StyleSheet + widget::text::StyleSheet,
{
fn from(
checkbox: Checkbox<'a, Message, Renderer>,
diff --git a/native/src/widget/column.rs b/native/src/widget/column.rs
index 268218b1..01ddd9f1 100644
--- a/native/src/widget/column.rs
+++ b/native/src/widget/column.rs
@@ -187,13 +187,21 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
viewport: &Rectangle,
) {
for (child, layout) in self.children.iter().zip(layout.children()) {
- child.draw(renderer, style, layout, cursor_position, viewport);
+ child.draw(
+ renderer,
+ theme,
+ style,
+ layout,
+ cursor_position,
+ viewport,
+ );
}
}
diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs
index 0e7c301e..493aa67b 100644
--- a/native/src/widget/container.rs
+++ b/native/src/widget/container.rs
@@ -12,13 +12,17 @@ use crate::{
use std::u32;
-pub use iced_style::container::{Style, StyleSheet};
+pub use iced_style::container::{Appearance, StyleSheet};
/// An element decorating some content.
///
/// It is normally used for alignment purposes.
#[allow(missing_debug_implementations)]
-pub struct Container<'a, Message, Renderer> {
+pub struct Container<'a, Message, Renderer>
+where
+ Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet,
+{
padding: Padding,
width: Length,
height: Length,
@@ -26,13 +30,14 @@ pub struct Container<'a, Message, Renderer> {
max_height: u32,
horizontal_alignment: alignment::Horizontal,
vertical_alignment: alignment::Vertical,
- style_sheet: Box<dyn StyleSheet + 'a>,
+ style: <Renderer::Theme as StyleSheet>::Style,
content: Element<'a, Message, Renderer>,
}
impl<'a, Message, Renderer> Container<'a, Message, Renderer>
where
Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet,
{
/// Creates an empty [`Container`].
pub fn new<T>(content: T) -> Self
@@ -47,7 +52,7 @@ where
max_height: u32::MAX,
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
- style_sheet: Default::default(),
+ style: Default::default(),
content: content.into(),
}
}
@@ -109,9 +114,9 @@ where
/// Sets the style of the [`Container`].
pub fn style(
mut self,
- style_sheet: impl Into<Box<dyn StyleSheet + 'a>>,
+ style: impl Into<<Renderer::Theme as StyleSheet>::Style>,
) -> Self {
- self.style_sheet = style_sheet.into();
+ self.style = style.into();
self
}
}
@@ -146,6 +151,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>
for Container<'a, Message, Renderer>
where
Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet,
{
fn width(&self) -> Length {
self.width
@@ -209,17 +215,19 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
renderer_style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
viewport: &Rectangle,
) {
- let style = self.style_sheet.style();
+ let style = theme.appearance(self.style);
draw_background(renderer, &style, layout.bounds());
self.content.draw(
renderer,
+ theme,
&renderer::Style {
text_color: style
.text_color
@@ -244,20 +252,20 @@ where
/// Draws the background of a [`Container`] given its [`Style`] and its `bounds`.
pub fn draw_background<Renderer>(
renderer: &mut Renderer,
- style: &Style,
+ appearance: &Appearance,
bounds: Rectangle,
) where
Renderer: crate::Renderer,
{
- if style.background.is_some() || style.border_width > 0.0 {
+ if appearance.background.is_some() || appearance.border_width > 0.0 {
renderer.fill_quad(
renderer::Quad {
bounds,
- border_radius: style.border_radius,
- border_width: style.border_width,
- border_color: style.border_color,
+ border_radius: appearance.border_radius,
+ border_width: appearance.border_width,
+ border_color: appearance.border_color,
},
- style
+ appearance
.background
.unwrap_or(Background::Color(Color::TRANSPARENT)),
);
@@ -267,8 +275,9 @@ pub fn draw_background<Renderer>(
impl<'a, Message, Renderer> From<Container<'a, Message, Renderer>>
for Element<'a, Message, Renderer>
where
- Renderer: 'a + crate::Renderer,
Message: 'a,
+ Renderer: 'a + crate::Renderer,
+ Renderer::Theme: StyleSheet,
{
fn from(
column: Container<'a, Message, Renderer>,
diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs
index 8e7a28e5..72075bd1 100644
--- a/native/src/widget/image.rs
+++ b/native/src/widget/image.rs
@@ -136,6 +136,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ _theme: &Renderer::Theme,
_style: &renderer::Style,
layout: Layout<'_>,
_cursor_position: Point,
diff --git a/native/src/widget/image/viewer.rs b/native/src/widget/image/viewer.rs
index 840b88e5..1aa75aa0 100644
--- a/native/src/widget/image/viewer.rs
+++ b/native/src/widget/image/viewer.rs
@@ -303,6 +303,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ _theme: &Renderer::Theme,
_style: &renderer::Style,
layout: Layout<'_>,
_cursor_position: Point,
diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs
index 0ceec83e..eb969dbf 100644
--- a/native/src/widget/pane_grid.rs
+++ b/native/src/widget/pane_grid.rs
@@ -36,6 +36,7 @@ use crate::mouse;
use crate::overlay;
use crate::renderer;
use crate::touch;
+use crate::widget::container;
use crate::{
Clipboard, Color, Element, Layout, Length, Point, Rectangle, Shell, Size,
Vector, Widget,
@@ -93,7 +94,11 @@ pub use iced_style::pane_grid::{Line, StyleSheet};
/// .on_resize(10, Message::PaneResized);
/// ```
#[allow(missing_debug_implementations)]
-pub struct PaneGrid<'a, Message, Renderer> {
+pub struct PaneGrid<'a, Message, Renderer>
+where
+ Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet + container::StyleSheet,
+{
state: &'a mut state::Internal,
action: &'a mut state::Action,
elements: Vec<(Pane, Content<'a, Message, Renderer>)>,
@@ -103,12 +108,13 @@ pub struct PaneGrid<'a, Message, Renderer> {
on_click: Option<Box<dyn Fn(Pane) -> Message + 'a>>,
on_drag: Option<Box<dyn Fn(DragEvent) -> Message + 'a>>,
on_resize: Option<(u16, Box<dyn Fn(ResizeEvent) -> Message + 'a>)>,
- style_sheet: Box<dyn StyleSheet + 'a>,
+ style: <Renderer::Theme as StyleSheet>::Style,
}
impl<'a, Message, Renderer> PaneGrid<'a, Message, Renderer>
where
Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet + container::StyleSheet,
{
/// Creates a [`PaneGrid`] with the given [`State`] and view function.
///
@@ -136,7 +142,7 @@ where
on_click: None,
on_drag: None,
on_resize: None,
- style_sheet: Default::default(),
+ style: Default::default(),
}
}
@@ -196,8 +202,11 @@ where
}
/// Sets the style of the [`PaneGrid`].
- pub fn style(mut self, style: impl Into<Box<dyn StyleSheet + 'a>>) -> Self {
- self.style_sheet = style.into();
+ pub fn style(
+ mut self,
+ style: impl Into<<Renderer::Theme as StyleSheet>::Style>,
+ ) -> Self {
+ self.style = style.into();
self
}
}
@@ -468,11 +477,12 @@ pub fn draw<Renderer, T>(
layout: Layout<'_>,
cursor_position: Point,
renderer: &mut Renderer,
- style: &renderer::Style,
+ theme: &Renderer::Theme,
+ default_style: &renderer::Style,
viewport: &Rectangle,
spacing: u16,
resize_leeway: Option<u16>,
- style_sheet: &dyn StyleSheet,
+ style: <Renderer::Theme as StyleSheet>::Style,
elements: impl Iterator<Item = (Pane, T)>,
draw_pane: impl Fn(
T,
@@ -484,6 +494,7 @@ pub fn draw<Renderer, T>(
),
) where
Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet,
{
let picked_pane = action.picked_pane();
@@ -545,7 +556,7 @@ pub fn draw<Renderer, T>(
draw_pane(
pane,
renderer,
- style,
+ default_style,
layout,
pane_cursor_position,
viewport,
@@ -558,7 +569,7 @@ pub fn draw<Renderer, T>(
draw_pane(
pane,
renderer,
- style,
+ default_style,
layout,
pane_cursor_position,
viewport,
@@ -569,9 +580,9 @@ pub fn draw<Renderer, T>(
if let Some((axis, split_region, is_picked)) = picked_split {
let highlight = if is_picked {
- style_sheet.picked_split()
+ theme.picked_split(style)
} else {
- style_sheet.hovered_split()
+ theme.hovered_split(style)
};
if let Some(highlight) = highlight {
@@ -649,6 +660,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>
for PaneGrid<'a, Message, Renderer>
where
Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet + container::StyleSheet,
{
fn width(&self) -> Length {
self.width
@@ -754,6 +766,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
@@ -765,14 +778,22 @@ where
layout,
cursor_position,
renderer,
+ theme,
style,
viewport,
self.spacing,
self.on_resize.as_ref().map(|(leeway, _)| *leeway),
- self.style_sheet.as_ref(),
+ self.style,
self.elements.iter().map(|(pane, content)| (*pane, content)),
|pane, renderer, style, layout, cursor_position, rectangle| {
- pane.draw(renderer, style, layout, cursor_position, rectangle);
+ pane.draw(
+ renderer,
+ theme,
+ style,
+ layout,
+ cursor_position,
+ rectangle,
+ );
},
)
}
@@ -793,8 +814,9 @@ where
impl<'a, Message, Renderer> From<PaneGrid<'a, Message, Renderer>>
for Element<'a, Message, Renderer>
where
- Renderer: 'a + crate::Renderer,
Message: 'a,
+ Renderer: 'a + crate::Renderer,
+ Renderer::Theme: StyleSheet + container::StyleSheet,
{
fn from(
pane_grid: PaneGrid<'a, Message, Renderer>,
diff --git a/native/src/widget/pane_grid/content.rs b/native/src/widget/pane_grid/content.rs
index 407f5458..4c9e65c9 100644
--- a/native/src/widget/pane_grid/content.rs
+++ b/native/src/widget/pane_grid/content.rs
@@ -11,22 +11,27 @@ use crate::{Clipboard, Element, Layout, Point, Rectangle, Shell, Size};
///
/// [`Pane`]: crate::widget::pane_grid::Pane
#[allow(missing_debug_implementations)]
-pub struct Content<'a, Message, Renderer> {
+pub struct Content<'a, Message, Renderer>
+where
+ Renderer: crate::Renderer,
+ Renderer::Theme: container::StyleSheet,
+{
title_bar: Option<TitleBar<'a, Message, Renderer>>,
body: Element<'a, Message, Renderer>,
- style_sheet: Box<dyn container::StyleSheet + 'a>,
+ style: <Renderer::Theme as container::StyleSheet>::Style,
}
impl<'a, Message, Renderer> Content<'a, Message, Renderer>
where
Renderer: crate::Renderer,
+ Renderer::Theme: container::StyleSheet,
{
/// Creates a new [`Content`] with the provided body.
pub fn new(body: impl Into<Element<'a, Message, Renderer>>) -> Self {
Self {
title_bar: None,
body: body.into(),
- style_sheet: Default::default(),
+ style: Default::default(),
}
}
@@ -42,9 +47,9 @@ where
/// Sets the style of the [`Content`].
pub fn style(
mut self,
- style_sheet: impl Into<Box<dyn container::StyleSheet + 'a>>,
+ style: impl Into<<Renderer::Theme as container::StyleSheet>::Style>,
) -> Self {
- self.style_sheet = style_sheet.into();
+ self.style = style.into();
self
}
}
@@ -52,6 +57,7 @@ where
impl<'a, Message, Renderer> Content<'a, Message, Renderer>
where
Renderer: crate::Renderer,
+ Renderer::Theme: container::StyleSheet,
{
/// Draws the [`Content`] with the provided [`Renderer`] and [`Layout`].
///
@@ -59,15 +65,18 @@ where
pub fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
viewport: &Rectangle,
) {
+ use container::StyleSheet;
+
let bounds = layout.bounds();
{
- let style = self.style_sheet.style();
+ let style = theme.appearance(self.style);
container::draw_background(renderer, &style, bounds);
}
@@ -81,6 +90,7 @@ where
title_bar.draw(
renderer,
+ theme,
style,
title_bar_layout,
cursor_position,
@@ -90,14 +100,21 @@ where
self.body.draw(
renderer,
+ theme,
style,
body_layout,
cursor_position,
viewport,
);
} else {
- self.body
- .draw(renderer, style, layout, cursor_position, viewport);
+ self.body.draw(
+ renderer,
+ theme,
+ style,
+ layout,
+ cursor_position,
+ viewport,
+ );
}
}
@@ -239,6 +256,7 @@ where
impl<'a, Message, Renderer> Draggable for &Content<'a, Message, Renderer>
where
Renderer: crate::Renderer,
+ Renderer::Theme: container::StyleSheet,
{
fn can_be_dragged_at(
&self,
@@ -260,6 +278,7 @@ impl<'a, T, Message, Renderer> From<T> for Content<'a, Message, Renderer>
where
T: Into<Element<'a, Message, Renderer>>,
Renderer: crate::Renderer,
+ Renderer::Theme: container::StyleSheet,
{
fn from(element: T) -> Self {
Self::new(element)
diff --git a/native/src/widget/pane_grid/title_bar.rs b/native/src/widget/pane_grid/title_bar.rs
index 6713724a..14c3ab4e 100644
--- a/native/src/widget/pane_grid/title_bar.rs
+++ b/native/src/widget/pane_grid/title_bar.rs
@@ -12,17 +12,22 @@ use crate::{
///
/// [`Pane`]: crate::widget::pane_grid::Pane
#[allow(missing_debug_implementations)]
-pub struct TitleBar<'a, Message, Renderer> {
+pub struct TitleBar<'a, Message, Renderer>
+where
+ Renderer: crate::Renderer,
+ Renderer::Theme: container::StyleSheet,
+{
content: Element<'a, Message, Renderer>,
controls: Option<Element<'a, Message, Renderer>>,
padding: Padding,
always_show_controls: bool,
- style_sheet: Box<dyn container::StyleSheet + 'a>,
+ style: <Renderer::Theme as container::StyleSheet>::Style,
}
impl<'a, Message, Renderer> TitleBar<'a, Message, Renderer>
where
Renderer: crate::Renderer,
+ Renderer::Theme: container::StyleSheet,
{
/// Creates a new [`TitleBar`] with the given content.
pub fn new<E>(content: E) -> Self
@@ -34,7 +39,7 @@ where
controls: None,
padding: Padding::ZERO,
always_show_controls: false,
- style_sheet: Default::default(),
+ style: Default::default(),
}
}
@@ -56,9 +61,9 @@ where
/// Sets the style of the [`TitleBar`].
pub fn style(
mut self,
- style: impl Into<Box<dyn container::StyleSheet + 'a>>,
+ style: impl Into<<Renderer::Theme as container::StyleSheet>::Style>,
) -> Self {
- self.style_sheet = style.into();
+ self.style = style.into();
self
}
@@ -79,6 +84,7 @@ where
impl<'a, Message, Renderer> TitleBar<'a, Message, Renderer>
where
Renderer: crate::Renderer,
+ Renderer::Theme: container::StyleSheet,
{
/// Draws the [`TitleBar`] with the provided [`Renderer`] and [`Layout`].
///
@@ -86,14 +92,17 @@ where
pub fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
inherited_style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
viewport: &Rectangle,
show_controls: bool,
) {
+ use container::StyleSheet;
+
let bounds = layout.bounds();
- let style = self.style_sheet.style();
+ let style = theme.appearance(self.style);
let inherited_style = renderer::Style {
text_color: style.text_color.unwrap_or(inherited_style.text_color),
};
@@ -118,6 +127,7 @@ where
}
controls.draw(
renderer,
+ theme,
&inherited_style,
controls_layout,
cursor_position,
@@ -129,6 +139,7 @@ where
if show_title {
self.content.draw(
renderer,
+ theme,
&inherited_style,
title_layout,
cursor_position,
diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs
index 0374aef7..c6cfcc01 100644
--- a/native/src/widget/pick_list.rs
+++ b/native/src/widget/pick_list.rs
@@ -9,19 +9,23 @@ 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::{
Clipboard, Element, Layout, Length, Padding, Point, Rectangle, Shell, Size,
Widget,
};
use std::borrow::Cow;
-pub use iced_style::pick_list::{Style, StyleSheet};
+pub use iced_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: text::Renderer>
+pub struct PickList<'a, T, Message, Renderer>
where
[T]: ToOwned<Owned = Vec<T>>,
+ Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet,
{
state: &'a mut State<T>,
on_selected: Box<dyn Fn(T) -> Message>,
@@ -32,7 +36,7 @@ where
padding: Padding,
text_size: Option<u16>,
font: Renderer::Font,
- style_sheet: Box<dyn StyleSheet + 'a>,
+ style: <Renderer::Theme as StyleSheet>::Style,
}
/// The local state of a [`PickList`].
@@ -64,11 +68,12 @@ impl<T> Default for State<T> {
}
}
-impl<'a, T: 'a, Message, Renderer: text::Renderer>
- PickList<'a, T, Message, Renderer>
+impl<'a, T: 'a, Message, Renderer> PickList<'a, T, Message, Renderer>
where
T: ToString + Eq,
[T]: ToOwned<Owned = Vec<T>>,
+ Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet,
{
/// The default padding of a [`PickList`].
pub const DEFAULT_PADDING: Padding = Padding::new(5);
@@ -92,7 +97,7 @@ where
text_size: None,
padding: Self::DEFAULT_PADDING,
font: Default::default(),
- style_sheet: Default::default(),
+ style: Default::default(),
}
}
@@ -129,9 +134,9 @@ where
/// Sets the style of the [`PickList`].
pub fn style(
mut self,
- style_sheet: impl Into<Box<dyn StyleSheet + 'a>>,
+ style: impl Into<<Renderer::Theme as StyleSheet>::Style>,
) -> Self {
- self.style_sheet = style_sheet.into();
+ self.style = style.into();
self
}
}
@@ -317,12 +322,13 @@ pub fn overlay<'a, T, Message, Renderer>(
text_size: Option<u16>,
font: Renderer::Font,
options: &'a [T],
- style_sheet: &dyn StyleSheet,
+ style: <Renderer::Theme as StyleSheet>::Style,
) -> Option<overlay::Element<'a, Message, Renderer>>
where
+ T: Clone + ToString,
Message: 'a,
Renderer: text::Renderer + 'a,
- T: Clone + ToString,
+ Renderer::Theme: StyleSheet,
{
if state.is_open {
let bounds = layout.bounds();
@@ -336,7 +342,7 @@ where
.width(bounds.width.round() as u16)
.padding(padding)
.font(font)
- .style(style_sheet.menu());
+ .style(style);
if let Some(text_size) = text_size {
menu = menu.text_size(text_size);
@@ -351,6 +357,7 @@ where
/// Draws a [`PickList`].
pub fn draw<T, Renderer>(
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
layout: Layout<'_>,
cursor_position: Point,
padding: Padding,
@@ -358,9 +365,10 @@ pub fn draw<T, Renderer>(
font: &Renderer::Font,
placeholder: Option<&str>,
selected: Option<&T>,
- style_sheet: &dyn StyleSheet,
+ style: <Renderer::Theme as StyleSheet>::Style,
) where
Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet,
T: ToString,
{
let bounds = layout.bounds();
@@ -368,9 +376,9 @@ pub fn draw<T, Renderer>(
let is_selected = selected.is_some();
let style = if is_mouse_over {
- style_sheet.hovered()
+ theme.hovered(style)
} else {
- style_sheet.active()
+ theme.active(style)
};
renderer.fill_quad(
@@ -430,6 +438,7 @@ where
[T]: ToOwned<Owned = Vec<T>>,
Message: 'static,
Renderer: text::Renderer + 'a,
+ Renderer::Theme: StyleSheet,
{
fn width(&self) -> Length {
self.width
@@ -490,6 +499,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
_style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
@@ -497,6 +507,7 @@ where
) {
draw(
renderer,
+ theme,
layout,
cursor_position,
self.padding,
@@ -504,7 +515,7 @@ where
&self.font,
self.placeholder.as_ref().map(String::as_str),
self.selected.as_ref(),
- self.style_sheet.as_ref(),
+ self.style,
)
}
@@ -520,7 +531,7 @@ where
self.text_size,
self.font.clone(),
&self.options,
- self.style_sheet.as_ref(),
+ self.style,
)
}
}
@@ -530,8 +541,14 @@ impl<'a, T: 'a, Message, Renderer> Into<Element<'a, Message, Renderer>>
where
T: Clone + ToString + Eq,
[T]: ToOwned<Owned = Vec<T>>,
- Renderer: text::Renderer + 'a,
Message: 'static,
+ Renderer: text::Renderer + 'a,
+ Renderer::Theme: StyleSheet
+ + container::StyleSheet
+ + scrollable::StyleSheet
+ + menu::StyleSheet,
+ <Renderer::Theme as StyleSheet>::Style:
+ Into<<Renderer::Theme as menu::StyleSheet>::Style>,
{
fn into(self) -> Element<'a, Message, Renderer> {
Element::new(self)
diff --git a/native/src/widget/progress_bar.rs b/native/src/widget/progress_bar.rs
index c26c38fa..4eb7438a 100644
--- a/native/src/widget/progress_bar.rs
+++ b/native/src/widget/progress_bar.rs
@@ -5,13 +5,13 @@ use crate::{Color, Element, Layout, Length, Point, Rectangle, Size, Widget};
use std::ops::RangeInclusive;
-pub use iced_style::progress_bar::{Style, StyleSheet};
+pub use iced_style::progress_bar::{Appearance, StyleSheet};
/// A bar that displays progress.
///
/// # Example
/// ```
-/// # use iced_native::widget::ProgressBar;
+/// # type ProgressBar = iced_native::widget::ProgressBar<iced_native::renderer::Null>;
/// let value = 50.0;
///
/// ProgressBar::new(0.0..=100.0, value);
@@ -19,15 +19,23 @@ pub use iced_style::progress_bar::{Style, 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<'a> {
+pub struct ProgressBar<Renderer>
+where
+ Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet,
+{
range: RangeInclusive<f32>,
value: f32,
width: Length,
height: Option<Length>,
- style_sheet: Box<dyn StyleSheet + 'a>,
+ style: <Renderer::Theme as StyleSheet>::Style,
}
-impl<'a> ProgressBar<'a> {
+impl<Renderer> ProgressBar<Renderer>
+where
+ Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet,
+{
/// The default height of a [`ProgressBar`].
pub const DEFAULT_HEIGHT: u16 = 30;
@@ -42,7 +50,7 @@ impl<'a> ProgressBar<'a> {
range,
width: Length::Fill,
height: None,
- style_sheet: Default::default(),
+ style: Default::default(),
}
}
@@ -61,16 +69,17 @@ impl<'a> ProgressBar<'a> {
/// Sets the style of the [`ProgressBar`].
pub fn style(
mut self,
- style_sheet: impl Into<Box<dyn StyleSheet + 'a>>,
+ style: impl Into<<Renderer::Theme as StyleSheet>::Style>,
) -> Self {
- self.style_sheet = style_sheet.into();
+ self.style = style.into();
self
}
}
-impl<'a, Message, Renderer> Widget<Message, Renderer> for ProgressBar<'a>
+impl<'a, Message, Renderer> Widget<Message, Renderer> for ProgressBar<Renderer>
where
Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet,
{
fn width(&self) -> Length {
self.width
@@ -97,6 +106,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
_style: &renderer::Style,
layout: Layout<'_>,
_cursor_position: Point,
@@ -112,7 +122,7 @@ where
/ (range_end - range_start)
};
- let style = self.style_sheet.style();
+ let style = theme.appearance(self.style);
renderer.fill_quad(
renderer::Quad {
@@ -141,13 +151,16 @@ where
}
}
-impl<'a, Message, Renderer> From<ProgressBar<'a>>
+impl<'a, Message, Renderer> From<ProgressBar<Renderer>>
for Element<'a, Message, Renderer>
where
- Renderer: 'a + crate::Renderer,
Message: 'a,
+ Renderer: 'a + crate::Renderer,
+ Renderer::Theme: StyleSheet,
{
- fn from(progress_bar: ProgressBar<'a>) -> Element<'a, Message, Renderer> {
+ fn from(
+ progress_bar: ProgressBar<Renderer>,
+ ) -> Element<'a, Message, Renderer> {
Element::new(progress_bar)
}
}
diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs
index 657ae786..ba45a0f4 100644
--- a/native/src/widget/radio.rs
+++ b/native/src/widget/radio.rs
@@ -12,14 +12,14 @@ use crate::{
Shell, Widget,
};
-pub use iced_style::radio::{Style, StyleSheet};
+pub use iced_style::radio::{Appearance, StyleSheet};
/// A circular button representing a choice.
///
/// # Example
/// ```
-/// # type Radio<'a, Message> =
-/// # iced_native::widget::Radio<'a, Message, iced_native::renderer::Null>;
+/// # type Radio<Message> =
+/// # iced_native::widget::Radio<Message, iced_native::renderer::Null>;
/// #
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// pub enum Choice {
@@ -41,7 +41,11 @@ pub use iced_style::radio::{Style, StyleSheet};
///
/// ![Radio buttons drawn by `iced_wgpu`](https://github.com/iced-rs/iced/blob/7760618fb112074bc40b148944521f312152012a/docs/images/radio.png?raw=true)
#[allow(missing_debug_implementations)]
-pub struct Radio<'a, Message, Renderer: text::Renderer> {
+pub struct Radio<Message, Renderer>
+where
+ Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet,
+{
is_selected: bool,
on_click: Message,
label: String,
@@ -50,12 +54,14 @@ pub struct Radio<'a, Message, Renderer: text::Renderer> {
spacing: u16,
text_size: Option<u16>,
font: Renderer::Font,
- style_sheet: Box<dyn StyleSheet + 'a>,
+ style: <Renderer::Theme as StyleSheet>::Style,
}
-impl<'a, Message, Renderer: text::Renderer> Radio<'a, Message, Renderer>
+impl<Message, Renderer> Radio<Message, Renderer>
where
Message: Clone,
+ Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet,
{
/// The default size of a [`Radio`] button.
pub const DEFAULT_SIZE: u16 = 28;
@@ -90,7 +96,7 @@ where
spacing: Self::DEFAULT_SPACING, //15
text_size: None,
font: Default::default(),
- style_sheet: Default::default(),
+ style: Default::default(),
}
}
@@ -127,18 +133,18 @@ where
/// Sets the style of the [`Radio`] button.
pub fn style(
mut self,
- style_sheet: impl Into<Box<dyn StyleSheet + 'a>>,
+ style: impl Into<<Renderer::Theme as StyleSheet>::Style>,
) -> Self {
- self.style_sheet = style_sheet.into();
+ self.style = style.into();
self
}
}
-impl<'a, Message, Renderer> Widget<Message, Renderer>
- for Radio<'a, Message, Renderer>
+impl<Message, Renderer> Widget<Message, Renderer> for Radio<Message, Renderer>
where
Message: Clone,
Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet + widget::text::StyleSheet,
{
fn width(&self) -> Length {
self.width
@@ -211,6 +217,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
@@ -222,9 +229,9 @@ where
let mut children = layout.children();
let custom_style = if is_mouse_over {
- self.style_sheet.hovered()
+ theme.hovered(self.style)
} else {
- self.style_sheet.active()
+ theme.active(self.style)
};
{
@@ -270,9 +277,11 @@ where
style,
label_layout,
&self.label,
- self.font.clone(),
self.text_size,
- custom_style.text_color,
+ self.font.clone(),
+ widget::text::Appearance {
+ color: custom_style.text_color,
+ },
alignment::Horizontal::Left,
alignment::Vertical::Center,
);
@@ -280,15 +289,14 @@ where
}
}
-impl<'a, Message, Renderer> From<Radio<'a, Message, Renderer>>
+impl<'a, Message, Renderer> From<Radio<Message, Renderer>>
for Element<'a, Message, Renderer>
where
Message: 'a + Clone,
Renderer: 'a + text::Renderer,
+ Renderer::Theme: StyleSheet + widget::text::StyleSheet,
{
- fn from(
- radio: Radio<'a, Message, Renderer>,
- ) -> Element<'a, Message, Renderer> {
+ fn from(radio: Radio<Message, Renderer>) -> Element<'a, Message, Renderer> {
Element::new(radio)
}
}
diff --git a/native/src/widget/row.rs b/native/src/widget/row.rs
index 7a7c70c6..9cff74c6 100644
--- a/native/src/widget/row.rs
+++ b/native/src/widget/row.rs
@@ -187,13 +187,21 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
viewport: &Rectangle,
) {
for (child, layout) in self.children.iter().zip(layout.children()) {
- child.draw(renderer, style, layout, cursor_position, viewport);
+ child.draw(
+ renderer,
+ theme,
+ style,
+ layout,
+ cursor_position,
+ viewport,
+ );
}
}
diff --git a/native/src/widget/rule.rs b/native/src/widget/rule.rs
index 69619583..26285df4 100644
--- a/native/src/widget/rule.rs
+++ b/native/src/widget/rule.rs
@@ -3,25 +3,33 @@ use crate::layout;
use crate::renderer;
use crate::{Color, Element, Layout, Length, Point, Rectangle, Size, Widget};
-pub use iced_style::rule::{FillMode, Style, StyleSheet};
+pub use iced_style::rule::{Appearance, FillMode, StyleSheet};
/// Display a horizontal or vertical rule for dividing content.
#[allow(missing_debug_implementations)]
-pub struct Rule<'a> {
+pub struct Rule<Renderer>
+where
+ Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet,
+{
width: Length,
height: Length,
is_horizontal: bool,
- style_sheet: Box<dyn StyleSheet + 'a>,
+ style: <Renderer::Theme as StyleSheet>::Style,
}
-impl<'a> Rule<'a> {
+impl<Renderer> Rule<Renderer>
+where
+ Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet,
+{
/// Creates a horizontal [`Rule`] with the given height.
pub fn horizontal(height: u16) -> Self {
Rule {
width: Length::Fill,
height: Length::Units(height),
is_horizontal: true,
- style_sheet: Default::default(),
+ style: Default::default(),
}
}
@@ -31,23 +39,24 @@ impl<'a> Rule<'a> {
width: Length::from(Length::Units(width)),
height: Length::Fill,
is_horizontal: false,
- style_sheet: Default::default(),
+ style: Default::default(),
}
}
/// Sets the style of the [`Rule`].
pub fn style(
mut self,
- style_sheet: impl Into<Box<dyn StyleSheet + 'a>>,
+ style: impl Into<<Renderer::Theme as StyleSheet>::Style>,
) -> Self {
- self.style_sheet = style_sheet.into();
+ self.style = style.into();
self
}
}
-impl<'a, Message, Renderer> Widget<Message, Renderer> for Rule<'a>
+impl<Message, Renderer> Widget<Message, Renderer> for Rule<Renderer>
where
Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet,
{
fn width(&self) -> Length {
self.width
@@ -70,13 +79,14 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
_style: &renderer::Style,
layout: Layout<'_>,
_cursor_position: Point,
_viewport: &Rectangle,
) {
let bounds = layout.bounds();
- let style = self.style_sheet.style();
+ let style = theme.style(self.style);
let bounds = if self.is_horizontal {
let line_y = (bounds.y + (bounds.height / 2.0)
@@ -120,12 +130,14 @@ where
}
}
-impl<'a, Message, Renderer> From<Rule<'a>> for Element<'a, Message, Renderer>
+impl<'a, Message, Renderer> From<Rule<Renderer>>
+ for Element<'a, Message, Renderer>
where
- Renderer: 'a + crate::Renderer,
Message: 'a,
+ Renderer: 'a + crate::Renderer,
+ Renderer::Theme: StyleSheet,
{
- fn from(rule: Rule<'a>) -> Element<'a, Message, Renderer> {
+ fn from(rule: Rule<Renderer>) -> Element<'a, Message, Renderer> {
Element::new(rule)
}
}
diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs
index 8958f6da..5d550315 100644
--- a/native/src/widget/scrollable.rs
+++ b/native/src/widget/scrollable.rs
@@ -25,7 +25,11 @@ pub mod style {
/// 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>
+where
+ Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet,
+{
state: &'a mut State,
height: Length,
max_height: u32,
@@ -34,10 +38,14 @@ pub struct Scrollable<'a, Message, Renderer> {
scroller_width: u16,
content: Column<'a, Message, Renderer>,
on_scroll: Option<Box<dyn Fn(f32) -> Message + 'a>>,
- style_sheet: Box<dyn StyleSheet + 'a>,
+ style: <Renderer::Theme as StyleSheet>::Style,
}
-impl<'a, Message, Renderer: crate::Renderer> Scrollable<'a, Message, Renderer> {
+impl<'a, Message, Renderer> Scrollable<'a, Message, Renderer>
+where
+ Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet,
+{
/// Creates a new [`Scrollable`] with the given [`State`].
pub fn new(state: &'a mut State) -> Self {
Scrollable {
@@ -49,7 +57,7 @@ impl<'a, Message, Renderer: crate::Renderer> Scrollable<'a, Message, Renderer> {
scroller_width: 10,
content: Column::new(),
on_scroll: None,
- style_sheet: Default::default(),
+ style: Default::default(),
}
}
@@ -132,9 +140,9 @@ impl<'a, Message, Renderer: crate::Renderer> Scrollable<'a, Message, Renderer> {
/// Sets the style of the [`Scrollable`] .
pub fn style(
mut self,
- style_sheet: impl Into<Box<dyn StyleSheet + 'a>>,
+ style: impl Into<<Renderer::Theme as StyleSheet>::Style>,
) -> Self {
- self.style_sheet = style_sheet.into();
+ self.style = style.into();
self
}
@@ -428,15 +436,17 @@ pub fn mouse_interaction(
pub fn draw<Renderer>(
state: &State,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
layout: Layout<'_>,
cursor_position: Point,
scrollbar_width: u16,
scrollbar_margin: u16,
scroller_width: u16,
- style_sheet: &dyn StyleSheet,
+ style: <Renderer::Theme as StyleSheet>::Style,
draw_content: impl FnOnce(&mut Renderer, Layout<'_>, Point, &Rectangle),
) where
Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet,
{
let bounds = layout.bounds();
let content_layout = layout.children().next().unwrap();
@@ -482,11 +492,11 @@ pub fn draw<Renderer>(
});
let style = if state.is_scroller_grabbed() {
- style_sheet.dragging()
+ theme.dragging(style)
} else if is_mouse_over_scrollbar {
- style_sheet.hovered()
+ theme.hovered(style)
} else {
- style_sheet.active()
+ theme.active(style)
};
let is_scrollbar_visible =
@@ -618,6 +628,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>
for Scrollable<'a, Message, Renderer>
where
Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet,
{
fn width(&self) -> Length {
Widget::<Message, Renderer>::width(&self.content)
@@ -702,6 +713,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
@@ -710,15 +722,17 @@ where
draw(
&self.state,
renderer,
+ theme,
layout,
cursor_position,
self.scrollbar_width,
self.scrollbar_margin,
self.scroller_width,
- self.style_sheet.as_ref(),
+ self.style,
|renderer, layout, cursor_position, viewport| {
self.content.draw(
renderer,
+ theme,
style,
layout,
cursor_position,
@@ -914,8 +928,9 @@ struct Scroller {
impl<'a, Message, Renderer> From<Scrollable<'a, Message, Renderer>>
for Element<'a, Message, Renderer>
where
- Renderer: 'a + crate::Renderer,
Message: 'a,
+ Renderer: 'a + crate::Renderer,
+ Renderer::Theme: StyleSheet,
{
fn from(
scrollable: Scrollable<'a, Message, Renderer>,
diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs
index f2e84ea9..bda31327 100644
--- a/native/src/widget/slider.rs
+++ b/native/src/widget/slider.rs
@@ -13,7 +13,7 @@ use crate::{
use std::ops::RangeInclusive;
-pub use iced_style::slider::{Handle, HandleShape, Style, StyleSheet};
+pub use iced_style::slider::{Appearance, Handle, HandleShape, StyleSheet};
/// An horizontal bar and a handle that selects a single value from a range of
/// values.
@@ -25,8 +25,10 @@ pub use iced_style::slider::{Handle, HandleShape, Style, StyleSheet};
///
/// # Example
/// ```
-/// # use iced_native::widget::slider::{self, Slider};
+/// # use iced_native::widget::slider;
+/// # use iced_native::renderer::Null;
/// #
+/// # type Slider<'a, T, Message> = slider::Slider<'a, T, Message, Null>;
/// #[derive(Clone)]
/// pub enum Message {
/// SliderChanged(f32),
@@ -40,7 +42,11 @@ pub use iced_style::slider::{Handle, HandleShape, Style, StyleSheet};
///
/// ![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> {
+pub struct Slider<'a, T, Message, Renderer>
+where
+ Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet,
+{
state: &'a mut State,
range: RangeInclusive<T>,
step: T,
@@ -49,13 +55,15 @@ pub struct Slider<'a, T, Message> {
on_release: Option<Message>,
width: Length,
height: u16,
- style_sheet: Box<dyn StyleSheet + 'a>,
+ style: <Renderer::Theme as StyleSheet>::Style,
}
-impl<'a, T, Message> Slider<'a, T, Message>
+impl<'a, T, Message, Renderer> Slider<'a, T, Message, Renderer>
where
T: Copy + From<u8> + std::cmp::PartialOrd,
Message: Clone,
+ Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet,
{
/// The default height of a [`Slider`].
pub const DEFAULT_HEIGHT: u16 = 22;
@@ -99,7 +107,7 @@ where
on_release: None,
width: Length::Fill,
height: Self::DEFAULT_HEIGHT,
- style_sheet: Default::default(),
+ style: Default::default(),
}
}
@@ -129,9 +137,9 @@ where
/// Sets the style of the [`Slider`].
pub fn style(
mut self,
- style_sheet: impl Into<Box<dyn StyleSheet + 'a>>,
+ style: impl Into<<Renderer::Theme as StyleSheet>::Style>,
) -> Self {
- self.style_sheet = style_sheet.into();
+ self.style = style.into();
self
}
@@ -230,26 +238,29 @@ where
}
/// Draws a [`Slider`].
-pub fn draw<T>(
- renderer: &mut impl crate::Renderer,
+pub fn draw<T, R>(
+ renderer: &mut R,
layout: Layout<'_>,
cursor_position: Point,
state: &State,
value: T,
range: &RangeInclusive<T>,
- style_sheet: &dyn StyleSheet,
+ style_sheet: &dyn StyleSheet<Style = <R::Theme as StyleSheet>::Style>,
+ style: <R::Theme as StyleSheet>::Style,
) where
T: Into<f64> + Copy,
+ R: crate::Renderer,
+ R::Theme: StyleSheet,
{
let bounds = layout.bounds();
let is_mouse_over = bounds.contains(cursor_position);
let style = if state.is_dragging {
- style_sheet.dragging()
+ style_sheet.dragging(style)
} else if is_mouse_over {
- style_sheet.hovered()
+ style_sheet.hovered(style)
} else {
- style_sheet.active()
+ style_sheet.active(style)
};
let rail_y = bounds.y + (bounds.height / 2.0).round();
@@ -357,11 +368,12 @@ impl State {
}
impl<'a, T, Message, Renderer> Widget<Message, Renderer>
- for Slider<'a, T, Message>
+ for Slider<'a, T, Message, Renderer>
where
T: Copy + Into<f64> + num_traits::FromPrimitive,
Message: Clone,
Renderer: crate::Renderer,
+ Renderer::Theme: StyleSheet,
{
fn width(&self) -> Length {
self.width
@@ -410,6 +422,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
_style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
@@ -422,7 +435,8 @@ where
&self.state,
self.value,
&self.range,
- self.style_sheet.as_ref(),
+ theme,
+ self.style,
)
}
@@ -437,14 +451,17 @@ where
}
}
-impl<'a, T, Message, Renderer> From<Slider<'a, T, Message>>
+impl<'a, T, Message, Renderer> From<Slider<'a, T, Message, Renderer>>
for Element<'a, Message, Renderer>
where
T: 'a + Copy + Into<f64> + num_traits::FromPrimitive,
Message: 'a + Clone,
Renderer: 'a + crate::Renderer,
+ Renderer::Theme: StyleSheet,
{
- fn from(slider: Slider<'a, T, Message>) -> Element<'a, Message, Renderer> {
+ fn from(
+ slider: Slider<'a, T, Message, Renderer>,
+ ) -> Element<'a, Message, Renderer> {
Element::new(slider)
}
}
diff --git a/native/src/widget/space.rs b/native/src/widget/space.rs
index 4135d1b8..81338306 100644
--- a/native/src/widget/space.rs
+++ b/native/src/widget/space.rs
@@ -60,6 +60,7 @@ where
fn draw(
&self,
_renderer: &mut Renderer,
+ _theme: &Renderer::Theme,
_style: &renderer::Style,
_layout: Layout<'_>,
_cursor_position: Point,
diff --git a/native/src/widget/svg.rs b/native/src/widget/svg.rs
index 008ab356..76b3eb8b 100644
--- a/native/src/widget/svg.rs
+++ b/native/src/widget/svg.rs
@@ -110,6 +110,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ _theme: &Renderer::Theme,
_style: &renderer::Style,
layout: Layout<'_>,
_cursor_position: Point,
diff --git a/native/src/widget/text.rs b/native/src/widget/text.rs
index a7855c30..242247b0 100644
--- a/native/src/widget/text.rs
+++ b/native/src/widget/text.rs
@@ -3,45 +3,57 @@ use crate::alignment;
use crate::layout;
use crate::renderer;
use crate::text;
-use crate::{Color, Element, Layout, Length, Point, Rectangle, Size, Widget};
+use crate::{Element, Layout, Length, Point, Rectangle, Size, Widget};
+
+pub use iced_style::text::{Appearance, StyleSheet};
/// A paragraph of text.
///
/// # Example
///
/// ```
+/// # use iced_native::Color;
+/// #
/// # type Text = iced_native::widget::Text<iced_native::renderer::Null>;
/// #
/// Text::new("I <3 iced!")
-/// .color([0.0, 0.0, 1.0])
-/// .size(40);
+/// .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)
-#[derive(Debug)]
-pub struct Text<Renderer: text::Renderer> {
+#[allow(missing_debug_implementations)]
+pub struct Text<Renderer>
+where
+ Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet,
+{
content: String,
size: Option<u16>,
- color: Option<Color>,
- font: Renderer::Font,
width: Length,
height: Length,
horizontal_alignment: alignment::Horizontal,
vertical_alignment: alignment::Vertical,
+ font: Renderer::Font,
+ style: <Renderer::Theme as StyleSheet>::Style,
}
-impl<Renderer: text::Renderer> Text<Renderer> {
+impl<Renderer> Text<Renderer>
+where
+ Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet,
+{
/// Create a new fragment of [`Text`] with the given contents.
pub fn new<T: Into<String>>(label: T) -> Self {
Text {
content: label.into(),
size: None,
- color: None,
font: Default::default(),
width: Length::Shrink,
height: Length::Shrink,
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
+ style: Default::default(),
}
}
@@ -51,12 +63,6 @@ impl<Renderer: text::Renderer> Text<Renderer> {
self
}
- /// Sets the [`Color`] of the [`Text`].
- pub fn color<C: Into<Color>>(mut self, color: C) -> Self {
- self.color = Some(color.into());
- self
- }
-
/// Sets the [`Font`] of the [`Text`].
///
/// [`Font`]: crate::text::Renderer::Font
@@ -65,6 +71,15 @@ impl<Renderer: text::Renderer> Text<Renderer> {
self
}
+ /// Sets the [`Color`] of the [`Text`].
+ pub fn style(
+ mut self,
+ style: impl Into<<Renderer::Theme as StyleSheet>::Style>,
+ ) -> Self {
+ self.style = style.into();
+ self
+ }
+
/// Sets the width of the [`Text`] boundaries.
pub fn width(mut self, width: Length) -> Self {
self.width = width;
@@ -99,6 +114,7 @@ impl<Renderer: text::Renderer> Text<Renderer> {
impl<Message, Renderer> Widget<Message, Renderer> for Text<Renderer>
where
Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet,
{
fn width(&self) -> Length {
self.width
@@ -130,6 +146,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
style: &renderer::Style,
layout: Layout<'_>,
_cursor_position: Point,
@@ -140,9 +157,9 @@ where
style,
layout,
&self.content,
- self.font.clone(),
self.size,
- self.color,
+ self.font.clone(),
+ theme.appearance(self.style),
self.horizontal_alignment,
self.vertical_alignment,
);
@@ -164,9 +181,9 @@ pub fn draw<Renderer>(
style: &renderer::Style,
layout: Layout<'_>,
content: &str,
- font: Renderer::Font,
size: Option<u16>,
- color: Option<Color>,
+ font: Renderer::Font,
+ appearance: Appearance,
horizontal_alignment: alignment::Horizontal,
vertical_alignment: alignment::Vertical,
) where
@@ -190,7 +207,7 @@ pub fn draw<Renderer>(
content,
size: f32::from(size.unwrap_or(renderer.default_size())),
bounds: Rectangle { x, y, ..bounds },
- color: color.unwrap_or(style.text_color),
+ color: appearance.color.unwrap_or(style.text_color),
font,
horizontal_alignment,
vertical_alignment,
@@ -201,23 +218,28 @@ impl<'a, Message, Renderer> From<Text<Renderer>>
for Element<'a, Message, Renderer>
where
Renderer: text::Renderer + 'a,
+ Renderer::Theme: StyleSheet,
{
fn from(text: Text<Renderer>) -> Element<'a, Message, Renderer> {
Element::new(text)
}
}
-impl<Renderer: text::Renderer> Clone for Text<Renderer> {
+impl<Renderer> Clone for Text<Renderer>
+where
+ Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet,
+{
fn clone(&self) -> Self {
Self {
content: self.content.clone(),
size: self.size,
- color: self.color,
- font: self.font.clone(),
width: self.width,
height: self.height,
horizontal_alignment: self.horizontal_alignment,
vertical_alignment: self.vertical_alignment,
+ font: self.font.clone(),
+ style: self.style,
}
}
}
diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs
index 5ecd68e9..d345cec3 100644
--- a/native/src/widget/text_input.rs
+++ b/native/src/widget/text_input.rs
@@ -24,7 +24,7 @@ use crate::{
Shell, Size, Vector, Widget,
};
-pub use iced_style::text_input::{Style, StyleSheet};
+pub use iced_style::text_input::{Appearance, StyleSheet};
/// A field that can be filled with text.
///
@@ -52,7 +52,11 @@ pub use iced_style::text_input::{Style, 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: text::Renderer> {
+pub struct TextInput<'a, Message, Renderer>
+where
+ Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet,
+{
state: &'a mut State,
placeholder: String,
value: Value,
@@ -63,13 +67,14 @@ pub struct TextInput<'a, Message, Renderer: text::Renderer> {
size: Option<u16>,
on_change: Box<dyn Fn(String) -> Message + 'a>,
on_submit: Option<Message>,
- style_sheet: Box<dyn StyleSheet + 'a>,
+ style: <Renderer::Theme as StyleSheet>::Style,
}
impl<'a, Message, Renderer> TextInput<'a, Message, Renderer>
where
Message: Clone,
Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet,
{
/// Creates a new [`TextInput`].
///
@@ -98,7 +103,7 @@ where
size: None,
on_change: Box::new(on_change),
on_submit: None,
- style_sheet: Default::default(),
+ style: Default::default(),
}
}
@@ -143,9 +148,9 @@ where
/// Sets the style of the [`TextInput`].
pub fn style(
mut self,
- style_sheet: impl Into<Box<dyn StyleSheet + 'a>>,
+ style: impl Into<<Renderer::Theme as StyleSheet>::Style>,
) -> Self {
- self.style_sheet = style_sheet.into();
+ self.style = style.into();
self
}
@@ -161,12 +166,14 @@ where
pub fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
layout: Layout<'_>,
cursor_position: Point,
value: Option<&Value>,
) {
draw(
renderer,
+ theme,
layout,
cursor_position,
&self.state,
@@ -175,7 +182,7 @@ where
self.size,
&self.font,
self.is_secure,
- self.style_sheet.as_ref(),
+ self.style,
)
}
}
@@ -575,6 +582,7 @@ where
/// [`Renderer`]: text::Renderer
pub fn draw<Renderer>(
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
layout: Layout<'_>,
cursor_position: Point,
state: &State,
@@ -583,9 +591,10 @@ pub fn draw<Renderer>(
size: Option<u16>,
font: &Renderer::Font,
is_secure: bool,
- style_sheet: &dyn StyleSheet,
+ style: <Renderer::Theme as StyleSheet>::Style,
) where
Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet,
{
let secure_value = is_secure.then(|| value.secure());
let value = secure_value.as_ref().unwrap_or(&value);
@@ -595,22 +604,22 @@ pub fn draw<Renderer>(
let is_mouse_over = bounds.contains(cursor_position);
- let style = if state.is_focused() {
- style_sheet.focused()
+ let appearance = if state.is_focused() {
+ theme.focused(style)
} else if is_mouse_over {
- style_sheet.hovered()
+ theme.hovered(style)
} else {
- style_sheet.active()
+ theme.active(style)
};
renderer.fill_quad(
renderer::Quad {
bounds,
- border_radius: style.border_radius,
- border_width: style.border_width,
- border_color: style.border_color,
+ border_radius: appearance.border_radius,
+ border_width: appearance.border_width,
+ border_color: appearance.border_color,
},
- style.background,
+ appearance.background,
);
let text = value.to_string();
@@ -642,7 +651,7 @@ pub fn draw<Renderer>(
border_width: 0.0,
border_color: Color::TRANSPARENT,
},
- style_sheet.value_color(),
+ theme.value_color(style),
)),
offset,
)
@@ -686,7 +695,7 @@ pub fn draw<Renderer>(
border_width: 0.0,
border_color: Color::TRANSPARENT,
},
- style_sheet.selection_color(),
+ theme.selection_color(style),
)),
if end == right {
right_offset
@@ -714,9 +723,9 @@ pub fn draw<Renderer>(
renderer.fill_text(Text {
content: if text.is_empty() { placeholder } else { &text },
color: if text.is_empty() {
- style_sheet.placeholder_color()
+ theme.placeholder_color(style)
} else {
- style_sheet.value_color()
+ theme.value_color(style)
},
font: font.clone(),
bounds: Rectangle {
@@ -756,6 +765,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>
where
Message: Clone,
Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet,
{
fn width(&self) -> Length {
self.width
@@ -812,12 +822,13 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
_style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
_viewport: &Rectangle,
) {
- self.draw(renderer, layout, cursor_position, None)
+ self.draw(renderer, theme, layout, cursor_position, None)
}
}
@@ -826,6 +837,7 @@ impl<'a, Message, Renderer> From<TextInput<'a, Message, Renderer>>
where
Message: 'a + Clone,
Renderer: 'a + text::Renderer,
+ Renderer::Theme: StyleSheet,
{
fn from(
text_input: TextInput<'a, Message, Renderer>,
diff --git a/native/src/widget/toggler.rs b/native/src/widget/toggler.rs
index 6d7592f3..0936c271 100644
--- a/native/src/widget/toggler.rs
+++ b/native/src/widget/toggler.rs
@@ -5,13 +5,13 @@ use crate::layout;
use crate::mouse;
use crate::renderer;
use crate::text;
-use crate::widget::{Row, Text};
+use crate::widget::{self, Row, Text};
use crate::{
Alignment, Clipboard, Element, Event, Layout, Length, Point, Rectangle,
Shell, Widget,
};
-pub use iced_style::toggler::{Style, StyleSheet};
+pub use iced_style::toggler::{Appearance, StyleSheet};
/// A toggler widget.
///
@@ -29,7 +29,11 @@ pub use iced_style::toggler::{Style, StyleSheet};
/// Toggler::new(is_active, String::from("Toggle me!"), |b| Message::TogglerToggled(b));
/// ```
#[allow(missing_debug_implementations)]
-pub struct Toggler<'a, Message, Renderer: text::Renderer> {
+pub struct Toggler<'a, Message, Renderer>
+where
+ Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet,
+{
is_active: bool,
on_toggle: Box<dyn Fn(bool) -> Message + 'a>,
label: Option<String>,
@@ -39,10 +43,14 @@ pub struct Toggler<'a, Message, Renderer: text::Renderer> {
text_alignment: alignment::Horizontal,
spacing: u16,
font: Renderer::Font,
- style_sheet: Box<dyn StyleSheet + 'a>,
+ style: <Renderer::Theme as StyleSheet>::Style,
}
-impl<'a, Message, Renderer: text::Renderer> Toggler<'a, Message, Renderer> {
+impl<'a, Message, Renderer> Toggler<'a, Message, Renderer>
+where
+ Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet,
+{
/// The default size of a [`Toggler`].
pub const DEFAULT_SIZE: u16 = 20;
@@ -72,7 +80,7 @@ impl<'a, Message, Renderer: text::Renderer> Toggler<'a, Message, Renderer> {
text_alignment: alignment::Horizontal::Left,
spacing: 0,
font: Renderer::Font::default(),
- style_sheet: Default::default(),
+ style: Default::default(),
}
}
@@ -117,9 +125,9 @@ impl<'a, Message, Renderer: text::Renderer> Toggler<'a, Message, Renderer> {
/// Sets the style of the [`Toggler`].
pub fn style(
mut self,
- style_sheet: impl Into<Box<dyn StyleSheet + 'a>>,
+ style: impl Into<<Renderer::Theme as StyleSheet>::Style>,
) -> Self {
- self.style_sheet = style_sheet.into();
+ self.style = style.into();
self
}
}
@@ -128,6 +136,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>
for Toggler<'a, Message, Renderer>
where
Renderer: text::Renderer,
+ Renderer::Theme: StyleSheet + widget::text::StyleSheet,
{
fn width(&self) -> Length {
self.width
@@ -208,6 +217,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
@@ -230,9 +240,9 @@ where
style,
label_layout,
&label,
- self.font.clone(),
self.text_size,
- None,
+ self.font.clone(),
+ Default::default(),
self.text_alignment,
alignment::Vertical::Center,
);
@@ -244,9 +254,9 @@ where
let is_mouse_over = bounds.contains(cursor_position);
let style = if is_mouse_over {
- self.style_sheet.hovered(self.is_active)
+ theme.hovered(self.style, self.is_active)
} else {
- self.style_sheet.active(self.is_active)
+ theme.active(self.style, self.is_active)
};
let border_radius = bounds.height as f32 / BORDER_RADIUS_RATIO;
@@ -300,8 +310,9 @@ where
impl<'a, Message, Renderer> From<Toggler<'a, Message, Renderer>>
for Element<'a, Message, Renderer>
where
- Renderer: 'a + text::Renderer,
Message: 'a,
+ Renderer: 'a + text::Renderer,
+ Renderer::Theme: StyleSheet + widget::text::StyleSheet,
{
fn from(
toggler: Toggler<'a, Message, Renderer>,
diff --git a/native/src/widget/tooltip.rs b/native/src/widget/tooltip.rs
index c929395f..0548e9da 100644
--- a/native/src/widget/tooltip.rs
+++ b/native/src/widget/tooltip.rs
@@ -4,6 +4,7 @@ use crate::layout;
use crate::mouse;
use crate::renderer;
use crate::text;
+use crate::widget;
use crate::widget::container;
use crate::widget::text::Text;
use crate::{
@@ -13,18 +14,23 @@ use crate::{
/// 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>
+where
+ Renderer: text::Renderer,
+ Renderer::Theme: container::StyleSheet + widget::text::StyleSheet,
+{
content: Element<'a, Message, Renderer>,
tooltip: Text<Renderer>,
position: Position,
- style_sheet: Box<dyn container::StyleSheet + 'a>,
gap: u16,
padding: u16,
+ style: <Renderer::Theme as container::StyleSheet>::Style,
}
impl<'a, Message, Renderer> Tooltip<'a, Message, Renderer>
where
Renderer: text::Renderer,
+ Renderer::Theme: container::StyleSheet + widget::text::StyleSheet,
{
/// The default padding of a [`Tooltip`] drawn by this renderer.
const DEFAULT_PADDING: u16 = 5;
@@ -41,9 +47,9 @@ where
content: content.into(),
tooltip: Text::new(tooltip.to_string()),
position,
- style_sheet: Default::default(),
gap: 0,
padding: Self::DEFAULT_PADDING,
+ style: Default::default(),
}
}
@@ -76,9 +82,9 @@ where
/// Sets the style of the [`Tooltip`].
pub fn style(
mut self,
- style_sheet: impl Into<Box<dyn container::StyleSheet + 'a>>,
+ style: impl Into<<Renderer::Theme as container::StyleSheet>::Style>,
) -> Self {
- self.style_sheet = style_sheet.into();
+ self.style = style.into();
self
}
}
@@ -99,8 +105,9 @@ pub enum Position {
}
/// Draws a [`Tooltip`].
-pub fn draw<Renderer: crate::Renderer>(
+pub fn draw<Renderer>(
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
inherited_style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
@@ -108,7 +115,7 @@ pub fn draw<Renderer: crate::Renderer>(
position: Position,
gap: u16,
padding: u16,
- style_sheet: &dyn container::StyleSheet,
+ style: <Renderer::Theme as container::StyleSheet>::Style,
layout_text: impl FnOnce(&Renderer, &layout::Limits) -> layout::Node,
draw_text: impl FnOnce(
&mut Renderer,
@@ -117,12 +124,17 @@ pub fn draw<Renderer: crate::Renderer>(
Point,
&Rectangle,
),
-) {
+) where
+ Renderer: crate::Renderer,
+ Renderer::Theme: container::StyleSheet,
+{
+ use container::StyleSheet;
+
let bounds = layout.bounds();
if bounds.contains(cursor_position) {
let gap = f32::from(gap);
- let style = style_sheet.style();
+ let style = theme.appearance(style);
let defaults = renderer::Style {
text_color: style.text_color.unwrap_or(inherited_style.text_color),
@@ -213,6 +225,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>
for Tooltip<'a, Message, Renderer>
where
Renderer: text::Renderer,
+ Renderer::Theme: container::StyleSheet + widget::text::StyleSheet,
{
fn width(&self) -> Length {
self.content.width()
@@ -267,6 +280,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ theme: &Renderer::Theme,
inherited_style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
@@ -274,6 +288,7 @@ where
) {
self.content.draw(
renderer,
+ theme,
inherited_style,
layout,
cursor_position,
@@ -284,6 +299,7 @@ where
draw(
renderer,
+ theme,
inherited_style,
layout,
cursor_position,
@@ -291,7 +307,7 @@ where
self.position,
self.gap,
self.padding,
- self.style_sheet.as_ref(),
+ self.style,
|renderer, limits| {
Widget::<(), Renderer>::layout(tooltip, renderer, limits)
},
@@ -299,6 +315,7 @@ where
Widget::<(), Renderer>::draw(
tooltip,
renderer,
+ theme,
defaults,
layout,
cursor_position,
@@ -312,8 +329,9 @@ where
impl<'a, Message, Renderer> From<Tooltip<'a, Message, Renderer>>
for Element<'a, Message, Renderer>
where
- Renderer: 'a + text::Renderer,
Message: 'a,
+ Renderer: 'a + text::Renderer,
+ Renderer::Theme: container::StyleSheet + widget::text::StyleSheet,
{
fn from(
tooltip: Tooltip<'a, Message, Renderer>,