iced icon indicating copy to clipboard operation
iced copied to clipboard

Add docs for how styling works in iced

Open Koranir opened this issue 1 year ago • 0 comments

It's difficult to understand how to change the styling of widgets in iced, so I've added a write-up to the crate docs that tries to explain how iced's styling system works.

Here's the section rendered:


Styling

In iced, each widget has a StyleSheet trait (at widget::_::StyleSheet) that governs how it is rendered onto the screen. This trait is implemented by the Theme associated type of the [Application] (which is returned by [Application::theme]) which allows styles to be dynamically updated based on the state of the application.

This, however, means that the individual widgets do not have much control over their styling, which is why most widgets have their StyleSheets include an associated Style generic type that can be set by a widget's style method. This Style generic is passed to the StyleSheet implementation and used to calculate the final Appearance.

Generally, Style is an enum that has a set of predefined styles and occasionally a custom style variant that can be given an arbitrary StyleSheet implementation for maximum flexibility, but any further than that requires a custom Theme to be created.

For example, take the Button widget.

The Button uses the button::StyleSheet trait for its styling, which is implemented by the default theme. The default theme's implementation defines the stylesheet's Style as [theme::Button], which is what should be passed to Button::style to change the theming of the button on the default theme.

The default theme defines a set of styles that the default theme has predefined the Appearance-returning method implementations for, as well as a Custom variant that takes a boxed implementor of the button StyleSheet.

Essentially, the application's Theme must implement the button's StyleSheet which has a method called according to the button's state with the application's button theme's Style that was either defaulted or set by Button::style, which finally produces the button::Appearance that the renderer uses to display the widget to the screen.

The theming for the other widgets are similar, but some are a bit simpler such as Text's default Style which only has the default text color or a custom [Color].

use iced::{widget::{button, text}, theme};
// To set the style of the button to a predefined 'Positive' style:
let positive_button = button("+").style(theme::Button::Positive);
// If you wish to radically change the theming of the application, use a different type
// for Application::Theme and implement custom stylesheets for the widgets you use on that.
let custom_button = button("-").style(theme::Button::Custom(Box::new({
    struct anon_theme;
    impl button::StyleSheet for anon_theme {
        type Style = iced::Theme;
        fn active(&self, style: &Self::Style) -> button::Appearance {
            // `match` on `style` if you want to change anything for different themes.
            button::Appearance {
                text_color: Color::new(1.0, 1.0, 0.0, 0.75),
                ..Default::default()
            }
        }
    }
    anon_theme
})));
// Text is easy to change the color for.
let custom_text = text("foo").style(theme::Text::Color(Color::new(1.0, 1.0, 0.0, 1.0)));

Koranir avatar Feb 21 '24 08:02 Koranir