summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/bezier_tool/src/main.rs9
-rw-r--r--examples/clock/src/main.rs19
-rw-r--r--examples/color_palette/src/main.rs9
-rw-r--r--examples/component/src/main.rs8
-rw-r--r--examples/counter/src/main.rs5
-rw-r--r--examples/custom_widget/src/main.rs1
-rw-r--r--examples/download_progress/src/main.rs9
-rw-r--r--examples/events/src/main.rs10
-rw-r--r--examples/game_of_life/src/main.rs53
-rw-r--r--examples/game_of_life/src/style.rs189
-rw-r--r--examples/geometry/src/main.rs11
-rw-r--r--examples/integration_opengl/src/controls.rs4
-rw-r--r--examples/integration_opengl/src/main.rs7
-rw-r--r--examples/integration_wgpu/src/controls.rs4
-rw-r--r--examples/integration_wgpu/src/main.rs7
-rw-r--r--examples/pane_grid/src/main.rs154
-rw-r--r--examples/pokedex/src/main.rs38
-rw-r--r--examples/pure/component/src/main.rs9
-rw-r--r--examples/pure/game_of_life/src/main.rs43
-rw-r--r--examples/pure/game_of_life/src/style.rs186
-rw-r--r--examples/pure/pane_grid/src/main.rs151
-rw-r--r--examples/pure/todos/src/main.rs72
-rw-r--r--examples/pure/tooltip/src/main.rs27
-rw-r--r--examples/pure/tour/src/main.rs45
-rw-r--r--examples/qr_code/src/main.rs5
-rw-r--r--examples/scrollable/src/main.rs44
-rw-r--r--examples/scrollable/src/style.rs191
-rw-r--r--examples/solar_system/src/main.rs30
-rw-r--r--examples/stopwatch/src/main.rs56
-rw-r--r--examples/styling/src/main.rs493
-rw-r--r--examples/system_information/src/main.rs3
-rw-r--r--examples/todos/src/main.rs72
-rw-r--r--examples/tooltip/src/main.rs26
-rw-r--r--examples/tour/src/main.rs57
-rw-r--r--examples/url_handler/src/main.rs8
-rw-r--r--examples/websocket/src/main.rs5
36 files changed, 377 insertions, 1683 deletions
diff --git a/examples/bezier_tool/src/main.rs b/examples/bezier_tool/src/main.rs
index 35b5182c..11e4828e 100644
--- a/examples/bezier_tool/src/main.rs
+++ b/examples/bezier_tool/src/main.rs
@@ -71,7 +71,7 @@ mod bezier {
use iced::{
canvas::event::{self, Event},
canvas::{self, Canvas, Cursor, Frame, Geometry, Path, Stroke},
- mouse, Element, Length, Point, Rectangle,
+ mouse, Element, Length, Point, Rectangle, Theme,
};
#[derive(Default)]
@@ -158,7 +158,12 @@ mod bezier {
}
}
- fn draw(&self, bounds: Rectangle, cursor: Cursor) -> Vec<Geometry> {
+ fn draw(
+ &self,
+ _theme: &Theme,
+ bounds: Rectangle,
+ cursor: Cursor,
+ ) -> Vec<Geometry> {
let content =
self.state.cache.draw(bounds.size(), |frame: &mut Frame| {
Curve::draw_all(self.curves, frame);
diff --git a/examples/clock/src/main.rs b/examples/clock/src/main.rs
index 3b8a1d6a..48b4cd7b 100644
--- a/examples/clock/src/main.rs
+++ b/examples/clock/src/main.rs
@@ -1,7 +1,10 @@
+use iced::canvas::{
+ self, Cache, Canvas, Cursor, Geometry, LineCap, Path, Stroke,
+};
+use iced::executor;
use iced::{
- canvas::{self, Cache, Canvas, Cursor, Geometry, LineCap, Path, Stroke},
- executor, Application, Color, Command, Container, Element, Length, Point,
- Rectangle, Settings, Subscription, Vector,
+ Application, Color, Command, Container, Element, Length, Point, Rectangle,
+ Settings, Subscription, Theme, Vector,
};
pub fn main() -> iced::Result {
@@ -22,8 +25,9 @@ enum Message {
}
impl Application for Clock {
- type Executor = executor::Default;
type Message = Message;
+ type Theme = Theme;
+ type Executor = executor::Default;
type Flags = ();
fn new(_flags: ()) -> (Self, Command<Message>) {
@@ -77,7 +81,12 @@ impl Application for Clock {
}
impl<Message> canvas::Program<Message> for Clock {
- fn draw(&self, bounds: Rectangle, _cursor: Cursor) -> Vec<Geometry> {
+ fn draw(
+ &self,
+ _theme: &Theme,
+ bounds: Rectangle,
+ _cursor: Cursor,
+ ) -> Vec<Geometry> {
let clock = self.clock.draw(bounds.size(), |frame| {
let center = frame.center();
let radius = frame.width().min(frame.height()) / 2.0;
diff --git a/examples/color_palette/src/main.rs b/examples/color_palette/src/main.rs
index f5fab251..16c87a75 100644
--- a/examples/color_palette/src/main.rs
+++ b/examples/color_palette/src/main.rs
@@ -236,7 +236,12 @@ impl Theme {
}
impl<Message> canvas::Program<Message> for Theme {
- fn draw(&self, bounds: Rectangle, _cursor: Cursor) -> Vec<Geometry> {
+ fn draw(
+ &self,
+ _theme: &iced::Theme,
+ bounds: Rectangle,
+ _cursor: Cursor,
+ ) -> Vec<Geometry> {
let theme = self.canvas_cache.draw(bounds.size(), |frame| {
self.draw(frame);
});
@@ -288,7 +293,7 @@ impl<C: 'static + ColorSpace + Copy> ColorPicker<C> {
range: RangeInclusive<f64>,
component: f32,
update: impl Fn(f32) -> C + 'static,
- ) -> Slider<f64, C> {
+ ) -> Slider<f64, C, iced::Renderer> {
Slider::new(state, range, f64::from(component), move |v| {
update(v as f32)
})
diff --git a/examples/component/src/main.rs b/examples/component/src/main.rs
index 39335cf1..b6ff0600 100644
--- a/examples/component/src/main.rs
+++ b/examples/component/src/main.rs
@@ -54,7 +54,7 @@ mod numeric_input {
use iced_native::text;
use iced_native::widget::button::{self, Button};
use iced_native::widget::text_input::{self, TextInput};
- use iced_native::widget::{Row, Text};
+ use iced_native::widget::{self, Row, Text};
use iced_native::{Element, Length};
pub struct NumericInput<'a, Message> {
@@ -95,6 +95,9 @@ mod numeric_input {
for NumericInput<'a, Message>
where
Renderer: 'a + text::Renderer,
+ Renderer::Theme: button::StyleSheet
+ + text_input::StyleSheet
+ + widget::text::StyleSheet,
{
type Event = Event;
@@ -172,6 +175,9 @@ mod numeric_input {
where
Message: 'a,
Renderer: text::Renderer + 'a,
+ Renderer::Theme: button::StyleSheet
+ + text_input::StyleSheet
+ + widget::text::StyleSheet,
{
fn from(numeric_input: NumericInput<'a, Message>) -> Self {
component::view(numeric_input)
diff --git a/examples/counter/src/main.rs b/examples/counter/src/main.rs
index 931cf5e1..e92f07f2 100644
--- a/examples/counter/src/main.rs
+++ b/examples/counter/src/main.rs
@@ -1,6 +1,5 @@
-use iced::{
- button, Alignment, Button, Column, Element, Sandbox, Settings, Text,
-};
+use iced::button::{self, Button};
+use iced::{Alignment, Column, Element, Sandbox, Settings, Text};
pub fn main() -> iced::Result {
Counter::run(Settings::default())
diff --git a/examples/custom_widget/src/main.rs b/examples/custom_widget/src/main.rs
index 28edf256..ce5306ba 100644
--- a/examples/custom_widget/src/main.rs
+++ b/examples/custom_widget/src/main.rs
@@ -46,6 +46,7 @@ mod circle {
fn draw(
&self,
renderer: &mut Renderer,
+ _theme: &Renderer::Theme,
_style: &renderer::Style,
layout: Layout<'_>,
_cursor_position: Point,
diff --git a/examples/download_progress/src/main.rs b/examples/download_progress/src/main.rs
index 21804a0a..4a801ba4 100644
--- a/examples/download_progress/src/main.rs
+++ b/examples/download_progress/src/main.rs
@@ -1,6 +1,8 @@
+use iced::button;
+use iced::executor;
use iced::{
- button, executor, Alignment, Application, Button, Column, Command,
- Container, Element, Length, ProgressBar, Settings, Subscription, Text,
+ Alignment, Application, Button, Column, Command, Container, Element,
+ Length, ProgressBar, Settings, Subscription, Text, Theme,
};
mod download;
@@ -24,8 +26,9 @@ pub enum Message {
}
impl Application for Example {
- type Executor = executor::Default;
type Message = Message;
+ type Theme = Theme;
+ type Executor = executor::Default;
type Flags = ();
fn new(_flags: ()) -> (Example, Command<Message>) {
diff --git a/examples/events/src/main.rs b/examples/events/src/main.rs
index 7f024c56..c87fbc72 100644
--- a/examples/events/src/main.rs
+++ b/examples/events/src/main.rs
@@ -1,6 +1,9 @@
+use iced::alignment;
+use iced::button;
+use iced::executor;
use iced::{
- alignment, button, executor, Alignment, Application, Button, Checkbox,
- Column, Command, Container, Element, Length, Settings, Subscription, Text,
+ Alignment, Application, Button, Checkbox, Column, Command, Container,
+ Element, Length, Settings, Subscription, Text, Theme,
};
use iced_native::{window, Event};
@@ -27,8 +30,9 @@ enum Message {
}
impl Application for Events {
- type Executor = executor::Default;
type Message = Message;
+ type Theme = Theme;
+ type Executor = executor::Default;
type Flags = ();
fn new(_flags: ()) -> (Events, Command<Message>) {
diff --git a/examples/game_of_life/src/main.rs b/examples/game_of_life/src/main.rs
index ab8b80e4..35399584 100644
--- a/examples/game_of_life/src/main.rs
+++ b/examples/game_of_life/src/main.rs
@@ -1,18 +1,18 @@
//! This example showcases an interactive version of the Game of Life, invented
//! by John Conway. It leverages a `Canvas` together with other widgets.
mod preset;
-mod style;
use grid::Grid;
use iced::button::{self, Button};
use iced::executor;
use iced::pick_list::{self, PickList};
use iced::slider::{self, Slider};
+use iced::theme::{self, Theme};
use iced::time;
use iced::window;
use iced::{
- Alignment, Application, Checkbox, Column, Command, Container, Element,
- Length, Row, Settings, Subscription, Text,
+ Alignment, Application, Checkbox, Column, Command, Element, Length, Row,
+ Settings, Subscription, Text,
};
use preset::Preset;
use std::time::{Duration, Instant};
@@ -55,6 +55,7 @@ enum Message {
impl Application for GameOfLife {
type Message = Message;
+ type Theme = Theme;
type Executor = executor::Default;
type Flags = ();
@@ -141,20 +142,19 @@ impl Application for GameOfLife {
self.grid.preset(),
);
- let content = Column::new()
+ Column::new()
.push(
self.grid
.view()
.map(move |message| Message::Grid(message, version)),
)
- .push(controls);
-
- Container::new(content)
- .width(Length::Fill)
- .height(Length::Fill)
- .style(style::Container)
+ .push(controls)
.into()
}
+
+ fn theme(&self) -> Theme {
+ Theme::Dark
+ }
}
mod grid {
@@ -163,7 +163,7 @@ mod grid {
alignment,
canvas::event::{self, Event},
canvas::{self, Cache, Canvas, Cursor, Frame, Geometry, Path, Text},
- mouse, Color, Element, Length, Point, Rectangle, Size, Vector,
+ mouse, Color, Element, Length, Point, Rectangle, Size, Theme, Vector,
};
use rustc_hash::{FxHashMap, FxHashSet};
use std::future::Future;
@@ -445,7 +445,12 @@ mod grid {
}
}
- fn draw(&self, bounds: Rectangle, cursor: Cursor) -> Vec<Geometry> {
+ fn draw(
+ &self,
+ _theme: &Theme,
+ bounds: Rectangle,
+ cursor: Cursor,
+ ) -> Vec<Geometry> {
let center = Vector::new(bounds.width / 2.0, bounds.height / 2.0);
let life = self.life_cache.draw(bounds.size(), |frame| {
@@ -836,27 +841,24 @@ impl Controls {
Text::new(if is_playing { "Pause" } else { "Play" }),
)
.on_press(Message::TogglePlayback)
- .style(style::Button),
+ .style(theme::Button::Primary),
)
.push(
Button::new(&mut self.next_button, Text::new("Next"))
.on_press(Message::Next)
- .style(style::Button),
+ .style(theme::Button::Secondary),
);
let speed_controls = Row::new()
.width(Length::Fill)
.align_items(Alignment::Center)
.spacing(10)
- .push(
- Slider::new(
- &mut self.speed_slider,
- 1.0..=1000.0,
- speed as f32,
- Message::SpeedChanged,
- )
- .style(style::Slider),
- )
+ .push(Slider::new(
+ &mut self.speed_slider,
+ 1.0..=1000.0,
+ speed as f32,
+ Message::SpeedChanged,
+ ))
.push(Text::new(format!("x{}", speed)).size(16));
Row::new()
@@ -879,13 +881,12 @@ impl Controls {
Message::PresetPicked,
)
.padding(8)
- .text_size(16)
- .style(style::PickList),
+ .text_size(16),
)
.push(
Button::new(&mut self.clear_button, Text::new("Clear"))
.on_press(Message::Clear)
- .style(style::Clear),
+ .style(theme::Button::Destructive),
)
.into()
}
diff --git a/examples/game_of_life/src/style.rs b/examples/game_of_life/src/style.rs
deleted file mode 100644
index be9a0e96..00000000
--- a/examples/game_of_life/src/style.rs
+++ /dev/null
@@ -1,189 +0,0 @@
-use iced::{button, container, pick_list, slider, Background, Color};
-
-const ACTIVE: Color = Color::from_rgb(
- 0x72 as f32 / 255.0,
- 0x89 as f32 / 255.0,
- 0xDA as f32 / 255.0,
-);
-
-const DESTRUCTIVE: Color = Color::from_rgb(
- 0xC0 as f32 / 255.0,
- 0x47 as f32 / 255.0,
- 0x47 as f32 / 255.0,
-);
-
-const HOVERED: Color = Color::from_rgb(
- 0x67 as f32 / 255.0,
- 0x7B as f32 / 255.0,
- 0xC4 as f32 / 255.0,
-);
-
-const BACKGROUND: Color = Color::from_rgb(
- 0x2F as f32 / 255.0,
- 0x31 as f32 / 255.0,
- 0x36 as f32 / 255.0,
-);
-
-pub struct Container;
-
-impl container::StyleSheet for Container {
- fn style(&self) -> container::Style {
- container::Style {
- background: Some(Background::Color(Color::from_rgb8(
- 0x36, 0x39, 0x3F,
- ))),
- text_color: Some(Color::WHITE),
- ..container::Style::default()
- }
- }
-}
-
-pub struct Button;
-
-impl button::StyleSheet for Button {
- fn active(&self) -> button::Style {
- button::Style {
- background: Some(Background::Color(ACTIVE)),
- border_radius: 3.0,
- text_color: Color::WHITE,
- ..button::Style::default()
- }
- }
-
- fn hovered(&self) -> button::Style {
- button::Style {
- background: Some(Background::Color(HOVERED)),
- text_color: Color::WHITE,
- ..self.active()
- }
- }
-
- fn pressed(&self) -> button::Style {
- button::Style {
- border_width: 1.0,
- border_color: Color::WHITE,
- ..self.hovered()
- }
- }
-}
-
-pub struct Clear;
-
-impl button::StyleSheet for Clear {
- fn active(&self) -> button::Style {
- button::Style {
- background: Some(Background::Color(DESTRUCTIVE)),
- border_radius: 3.0,
- text_color: Color::WHITE,
- ..button::Style::default()
- }
- }
-
- fn hovered(&self) -> button::Style {
- button::Style {
- background: Some(Background::Color(Color {
- a: 0.5,
- ..DESTRUCTIVE
- })),
- text_color: Color::WHITE,
- ..self.active()
- }
- }
-
- fn pressed(&self) -> button::Style {
- button::Style {
- border_width: 1.0,
- border_color: Color::WHITE,
- ..self.hovered()
- }
- }
-}
-
-pub struct Slider;
-
-impl slider::StyleSheet for Slider {
- fn active(&self) -> slider::Style {
- slider::Style {
- rail_colors: (ACTIVE, Color { a: 0.1, ..ACTIVE }),
- handle: slider::Handle {
- shape: slider::HandleShape::Circle { radius: 9.0 },
- color: ACTIVE,
- border_width: 0.0,
- border_color: Color::TRANSPARENT,
- },
- }
- }
-
- fn hovered(&self) -> slider::Style {
- let active = self.active();
-
- slider::Style {
- handle: slider::Handle {
- color: HOVERED,
- ..active.handle
- },
- ..active
- }
- }
-
- fn dragging(&self) -> slider::Style {
- let active = self.active();
-
- slider::Style {
- handle: slider::Handle {
- color: Color::from_rgb(0.85, 0.85, 0.85),
- ..active.handle
- },
- ..active
- }
- }
-}
-
-pub struct PickList;
-
-impl pick_list::StyleSheet for PickList {
- fn menu(&self) -> pick_list::Menu {
- pick_list::Menu {
- text_color: Color::WHITE,
- background: BACKGROUND.into(),
- border_width: 1.0,
- border_color: Color {
- a: 0.7,
- ..Color::BLACK
- },
- selected_background: Color {
- a: 0.5,
- ..Color::BLACK
- }
- .into(),
- selected_text_color: Color::WHITE,
- }
- }
-
- fn active(&self) -> pick_list::Style {
- pick_list::Style {
- text_color: Color::WHITE,
- background: BACKGROUND.into(),
- border_width: 1.0,
- border_color: Color {
- a: 0.6,
- ..Color::BLACK
- },
- border_radius: 2.0,
- icon_size: 0.5,
- ..pick_list::Style::default()
- }
- }
-
- fn hovered(&self) -> pick_list::Style {
- let active = self.active();
-
- pick_list::Style {
- border_color: Color {
- a: 0.9,
- ..Color::BLACK
- },
- ..active
- }
- }
-}
diff --git a/examples/geometry/src/main.rs b/examples/geometry/src/main.rs
index 58dfa3ad..ba4b808e 100644
--- a/examples/geometry/src/main.rs
+++ b/examples/geometry/src/main.rs
@@ -25,7 +25,7 @@ mod rainbow {
}
}
- impl<Message, B> Widget<Message, Renderer<B>> for Rainbow
+ impl<Message, B, T> Widget<Message, Renderer<B, T>> for Rainbow
where
B: Backend,
{
@@ -39,7 +39,7 @@ mod rainbow {
fn layout(
&self,
- _renderer: &Renderer<B>,
+ _renderer: &Renderer<B, T>,
limits: &layout::Limits,
) -> layout::Node {
let size = limits.width(Length::Fill).resolve(Size::ZERO);
@@ -49,7 +49,8 @@ mod rainbow {
fn draw(
&self,
- renderer: &mut Renderer<B>,
+ renderer: &mut Renderer<B, T>,
+ _theme: &T,
_style: &renderer::Style,
layout: Layout<'_>,
cursor_position: Point,
@@ -147,11 +148,11 @@ mod rainbow {
}
}
- impl<'a, Message, B> Into<Element<'a, Message, Renderer<B>>> for Rainbow
+ impl<'a, Message, B, T> Into<Element<'a, Message, Renderer<B, T>>> for Rainbow
where
B: Backend,
{
- fn into(self) -> Element<'a, Message, Renderer<B>> {
+ fn into(self) -> Element<'a, Message, Renderer<B, T>> {
Element::new(self)
}
}
diff --git a/examples/integration_opengl/src/controls.rs b/examples/integration_opengl/src/controls.rs
index f387b4e5..fdaa29d5 100644
--- a/examples/integration_opengl/src/controls.rs
+++ b/examples/integration_opengl/src/controls.rs
@@ -89,13 +89,13 @@ impl Program for Controls {
.spacing(10)
.push(
Text::new("Background color")
- .color(Color::WHITE),
+ .style(Color::WHITE),
)
.push(sliders)
.push(
Text::new(format!("{:?}", background_color))
.size(14)
- .color(Color::WHITE),
+ .style(Color::WHITE),
),
),
)
diff --git a/examples/integration_opengl/src/main.rs b/examples/integration_opengl/src/main.rs
index 1007b90f..1a78a493 100644
--- a/examples/integration_opengl/src/main.rs
+++ b/examples/integration_opengl/src/main.rs
@@ -12,7 +12,8 @@ use iced_glow::glow;
use iced_glow::{Backend, Renderer, Settings, Viewport};
use iced_glutin::conversion;
use iced_glutin::glutin;
-use iced_glutin::{program, Clipboard, Debug, Size};
+use iced_glutin::renderer;
+use iced_glutin::{program, Clipboard, Color, Debug, Size};
pub fn main() {
env_logger::init();
@@ -125,6 +126,10 @@ pub fn main() {
viewport.scale_factor(),
),
&mut renderer,
+ &iced_glow::Theme::Dark,
+ &renderer::Style {
+ text_color: Color::WHITE,
+ },
&mut clipboard,
&mut debug,
);
diff --git a/examples/integration_wgpu/src/controls.rs b/examples/integration_wgpu/src/controls.rs
index 9bca40eb..cb2c423f 100644
--- a/examples/integration_wgpu/src/controls.rs
+++ b/examples/integration_wgpu/src/controls.rs
@@ -100,13 +100,13 @@ impl Program for Controls {
.spacing(10)
.push(
Text::new("Background color")
- .color(Color::WHITE),
+ .style(Color::WHITE),
)
.push(sliders)
.push(
Text::new(format!("{:?}", background_color))
.size(14)
- .color(Color::WHITE),
+ .style(Color::WHITE),
)
.push(TextInput::new(
t,
diff --git a/examples/integration_wgpu/src/main.rs b/examples/integration_wgpu/src/main.rs
index 89ae03c6..3d27a0f0 100644
--- a/examples/integration_wgpu/src/main.rs
+++ b/examples/integration_wgpu/src/main.rs
@@ -5,7 +5,10 @@ use controls::Controls;
use scene::Scene;
use iced_wgpu::{wgpu, Backend, Renderer, Settings, Viewport};
-use iced_winit::{conversion, futures, program, winit, Clipboard, Debug, Size};
+use iced_winit::{
+ conversion, futures, program, renderer, winit, Clipboard, Color, Debug,
+ Size,
+};
use winit::{
dpi::PhysicalPosition,
@@ -188,6 +191,8 @@ pub fn main() {
viewport.scale_factor(),
),
&mut renderer,
+ &iced_wgpu::Theme::Dark,
+ &renderer::Style { text_color: Color::WHITE },
&mut clipboard,
&mut debug,
);
diff --git a/examples/pane_grid/src/main.rs b/examples/pane_grid/src/main.rs
index 2962ca25..5fbcea2c 100644
--- a/examples/pane_grid/src/main.rs
+++ b/examples/pane_grid/src/main.rs
@@ -4,6 +4,7 @@ use iced::executor;
use iced::keyboard;
use iced::pane_grid::{self, PaneGrid};
use iced::scrollable::{self, Scrollable};
+use iced::theme::{self, Theme};
use iced::{
Application, Color, Column, Command, Container, Element, Length, Row,
Settings, Size, Subscription, Text,
@@ -36,6 +37,7 @@ enum Message {
impl Application for Example {
type Message = Message;
+ type Theme = Theme;
type Executor = executor::Default;
type Flags = ();
@@ -171,14 +173,14 @@ impl Application for Example {
let text = if *is_pinned { "Unpin" } else { "Pin" };
let pin_button = Button::new(pin_button, Text::new(text).size(14))
.on_press(Message::TogglePin(id))
- .style(style::Button::Pin)
+ .style(theme::Button::Secondary)
.padding(3);
let title = Row::with_children(vec![
pin_button.into(),
Text::new("Pane").into(),
Text::new(content.id.to_string())
- .color(if is_focused {
+ .style(if is_focused {
PANE_ID_COLOR_FOCUSED
} else {
PANE_ID_COLOR_UNFOCUSED
@@ -191,9 +193,9 @@ impl Application for Example {
.controls(pane.controls.view(id, total_panes, *is_pinned))
.padding(10)
.style(if is_focused {
- style::TitleBar::Focused
+ style::title_bar_focused
} else {
- style::TitleBar::Active
+ style::title_bar_active
});
pane_grid::Content::new(Responsive::new(responsive, move |size| {
@@ -201,9 +203,9 @@ impl Application for Example {
}))
.title_bar(title_bar)
.style(if is_focused {
- style::Pane::Focused
+ style::pane_focused
} else {
- style::Pane::Active
+ style::pane_active
})
})
.width(Length::Fill)
@@ -309,7 +311,7 @@ impl Content {
..
} = self;
- let button = |state, label, message, style| {
+ let button = |state, label, message| {
Button::new(
state,
Text::new(label)
@@ -320,7 +322,6 @@ impl Content {
.width(Length::Fill)
.padding(8)
.on_press(message)
- .style(style)
};
let mut controls = Column::new()
@@ -330,22 +331,18 @@ impl Content {
split_horizontally,
"Split horizontally",
Message::Split(pane_grid::Axis::Horizontal, pane),
- style::Button::Primary,
))
.push(button(
split_vertically,
"Split vertically",
Message::Split(pane_grid::Axis::Vertical, pane),
- style::Button::Primary,
));
if total_panes > 1 && !is_pinned {
- controls = controls.push(button(
- close,
- "Close",
- Message::Close(pane),
- style::Button::Destructive,
- ));
+ controls = controls.push(
+ button(close, "Close", Message::Close(pane))
+ .style(theme::Button::Destructive),
+ );
}
let content = Scrollable::new(scroll)
@@ -379,8 +376,9 @@ impl Controls {
) -> Element<Message> {
let mut button =
Button::new(&mut self.close, Text::new("Close").size(14))
- .style(style::Button::Control)
+ .style(theme::Button::Destructive)
.padding(3);
+
if total_panes > 1 && !is_pinned {
button = button.on_press(Message::Close(pane));
}
@@ -389,111 +387,47 @@ impl Controls {
}
mod style {
- use crate::PANE_ID_COLOR_FOCUSED;
- use iced::{button, container, Background, Color, Vector};
-
- const SURFACE: Color = Color::from_rgb(
- 0xF2 as f32 / 255.0,
- 0xF3 as f32 / 255.0,
- 0xF5 as f32 / 255.0,
- );
-
- const ACTIVE: Color = Color::from_rgb(
- 0x72 as f32 / 255.0,
- 0x89 as f32 / 255.0,
- 0xDA as f32 / 255.0,
- );
-
- const HOVERED: Color = Color::from_rgb(
- 0x67 as f32 / 255.0,
- 0x7B as f32 / 255.0,
- 0xC4 as f32 / 255.0,
- );
-
- pub enum TitleBar {
- Active,
- Focused,
- }
+ use iced::{container, Theme};
- impl container::StyleSheet for TitleBar {
- fn style(&self) -> container::Style {
- let pane = match self {
- Self::Active => Pane::Active,
- Self::Focused => Pane::Focused,
- }
- .style();
+ pub fn title_bar_active(theme: &Theme) -> container::Appearance {
+ let palette = theme.extended_palette();
- container::Style {
- text_color: Some(Color::WHITE),
- background: Some(pane.border_color.into()),
- ..Default::default()
- }
+ container::Appearance {
+ text_color: Some(palette.background.strong.text),
+ background: Some(palette.background.strong.color.into()),
+ ..Default::default()
}
}
- pub enum Pane {
- Active,
- Focused,
- }
+ pub fn title_bar_focused(theme: &Theme) -> container::Appearance {
+ let palette = theme.extended_palette();
- impl container::StyleSheet for Pane {
- fn style(&self) -> container::Style {
- container::Style {
- background: Some(Background::Color(SURFACE)),
- border_width: 2.0,
- border_color: match self {
- Self::Active => Color::from_rgb(0.7, 0.7, 0.7),
- Self::Focused => Color::BLACK,
- },
- ..Default::default()
- }
+ container::Appearance {
+ text_color: Some(palette.primary.strong.text),
+ background: Some(palette.primary.strong.color.into()),
+ ..Default::default()
}
}
- pub enum Button {
- Primary,
- Destructive,
- Control,
- Pin,
- }
+ pub fn pane_active(theme: &Theme) -> container::Appearance {
+ let palette = theme.extended_palette();
- impl button::StyleSheet for Button {
- fn active(&self) -> button::Style {
- let (background, text_color) = match self {
- Button::Primary => (Some(ACTIVE), Color::WHITE),
- Button::Destructive => {
- (None, Color::from_rgb8(0xFF, 0x47, 0x47))
- }
- Button::Control => (Some(PANE_ID_COLOR_FOCUSED), Color::WHITE),
- Button::Pin => (Some(ACTIVE), Color::WHITE),
- };
-
- button::Style {
- text_color,
- background: background.map(Background::Color),
- border_radius: 5.0,
- shadow_offset: Vector::new(0.0, 0.0),
- ..button::Style::default()
- }
+ container::Appearance {
+ background: Some(palette.background.weak.color.into()),
+ border_width: 2.0,
+ border_color: palette.background.strong.color,
+ ..Default::default()
}
+ }
- fn hovered(&self) -> button::Style {
- let active = self.active();
-
- let background = match self {
- Button::Primary => Some(HOVERED),
- Button::Destructive => Some(Color {
- a: 0.2,
- ..active.text_color
- }),
- Button::Control => Some(PANE_ID_COLOR_FOCUSED),
- Button::Pin => Some(HOVERED),
- };
-
- button::Style {
- background: background.map(Background::Color),
- ..active
- }
+ pub fn pane_focused(theme: &Theme) -> container::Appearance {
+ let palette = theme.extended_palette();
+
+ container::Appearance {
+ background: Some(palette.background.weak.color.into()),
+ border_width: 2.0,
+ border_color: palette.primary.strong.color,
+ ..Default::default()
}
}
}
diff --git a/examples/pokedex/src/main.rs b/examples/pokedex/src/main.rs
index 85c26987..89d865e4 100644
--- a/examples/pokedex/src/main.rs
+++ b/examples/pokedex/src/main.rs
@@ -1,6 +1,9 @@
+use iced::button;
+use iced::futures;
+use iced::image;
use iced::{
- button, futures, image, Alignment, Application, Button, Column, Command,
- Container, Element, Length, Row, Settings, Text,
+ Alignment, Application, Button, Color, Column, Command, Container, Element,
+ Length, Row, Settings, Text, Theme,
};
pub fn main() -> iced::Result {
@@ -26,8 +29,9 @@ enum Message {
}
impl Application for Pokedex {
- type Executor = iced::executor::Default;
type Message = Message;
+ type Theme = Theme;
+ type Executor = iced::executor::Default;
type Flags = ();
fn new(_flags: ()) -> (Pokedex, Command<Message>) {
@@ -139,7 +143,7 @@ impl Pokemon {
.push(
Text::new(format!("#{}", self.number))
.size(20)
- .color([0.5, 0.5, 0.5]),
+ .style(Color::from([0.5, 0.5, 0.5])),
),
)
.push(Text::new(&self.description)),
@@ -238,29 +242,5 @@ impl From<reqwest::Error> for Error {
}
fn button<'a>(state: &'a mut button::State, text: &str) -> Button<'a, Message> {
- Button::new(state, Text::new(text))
- .padding(10)
- .style(style::Button::Primary)
-}
-
-mod style {
- use iced::{button, Background, Color, Vector};
-
- pub enum Button {
- Primary,
- }
-
- impl button::StyleSheet for Button {
- fn active(&self) -> button::Style {
- button::Style {
- background: Some(Background::Color(match self {
- Button::Primary => Color::from_rgb(0.11, 0.42, 0.87),
- })),
- border_radius: 12.0,
- shadow_offset: Vector::new(1.0, 1.0),
- text_color: Color::WHITE,
- ..button::Style::default()
- }
- }
- }
+ Button::new(state, Text::new(text)).padding(10)
}
diff --git a/examples/pure/component/src/main.rs b/examples/pure/component/src/main.rs
index b38d6fca..64935afd 100644
--- a/examples/pure/component/src/main.rs
+++ b/examples/pure/component/src/main.rs
@@ -47,12 +47,13 @@ impl Sandbox for Component {
}
mod numeric_input {
- use iced::pure::{button, row, text, text_input};
use iced_lazy::pure::{self, Component};
use iced_native::alignment::{self, Alignment};
use iced_native::text;
+ use iced_native::widget;
use iced_native::Length;
use iced_pure::Element;
+ use iced_pure::{button, row, text, text_input};
pub struct NumericInput<Message> {
value: Option<u32>,
@@ -88,6 +89,9 @@ mod numeric_input {
impl<Message, Renderer> Component<Message, Renderer> for NumericInput<Message>
where
Renderer: text::Renderer + 'static,
+ Renderer::Theme: widget::button::StyleSheet
+ + widget::text_input::StyleSheet
+ + widget::text::StyleSheet,
{
type State = ();
type Event = Event;
@@ -158,6 +162,9 @@ mod numeric_input {
where
Message: 'a,
Renderer: 'static + text::Renderer,
+ Renderer::Theme: widget::button::StyleSheet
+ + widget::text_input::StyleSheet
+ + widget::text::StyleSheet,
{
fn from(numeric_input: NumericInput<Message>) -> Self {
pure::component(numeric_input)
diff --git a/examples/pure/game_of_life/src/main.rs b/examples/pure/game_of_life/src/main.rs
index a3164701..851fbd47 100644
--- a/examples/pure/game_of_life/src/main.rs
+++ b/examples/pure/game_of_life/src/main.rs
@@ -1,18 +1,19 @@
//! This example showcases an interactive version of the Game of Life, invented
//! by John Conway. It leverages a `Canvas` together with other widgets.
mod preset;
-mod style;
use grid::Grid;
+use preset::Preset;
+
use iced::executor;
use iced::pure::{
button, checkbox, column, container, pick_list, row, slider, text,
};
use iced::pure::{Application, Element};
+use iced::theme::{self, Theme};
use iced::time;
use iced::window;
-use iced::{Alignment, Color, Command, Length, Settings, Subscription};
-use preset::Preset;
+use iced::{Alignment, Command, Length, Settings, Subscription};
use std::time::{Duration, Instant};
pub fn main() -> iced::Result {
@@ -52,6 +53,7 @@ enum Message {
impl Application for GameOfLife {
type Message = Message;
+ type Theme = Theme;
type Executor = executor::Default;
type Flags = ();
@@ -69,10 +71,6 @@ impl Application for GameOfLife {
String::from("Game of Life - Iced")
}
- fn background_color(&self) -> Color {
- style::BACKGROUND
- }
-
fn update(&mut self, message: Message) -> Command<Message> {
match message {
Message::Grid(message, version) => {
@@ -153,9 +151,12 @@ impl Application for GameOfLife {
container(content)
.width(Length::Fill)
.height(Length::Fill)
- .style(style::Container)
.into()
}
+
+ fn theme(&self) -> Theme {
+ Theme::Dark
+ }
}
fn view_controls<'a>(
@@ -168,19 +169,19 @@ fn view_controls<'a>(
.spacing(10)
.push(
button(if is_playing { "Pause" } else { "Play" })
- .on_press(Message::TogglePlayback)
- .style(style::Button),
+ .on_press(Message::TogglePlayback),
)
- .push(button("Next").on_press(Message::Next).style(style::Button));
+ .push(
+ button("Next")
+ .on_press(Message::Next)
+ .style(theme::Button::Secondary),
+ );
let speed_controls = row()
.width(Length::Fill)
.align_items(Alignment::Center)
.spacing(10)
- .push(
- slider(1.0..=1000.0, speed as f32, Message::SpeedChanged)
- .style(style::Slider),
- )
+ .push(slider(1.0..=1000.0, speed as f32, Message::SpeedChanged))
.push(text(format!("x{}", speed)).size(16));
row()
@@ -198,10 +199,13 @@ fn view_controls<'a>(
.push(
pick_list(preset::ALL, Some(preset), Message::PresetPicked)
.padding(8)
- .text_size(16)
- .style(style::PickList),
+ .text_size(16),
+ )
+ .push(
+ button("Clear")
+ .on_press(Message::Clear)
+ .style(theme::Button::Destructive),
)
- .push(button("Clear").on_press(Message::Clear).style(style::Clear))
.into()
}
@@ -213,7 +217,7 @@ mod grid {
};
use iced::pure::Element;
use iced::{
- alignment, mouse, Color, Length, Point, Rectangle, Size, Vector,
+ alignment, mouse, Color, Length, Point, Rectangle, Size, Theme, Vector,
};
use rustc_hash::{FxHashMap, FxHashSet};
use std::future::Future;
@@ -522,6 +526,7 @@ mod grid {
fn draw(
&self,
_interaction: &Interaction,
+ _theme: &Theme,
bounds: Rectangle,
cursor: Cursor,
) -> Vec<Geometry> {
diff --git a/examples/pure/game_of_life/src/style.rs b/examples/pure/game_of_life/src/style.rs
deleted file mode 100644
index 1a64cf4a..00000000
--- a/examples/pure/game_of_life/src/style.rs
+++ /dev/null
@@ -1,186 +0,0 @@
-use iced::{button, container, pick_list, slider, Background, Color};
-
-const ACTIVE: Color = Color::from_rgb(
- 0x72 as f32 / 255.0,
- 0x89 as f32 / 255.0,
- 0xDA as f32 / 255.0,
-);
-
-const DESTRUCTIVE: Color = Color::from_rgb(
- 0xC0 as f32 / 255.0,
- 0x47 as f32 / 255.0,
- 0x47 as f32 / 255.0,
-);
-
-const HOVERED: Color = Color::from_rgb(
- 0x67 as f32 / 255.0,
- 0x7B as f32 / 255.0,
- 0xC4 as f32 / 255.0,
-);
-
-pub const BACKGROUND: Color = Color::from_rgb(
- 0x2F as f32 / 255.0,
- 0x31 as f32 / 255.0,
- 0x36 as f32 / 255.0,
-);
-
-pub struct Container;
-
-impl container::StyleSheet for Container {
- fn style(&self) -> container::Style {
- container::Style {
- text_color: Some(Color::WHITE),
- ..container::Style::default()
- }
- }
-}
-
-pub struct Button;
-
-impl button::StyleSheet for Button {
- fn active(&self) -> button::Style {
- button::Style {
- background: Some(Background::Color(ACTIVE)),
- border_radius: 3.0,
- text_color: Color::WHITE,
- ..button::Style::default()
- }
- }
-
- fn hovered(&self) -> button::Style {
- button::Style {
- background: Some(Background::Color(HOVERED)),
- text_color: Color::WHITE,
- ..self.active()
- }
- }
-
- fn pressed(&self) -> button::Style {
- button::Style {
- border_width: 1.0,
- border_color: Color::WHITE,
- ..self.hovered()
- }
- }
-}
-
-pub struct Clear;
-
-impl button::StyleSheet for Clear {
- fn active(&self) -> button::Style {
- button::Style {
- background: Some(Background::Color(DESTRUCTIVE)),
- border_radius: 3.0,
- text_color: Color::WHITE,
- ..button::Style::default()
- }
- }
-
- fn hovered(&self) -> button::Style {
- button::Style {
- background: Some(Background::Color(Color {
- a: 0.5,
- ..DESTRUCTIVE
- })),
- text_color: Color::WHITE,
- ..self.active()
- }
- }
-
- fn pressed(&self) -> button::Style {
- button::Style {
- border_width: 1.0,
- border_color: Color::WHITE,
- ..self.hovered()
- }
- }
-}
-
-pub struct Slider;
-
-impl slider::StyleSheet for Slider {
- fn active(&self) -> slider::Style {
- slider::Style {
- rail_colors: (ACTIVE, Color { a: 0.1, ..ACTIVE }),
- handle: slider::Handle {
- shape: slider::HandleShape::Circle { radius: 9.0 },
- color: ACTIVE,
- border_width: 0.0,
- border_color: Color::TRANSPARENT,
- },
- }
- }
-
- fn hovered(&self) -> slider::Style {
- let active = self.active();
-
- slider::Style {
- handle: slider::Handle {
- color: HOVERED,
- ..active.handle
- },
- ..active
- }
- }
-
- fn dragging(&self) -> slider::Style {
- let active = self.active();
-
- slider::Style {
- handle: slider::Handle {
- color: Color::from_rgb(0.85, 0.85, 0.85),
- ..active.handle
- },
- ..active
- }
- }
-}
-
-pub struct PickList;
-
-impl pick_list::StyleSheet for PickList {
- fn menu(&self) -> pick_list::Menu {
- pick_list::Menu {
- text_color: Color::WHITE,
- background: BACKGROUND.into(),
- border_width: 1.0,
- border_color: Color {
- a: 0.7,
- ..Color::BLACK
- },
- selected_background: Color {
- a: 0.5,
- ..Color::BLACK
- }
- .into(),
- selected_text_color: Color::WHITE,
- }
- }
-
- fn active(&self) -> pick_list::Style {
- pick_list::Style {
- text_color: Color::WHITE,
- background: BACKGROUND.into(),
- border_width: 1.0,
- border_color: Color {
- a: 0.6,
- ..Color::BLACK
- },
- border_radius: 2.0,
- icon_size: 0.5,
- ..pick_list::Style::default()
- }
- }
-
- fn hovered(&self) -> pick_list::Style {
- let active = self.active();
-
- pick_list::Style {
- border_color: Color {
- a: 0.9,
- ..Color::BLACK
- },
- ..active
- }
- }
-}
diff --git a/examples/pure/pane_grid/src/main.rs b/examples/pure/pane_grid/src/main.rs
index 65516956..e85ed78d 100644
--- a/examples/pure/pane_grid/src/main.rs
+++ b/examples/pure/pane_grid/src/main.rs
@@ -4,6 +4,7 @@ use iced::keyboard;
use iced::pure::widget::pane_grid::{self, PaneGrid};
use iced::pure::{button, column, container, row, scrollable, text};
use iced::pure::{Application, Element};
+use iced::theme::{self, Theme};
use iced::{Color, Command, Length, Settings, Size, Subscription};
use iced_lazy::pure::responsive;
use iced_native::{event, subscription, Event};
@@ -33,6 +34,7 @@ enum Message {
impl Application for Example {
type Message = Message;
+ type Theme = Theme;
type Executor = executor::Default;
type Flags = ();
@@ -161,13 +163,12 @@ impl Application for Example {
text(if pane.is_pinned { "Unpin" } else { "Pin" }).size(14),
)
.on_press(Message::TogglePin(id))
- .style(style::Button::Pin)
.padding(3);
let title = row()
.push(pin_button)
.push("Pane")
- .push(text(pane.id.to_string()).color(if is_focused {
+ .push(text(pane.id.to_string()).style(if is_focused {
PANE_ID_COLOR_FOCUSED
} else {
PANE_ID_COLOR_UNFOCUSED
@@ -178,9 +179,9 @@ impl Application for Example {
.controls(view_controls(id, total_panes, pane.is_pinned))
.padding(10)
.style(if is_focused {
- style::TitleBar::Focused
+ style::title_bar_focused
} else {
- style::TitleBar::Active
+ style::title_bar_active
});
pane_grid::Content::new(responsive(move |size| {
@@ -188,9 +189,9 @@ impl Application for Example {
}))
.title_bar(title_bar)
.style(if is_focused {
- style::Pane::Focused
+ style::pane_focused
} else {
- style::Pane::Active
+ style::pane_active
})
})
.width(Length::Fill)
@@ -259,7 +260,7 @@ fn view_content<'a>(
is_pinned: bool,
size: Size,
) -> Element<'a, Message> {
- let button = |label, message, style| {
+ let button = |label, message| {
button(
text(label)
.width(Length::Fill)
@@ -269,7 +270,6 @@ fn view_content<'a>(
.width(Length::Fill)
.padding(8)
.on_press(message)
- .style(style)
};
let mut controls = column()
@@ -278,20 +278,17 @@ fn view_content<'a>(
.push(button(
"Split horizontally",
Message::Split(pane_grid::Axis::Horizontal, pane),
- style::Button::Primary,
))
.push(button(
"Split vertically",
Message::Split(pane_grid::Axis::Vertical, pane),
- style::Button::Primary,
));
if total_panes > 1 && !is_pinned {
- controls = controls.push(button(
- "Close",
- Message::Close(pane),
- style::Button::Destructive,
- ));
+ controls = controls.push(
+ button("Close", Message::Close(pane))
+ .style(theme::Button::Destructive),
+ );
}
let content = column()
@@ -315,7 +312,7 @@ fn view_controls<'a>(
is_pinned: bool,
) -> Element<'a, Message> {
let mut button = button(text("Close").size(14))
- .style(style::Button::Control)
+ .style(theme::Button::Destructive)
.padding(3);
if total_panes > 1 && !is_pinned {
@@ -326,111 +323,47 @@ fn view_controls<'a>(
}
mod style {
- use crate::PANE_ID_COLOR_FOCUSED;
- use iced::{button, container, Background, Color, Vector};
-
- const SURFACE: Color = Color::from_rgb(
- 0xF2 as f32 / 255.0,
- 0xF3 as f32 / 255.0,
- 0xF5 as f32 / 255.0,
- );
-
- const ACTIVE: Color = Color::from_rgb(
- 0x72 as f32 / 255.0,
- 0x89 as f32 / 255.0,
- 0xDA as f32 / 255.0,
- );
-
- const HOVERED: Color = Color::from_rgb(
- 0x67 as f32 / 255.0,
- 0x7B as f32 / 255.0,
- 0xC4 as f32 / 255.0,
- );
-
- pub enum TitleBar {
- Active,
- Focused,
- }
+ use iced::{container, Theme};
- impl container::StyleSheet for TitleBar {
- fn style(&self) -> container::Style {
- let pane = match self {
- Self::Active => Pane::Active,
- Self::Focused => Pane::Focused,
- }
- .style();
+ pub fn title_bar_active(theme: &Theme) -> container::Appearance {
+ let palette = theme.extended_palette();
- container::Style {
- text_color: Some(Color::WHITE),
- background: Some(pane.border_color.into()),
- ..Default::default()
- }
+ container::Appearance {
+ text_color: Some(palette.background.strong.text),
+ background: Some(palette.background.strong.color.into()),
+ ..Default::default()
}
}
- pub enum Pane {
- Active,
- Focused,
- }
+ pub fn title_bar_focused(theme: &Theme) -> container::Appearance {
+ let palette = theme.extended_palette();
- impl container::StyleSheet for Pane {
- fn style(&self) -> container::Style {
- container::Style {
- background: Some(Background::Color(SURFACE)),
- border_width: 2.0,
- border_color: match self {
- Self::Active => Color::from_rgb(0.7, 0.7, 0.7),
- Self::Focused => Color::BLACK,
- },
- ..Default::default()
- }
+ container::Appearance {
+ text_color: Some(palette.primary.strong.text),
+ background: Some(palette.primary.strong.color.into()),
+ ..Default::default()
}
}
- pub enum Button {
- Primary,
- Destructive,
- Control,
- Pin,
- }
+ pub fn pane_active(theme: &Theme) -> container::Appearance {
+ let palette = theme.extended_palette();
- impl button::StyleSheet for Button {
- fn active(&self) -> button::Style {
- let (background, text_color) = match self {
- Button::Primary => (Some(ACTIVE), Color::WHITE),
- Button::Destructive => {
- (None, Color::from_rgb8(0xFF, 0x47, 0x47))
- }
- Button::Control => (Some(PANE_ID_COLOR_FOCUSED), Color::WHITE),
- Button::Pin => (Some(ACTIVE), Color::WHITE),
- };
-
- button::Style {
- text_color,
- background: background.map(Background::Color),
- border_radius: 5.0,
- shadow_offset: Vector::new(0.0, 0.0),
- ..button::Style::default()
- }
+ container::Appearance {
+ background: Some(palette.background.weak.color.into()),
+ border_width: 2.0,
+ border_color: palette.background.strong.color,
+ ..Default::default()
}
+ }
- fn hovered(&self) -> button::Style {
- let active = self.active();
-
- let background = match self {
- Button::Primary => Some(HOVERED),
- Button::Destructive => Some(Color {
- a: 0.2,
- ..active.text_color
- }),
- Button::Control => Some(PANE_ID_COLOR_FOCUSED),
- Button::Pin => Some(HOVERED),
- };
-
- button::Style {
- background: background.map(Background::Color),
- ..active
- }
+ pub fn pane_focused(theme: &Theme) -> container::Appearance {
+ let palette = theme.extended_palette();
+
+ container::Appearance {
+ background: Some(palette.background.weak.color.into()),
+ border_width: 2.0,
+ border_color: palette.primary.strong.color,
+ ..Default::default()
}
}
}
diff --git a/examples/pure/todos/src/main.rs b/examples/pure/todos/src/main.rs
index 6a6c6300..723386ad 100644
--- a/examples/pure/todos/src/main.rs
+++ b/examples/pure/todos/src/main.rs
@@ -4,8 +4,9 @@ use iced::pure::{
button, checkbox, column, container, row, scrollable, text, text_input,
Application, Element,
};
+use iced::theme::{self, Theme};
use iced::window;
-use iced::{Command, Font, Length, Settings};
+use iced::{Color, Command, Font, Length, Settings};
use serde::{Deserialize, Serialize};
pub fn main() -> iced::Result {
@@ -44,8 +45,9 @@ enum Message {
}
impl Application for Todos {
- type Executor = iced::executor::Default;
type Message = Message;
+ type Theme = Theme;
+ type Executor = iced::executor::Default;
type Flags = ();
fn new(_flags: ()) -> (Todos, Command<Message>) {
@@ -153,7 +155,7 @@ impl Application for Todos {
let title = text("todos")
.width(Length::Fill)
.size(100)
- .color([0.5, 0.5, 0.5])
+ .style(Color::from([0.5, 0.5, 0.5]))
.horizontal_alignment(alignment::Horizontal::Center);
let input = text_input(
@@ -287,7 +289,7 @@ impl Task {
button(edit_icon())
.on_press(TaskMessage::Edit)
.padding(10)
- .style(style::Button::Icon),
+ .style(theme::Button::Text),
)
.into()
}
@@ -313,7 +315,7 @@ impl Task {
)
.on_press(TaskMessage::Delete)
.padding(10)
- .style(style::Button::Destructive),
+ .style(theme::Button::Destructive),
)
.into()
}
@@ -328,9 +330,9 @@ fn view_controls(tasks: &[Task], current_filter: Filter) -> Element<Message> {
let label = text(label).size(16);
let button = button(label).style(if filter == current_filter {
- style::Button::FilterSelected
+ theme::Button::Primary
} else {
- style::Button::FilterActive
+ theme::Button::Text
});
button.on_press(Message::FilterChanged(filter)).padding(8)
@@ -404,7 +406,7 @@ fn empty_message(message: &str) -> Element<'_, Message> {
.width(Length::Fill)
.size(25)
.horizontal_alignment(alignment::Horizontal::Center)
- .color([0.7, 0.7, 0.7]),
+ .style(Color::from([0.7, 0.7, 0.7])),
)
.width(Length::Fill)
.height(Length::Units(200))
@@ -552,57 +554,3 @@ impl SavedState {
Ok(())
}
}
-
-mod style {
- use iced::{button, Background, Color, Vector};
-
- pub enum Button {
- FilterActive,
- FilterSelected,
- Icon,
- Destructive,
- }
-
- impl button::StyleSheet for Button {
- fn active(&self) -> button::Style {
- match self {
- Button::FilterActive => button::Style::default(),
- Button::FilterSelected => button::Style {
- background: Some(Background::Color(Color::from_rgb(
- 0.2, 0.2, 0.7,
- ))),
- border_radius: 10.0,
- text_color: Color::WHITE,
- ..button::Style::default()
- },
- Button::Icon => button::Style {
- text_color: Color::from_rgb(0.5, 0.5, 0.5),
- ..button::Style::default()
- },
- Button::Destructive => button::Style {
- background: Some(Background::Color(Color::from_rgb(
- 0.8, 0.2, 0.2,
- ))),
- border_radius: 5.0,
- text_color: Color::WHITE,
- shadow_offset: Vector::new(1.0, 1.0),
- ..button::Style::default()
- },
- }
- }
-
- fn hovered(&self) -> button::Style {
- let active = self.active();
-
- button::Style {
- text_color: match self {
- Button::Icon => Color::from_rgb(0.2, 0.2, 0.7),
- Button::FilterActive => Color::from_rgb(0.2, 0.2, 0.7),
- _ => active.text_color,
- },
- shadow_offset: active.shadow_offset + Vector::new(0.0, 1.0),
- ..active
- }
- }
- }
-}
diff --git a/examples/pure/tooltip/src/main.rs b/examples/pure/tooltip/src/main.rs
index dbd83f5f..e9a6c111 100644
--- a/examples/pure/tooltip/src/main.rs
+++ b/examples/pure/tooltip/src/main.rs
@@ -1,6 +1,7 @@
-use iced::pure::{
- button, container, tooltip, widget::tooltip::Position, Element, Sandbox,
-};
+use iced::pure::widget::tooltip::Position;
+use iced::pure::{button, container, tooltip};
+use iced::pure::{Element, Sandbox};
+use iced::theme;
use iced::{Length, Settings};
pub fn main() -> iced::Result {
@@ -53,7 +54,7 @@ impl Sandbox for Example {
self.position,
)
.gap(10)
- .style(style::Tooltip);
+ .style(theme::Container::Box);
container(tooltip)
.width(Length::Fill)
@@ -73,21 +74,3 @@ fn position_to_text<'a>(position: Position) -> &'a str {
Position::Right => "Right",
}
}
-
-mod style {
- use iced::container;
- use iced::Color;
-
- pub struct Tooltip;
-
- impl container::StyleSheet for Tooltip {
- fn style(&self) -> container::Style {
- container::Style {
- text_color: Some(Color::from_rgb8(0xEE, 0xEE, 0xEE)),
- background: Some(Color::from_rgb(0.11, 0.42, 0.87).into()),
- border_radius: 12.0,
- ..container::Style::default()
- }
- }
- }
-}
diff --git a/examples/pure/tour/src/main.rs b/examples/pure/tour/src/main.rs
index a44d99f3..477a1ec7 100644
--- a/examples/pure/tour/src/main.rs
+++ b/examples/pure/tour/src/main.rs
@@ -5,7 +5,8 @@ use iced::pure::{
scrollable, slider, text, text_input, toggler, vertical_space,
};
use iced::pure::{Element, Sandbox};
-use iced::{Color, Length, Settings};
+use iced::theme;
+use iced::{Color, Length, Renderer, Settings};
pub fn main() -> iced::Result {
env_logger::init();
@@ -55,7 +56,7 @@ impl Sandbox for Tour {
controls = controls.push(
button("Back")
.on_press(Message::BackPressed)
- .style(style::Button::Secondary),
+ .style(theme::Button::Secondary),
);
}
@@ -65,7 +66,7 @@ impl Sandbox for Tour {
controls = controls.push(
button("Next")
.on_press(Message::NextPressed)
- .style(style::Button::Primary),
+ .style(theme::Button::Primary),
);
}
@@ -432,7 +433,7 @@ impl<'a> Step {
.padding(20)
.spacing(20)
.push("And its color:")
- .push(text(format!("{:?}", color)).color(color))
+ .push(text(format!("{:?}", color)).style(color))
.push(color_sliders);
Self::container("Text")
@@ -575,7 +576,7 @@ impl<'a> Step {
.push(if cfg!(target_arch = "wasm32") {
Element::new(
text("Not available on web yet!")
- .color([0.7, 0.7, 0.7])
+ .style(Color::from([0.7, 0.7, 0.7]))
.horizontal_alignment(alignment::Horizontal::Center),
)
} else {
@@ -621,7 +622,7 @@ fn button<'a, Message: Clone>(label: &str) -> Button<'a, Message> {
fn color_slider<'a>(
component: f32,
update: impl Fn(f32) -> Color + 'a,
-) -> Slider<'a, f64, StepMessage> {
+) -> Slider<'a, f64, StepMessage, Renderer> {
slider(0.0..=1.0, f64::from(component), move |c| {
StepMessage::TextColorChanged(update(c as f32))
})
@@ -669,35 +670,3 @@ pub enum Layout {
Row,
Column,
}
-
-mod style {
- use iced::{button, Background, Color, Vector};
-
- pub enum Button {
- Primary,
- Secondary,
- }
-
- impl button::StyleSheet for Button {
- fn active(&self) -> button::Style {
- button::Style {
- background: Some(Background::Color(match self {
- Button::Primary => Color::from_rgb(0.11, 0.42, 0.87),
- Button::Secondary => Color::from_rgb(0.5, 0.5, 0.5),
- })),
- border_radius: 12.0,
- shadow_offset: Vector::new(1.0, 1.0),
- text_color: Color::from_rgb8(0xEE, 0xEE, 0xEE),
- ..button::Style::default()
- }
- }
-
- fn hovered(&self) -> button::Style {
- button::Style {
- text_color: Color::WHITE,
- shadow_offset: Vector::new(1.0, 2.0),
- ..self.active()
- }
- }
- }
-}
diff --git a/examples/qr_code/src/main.rs b/examples/qr_code/src/main.rs
index 92c82d45..3e9ba921 100644
--- a/examples/qr_code/src/main.rs
+++ b/examples/qr_code/src/main.rs
@@ -1,7 +1,8 @@
use iced::qr_code::{self, QRCode};
use iced::text_input::{self, TextInput};
use iced::{
- Alignment, Column, Container, Element, Length, Sandbox, Settings, Text,
+ Alignment, Color, Column, Container, Element, Length, Sandbox, Settings,
+ Text,
};
pub fn main() -> iced::Result {
@@ -48,7 +49,7 @@ impl Sandbox for QRGenerator {
fn view(&mut self) -> Element<Message> {
let title = Text::new("QR Code Generator")
.size(70)
- .color([0.5, 0.5, 0.5]);
+ .style(Color::from([0.5, 0.5, 0.5]));
let input = TextInput::new(
&mut self.input,
diff --git a/examples/scrollable/src/main.rs b/examples/scrollable/src/main.rs
index 8e027504..f66d2180 100644
--- a/examples/scrollable/src/main.rs
+++ b/examples/scrollable/src/main.rs
@@ -1,8 +1,8 @@
-mod style;
-
+use iced::button;
+use iced::scrollable;
use iced::{
- button, scrollable, Button, Column, Container, Element, Length,
- ProgressBar, Radio, Row, Rule, Sandbox, Scrollable, Settings, Space, Text,
+ Button, Column, Container, Element, Length, ProgressBar, Radio, Row, Rule,
+ Sandbox, Scrollable, Settings, Space, Text, Theme,
};
pub fn main() -> iced::Result {
@@ -10,13 +10,13 @@ pub fn main() -> iced::Result {
}
struct ScrollableDemo {
- theme: style::Theme,
+ theme: Theme,
variants: Vec<Variant>,
}
#[derive(Debug, Clone)]
enum Message {
- ThemeChanged(style::Theme),
+ ThemeChanged(Theme),
ScrollToTop(usize),
ScrollToBottom(usize),
Scrolled(usize, f32),
@@ -66,18 +66,15 @@ impl Sandbox for ScrollableDemo {
theme, variants, ..
} = self;
- let choose_theme = style::Theme::ALL.iter().fold(
+ let choose_theme = [Theme::Light, Theme::Dark].iter().fold(
Column::new().spacing(10).push(Text::new("Choose a theme:")),
|column, option| {
- column.push(
- Radio::new(
- *option,
- format!("{:?}", option),
- Some(*theme),
- Message::ThemeChanged,
- )
- .style(*theme),
- )
+ column.push(Radio::new(
+ *option,
+ format!("{:?}", option),
+ Some(*theme),
+ Message::ThemeChanged,
+ ))
},
);
@@ -95,7 +92,6 @@ impl Sandbox for ScrollableDemo {
.on_scroll(move |offset| {
Message::Scrolled(i, offset)
})
- .style(*theme)
.push(Text::new(variant.title))
.push(
Button::new(
@@ -160,12 +156,7 @@ impl Sandbox for ScrollableDemo {
.width(Length::Fill)
.height(Length::Fill)
.spacing(10)
- .push(
- Container::new(scrollable)
- .width(Length::Fill)
- .height(Length::Fill)
- .style(*theme),
- )
+ .push(scrollable)
.push(ProgressBar::new(
0.0..=1.0,
variant.latest_offset,
@@ -182,7 +173,7 @@ impl Sandbox for ScrollableDemo {
.spacing(20)
.padding(20)
.push(choose_theme)
- .push(Rule::horizontal(20).style(self.theme))
+ .push(Rule::horizontal(20))
.push(scrollable_row);
Container::new(content)
@@ -190,9 +181,12 @@ impl Sandbox for ScrollableDemo {
.height(Length::Fill)
.center_x()
.center_y()
- .style(self.theme)
.into()
}
+
+ fn theme(&self) -> Theme {
+ self.theme
+ }
}
/// A version of a scrollable
diff --git a/examples/scrollable/src/style.rs b/examples/scrollable/src/style.rs
deleted file mode 100644
index 0ed38b00..00000000
--- a/examples/scrollable/src/style.rs
+++ /dev/null
@@ -1,191 +0,0 @@
-use iced::{container, radio, rule, scrollable};
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub enum Theme {
- Light,
- Dark,
-}
-
-impl Theme {
- pub const ALL: [Theme; 2] = [Theme::Light, Theme::Dark];
-}
-
-impl Default for Theme {
- fn default() -> Theme {
- Theme::Light
- }
-}
-
-impl<'a> From<Theme> for Box<dyn container::StyleSheet + 'a> {
- fn from(theme: Theme) -> Self {
- match theme {
- Theme::Light => Default::default(),
- Theme::Dark => dark::Container.into(),
- }
- }
-}
-
-impl<'a> From<Theme> for Box<dyn radio::StyleSheet + 'a> {
- fn from(theme: Theme) -> Self {
- match theme {
- Theme::Light => Default::default(),
- Theme::Dark => dark::Radio.into(),
- }
- }
-}
-
-impl<'a> From<Theme> for Box<dyn scrollable::StyleSheet + 'a> {
- fn from(theme: Theme) -> Self {
- match theme {
- Theme::Light => Default::default(),
- Theme::Dark => dark::Scrollable.into(),
- }
- }
-}
-
-impl From<Theme> for Box<dyn rule::StyleSheet> {
- fn from(theme: Theme) -> Self {
- match theme {
- Theme::Light => Default::default(),
- Theme::Dark => dark::Rule.into(),
- }
- }
-}
-
-mod dark {
- use iced::{container, radio, rule, scrollable, Color};
-
- const BACKGROUND: Color = Color::from_rgb(
- 0x36 as f32 / 255.0,
- 0x39 as f32 / 255.0,
- 0x3F as f32 / 255.0,
- );
-
- const SURFACE: Color = Color::from_rgb(
- 0x40 as f32 / 255.0,
- 0x44 as f32 / 255.0,
- 0x4B as f32 / 255.0,
- );
-
- const ACCENT: Color = Color::from_rgb(
- 0x6F as f32 / 255.0,
- 0xFF as f32 / 255.0,
- 0xE9 as f32 / 255.0,
- );
-
- const ACTIVE: Color = Color::from_rgb(
- 0x72 as f32 / 255.0,
- 0x89 as f32 / 255.0,
- 0xDA as f32 / 255.0,
- );
-
- const SCROLLBAR: Color = Color::from_rgb(
- 0x2E as f32 / 255.0,
- 0x33 as f32 / 255.0,
- 0x38 as f32 / 255.0,
- );
-
- const SCROLLER: Color = Color::from_rgb(
- 0x20 as f32 / 255.0,
- 0x22 as f32 / 255.0,
- 0x25 as f32 / 255.0,
- );
-
- pub struct Container;
-
- impl container::StyleSheet for Container {
- fn style(&self) -> container::Style {
- container::Style {
- background: Color {
- a: 0.99,
- ..BACKGROUND
- }
- .into(),
- text_color: Color::WHITE.into(),
- ..container::Style::default()
- }
- }
- }
-
- pub struct Radio;
-
- impl radio::StyleSheet for Radio {
- fn active(&self) -> radio::Style {
- radio::Style {
- background: SURFACE.into(),
- dot_color: ACTIVE,
- border_width: 1.0,
- border_color: ACTIVE,
- text_color: None,
- }
- }
-
- fn hovered(&self) -> radio::Style {
- radio::Style {
- background: Color { a: 0.5, ..SURFACE }.into(),
- ..self.active()
- }
- }
- }
-
- pub struct Scrollable;
-
- impl scrollable::StyleSheet for Scrollable {
- fn active(&self) -> scrollable::Scrollbar {
- scrollable::Scrollbar {
- background: Color {
- a: 0.8,
- ..SCROLLBAR
- }
- .into(),
- border_radius: 2.0,
- border_width: 0.0,
- border_color: Color::TRANSPARENT,
- scroller: scrollable::Scroller {
- color: Color { a: 0.7, ..SCROLLER },
- border_radius: 2.0,
- border_width: 0.0,
- border_color: Color::TRANSPARENT,
- },
- }
- }
-
- fn hovered(&self) -> scrollable::Scrollbar {
- let active = self.active();
-
- scrollable::Scrollbar {
- background: SCROLLBAR.into(),
- scroller: scrollable::Scroller {
- color: SCROLLER,
- ..active.scroller
- },
- ..active
- }
- }
-
- fn dragging(&self) -> scrollable::Scrollbar {
- let hovered = self.hovered();
-
- scrollable::Scrollbar {
- scroller: scrollable::Scroller {
- color: ACCENT,
- ..hovered.scroller
- },
- ..hovered
- }
- }
- }
-
- pub struct Rule;
-
- impl rule::StyleSheet for Rule {
- fn style(&self) -> rule::Style {
- rule::Style {
- color: SURFACE,
- width: 2,
- radius: 1.0,
- fill_mode: rule::FillMode::Percent(30.0),
- }
- }
- }
-}
diff --git a/examples/solar_system/src/main.rs b/examples/solar_system/src/main.rs
index e96b53ff..cee9a02f 100644
--- a/examples/solar_system/src/main.rs
+++ b/examples/solar_system/src/main.rs
@@ -6,10 +6,15 @@
//! Inspired by the example found in the MDN docs[1].
//!
//! [1]: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_animations#An_animated_solar_system
+use iced::application;
+use iced::canvas::{self, Cursor, Path, Stroke};
+use iced::executor;
+use iced::theme::{self, Theme};
+use iced::time;
+use iced::window;
use iced::{
- canvas::{self, Cursor, Path, Stroke},
- executor, time, window, Application, Canvas, Color, Command, Element,
- Length, Point, Rectangle, Settings, Size, Subscription, Vector,
+ Application, Canvas, Color, Command, Element, Length, Point, Rectangle,
+ Settings, Size, Subscription, Vector,
};
use std::time::Instant;
@@ -31,8 +36,9 @@ enum Message {
}
impl Application for SolarSystem {
- type Executor = executor::Default;
type Message = Message;
+ type Theme = Theme;
+ type Executor = executor::Default;
type Flags = ();
fn new(_flags: ()) -> (Self, Command<Message>) {
@@ -48,10 +54,6 @@ impl Application for SolarSystem {
String::from("Solar system - Iced")
}
- fn background_color(&self) -> Color {
- Color::BLACK
- }
-
fn update(&mut self, message: Message) -> Command<Message> {
match message {
Message::Tick(instant) => {
@@ -73,6 +75,17 @@ impl Application for SolarSystem {
.height(Length::Fill)
.into()
}
+
+ fn theme(&self) -> Theme {
+ Theme::Dark
+ }
+
+ fn style(&self) -> theme::Application {
+ theme::Application::Custom(|_theme| application::Appearance {
+ background_color: Color::BLACK,
+ text_color: Color::WHITE,
+ })
+ }
}
#[derive(Debug)]
@@ -135,6 +148,7 @@ impl State {
impl<Message> canvas::Program<Message> for State {
fn draw(
&self,
+ _theme: &Theme,
bounds: Rectangle,
_cursor: Cursor,
) -> Vec<canvas::Geometry> {
diff --git a/examples/stopwatch/src/main.rs b/examples/stopwatch/src/main.rs
index 377d7a2d..b83b92ec 100644
--- a/examples/stopwatch/src/main.rs
+++ b/examples/stopwatch/src/main.rs
@@ -1,7 +1,13 @@
+use iced::alignment;
+use iced::button;
+use iced::executor;
+use iced::theme::{self, Theme};
+use iced::time;
use iced::{
- alignment, button, executor, time, Alignment, Application, Button, Column,
- Command, Container, Element, Length, Row, Settings, Subscription, Text,
+ Alignment, Application, Button, Column, Command, Container, Element,
+ Length, Row, Settings, Subscription, Text,
};
+
use std::time::{Duration, Instant};
pub fn main() -> iced::Result {
@@ -28,8 +34,9 @@ enum Message {
}
impl Application for Stopwatch {
- type Executor = executor::Default;
type Message = Message;
+ type Theme = Theme;
+ type Executor = executor::Default;
type Flags = ();
fn new(_flags: ()) -> (Stopwatch, Command<Message>) {
@@ -99,7 +106,7 @@ impl Application for Stopwatch {
))
.size(40);
- let button = |state, label, style| {
+ let button = |state, label| {
Button::new(
state,
Text::new(label)
@@ -107,21 +114,20 @@ impl Application for Stopwatch {
)
.padding(10)
.width(Length::Units(80))
- .style(style)
};
let toggle_button = {
- let (label, color) = match self.state {
- State::Idle => ("Start", style::Button::Primary),
- State::Ticking { .. } => ("Stop", style::Button::Destructive),
+ let label = match self.state {
+ State::Idle => "Start",
+ State::Ticking { .. } => "Stop",
};
- button(&mut self.toggle, label, color).on_press(Message::Toggle)
+ button(&mut self.toggle, label).on_press(Message::Toggle)
};
- let reset_button =
- button(&mut self.reset, "Reset", style::Button::Secondary)
- .on_press(Message::Reset);
+ let reset_button = button(&mut self.reset, "Reset")
+ .style(theme::Button::Destructive)
+ .on_press(Message::Reset);
let controls = Row::new()
.spacing(20)
@@ -142,29 +148,3 @@ impl Application for Stopwatch {
.into()
}
}
-
-mod style {
- use iced::{button, Background, Color, Vector};
-
- pub enum Button {
- Primary,
- Secondary,
- Destructive,
- }
-
- impl button::StyleSheet for Button {
- fn active(&self) -> button::Style {
- button::Style {
- background: Some(Background::Color(match self {
- Button::Primary => Color::from_rgb(0.11, 0.42, 0.87),
- Button::Secondary => Color::from_rgb(0.5, 0.5, 0.5),
- Button::Destructive => Color::from_rgb(0.8, 0.2, 0.2),
- })),
- border_radius: 12.0,
- shadow_offset: Vector::new(1.0, 1.0),
- text_color: Color::WHITE,
- ..button::Style::default()
- }
- }
- }
-}
diff --git a/examples/styling/src/main.rs b/examples/styling/src/main.rs
index b4ef3e87..aa90d17c 100644
--- a/examples/styling/src/main.rs
+++ b/examples/styling/src/main.rs
@@ -1,7 +1,11 @@
+use iced::button;
+use iced::scrollable;
+use iced::slider;
+use iced::text_input;
use iced::{
- button, scrollable, slider, text_input, Alignment, Button, Checkbox,
- Column, Container, Element, Length, ProgressBar, Radio, Row, Rule, Sandbox,
- Scrollable, Settings, Slider, Space, Text, TextInput, Toggler,
+ Alignment, Button, Checkbox, Column, Container, Element, Length,
+ ProgressBar, Radio, Row, Rule, Sandbox, Scrollable, Settings, Slider,
+ Space, Text, TextInput, Theme, Toggler,
};
pub fn main() -> iced::Result {
@@ -10,7 +14,7 @@ pub fn main() -> iced::Result {
#[derive(Default)]
struct Styling {
- theme: style::Theme,
+ theme: Theme,
scroll: scrollable::State,
input: text_input::State,
input_value: String,
@@ -23,7 +27,7 @@ struct Styling {
#[derive(Debug, Clone)]
enum Message {
- ThemeChanged(style::Theme),
+ ThemeChanged(Theme),
InputChanged(String),
ButtonPressed,
SliderChanged(f32),
@@ -54,18 +58,15 @@ impl Sandbox for Styling {
}
fn view(&mut self) -> Element<Message> {
- let choose_theme = style::Theme::ALL.iter().fold(
+ let choose_theme = [Theme::Light, Theme::Dark].iter().fold(
Column::new().spacing(10).push(Text::new("Choose a theme:")),
|column, theme| {
- column.push(
- Radio::new(
- *theme,
- format!("{:?}", theme),
- Some(self.theme),
- Message::ThemeChanged,
- )
- .style(self.theme),
- )
+ column.push(Radio::new(
+ *theme,
+ format!("{:?}", theme),
+ Some(self.theme),
+ Message::ThemeChanged,
+ ))
},
);
@@ -76,29 +77,24 @@ impl Sandbox for Styling {
Message::InputChanged,
)
.padding(10)
- .size(20)
- .style(self.theme);
+ .size(20);
let button = Button::new(&mut self.button, Text::new("Submit"))
.padding(10)
- .on_press(Message::ButtonPressed)
- .style(self.theme);
+ .on_press(Message::ButtonPressed);
let slider = Slider::new(
&mut self.slider,
0.0..=100.0,
self.slider_value,
Message::SliderChanged,
- )
- .style(self.theme);
+ );
- let progress_bar =
- ProgressBar::new(0.0..=100.0, self.slider_value).style(self.theme);
+ let progress_bar = ProgressBar::new(0.0..=100.0, self.slider_value);
let scrollable = Scrollable::new(&mut self.scroll)
.width(Length::Fill)
.height(Length::Units(100))
- .style(self.theme)
.push(Text::new("Scroll me!"))
.push(Space::with_height(Length::Units(800)))
.push(Text::new("You did it!"));
@@ -107,8 +103,7 @@ impl Sandbox for Styling {
self.checkbox_value,
"Check me!",
Message::CheckboxToggled,
- )
- .style(self.theme);
+ );
let toggler = Toggler::new(
self.toggler_value,
@@ -116,15 +111,14 @@ impl Sandbox for Styling {
Message::TogglerToggled,
)
.width(Length::Shrink)
- .spacing(10)
- .style(self.theme);
+ .spacing(10);
let content = Column::new()
.spacing(20)
.padding(20)
.max_width(600)
.push(choose_theme)
- .push(Rule::horizontal(38).style(self.theme))
+ .push(Rule::horizontal(38))
.push(Row::new().spacing(10).push(text_input).push(button))
.push(slider)
.push(progress_bar)
@@ -134,7 +128,7 @@ impl Sandbox for Styling {
.height(Length::Units(100))
.align_items(Alignment::Center)
.push(scrollable)
- .push(Rule::vertical(38).style(self.theme))
+ .push(Rule::vertical(38))
.push(
Column::new()
.width(Length::Shrink)
@@ -149,445 +143,10 @@ impl Sandbox for Styling {
.height(Length::Fill)
.center_x()
.center_y()
- .style(self.theme)
.into()
}
-}
-
-mod style {
- use iced::{
- button, checkbox, container, progress_bar, radio, rule, scrollable,
- slider, text_input, toggler,
- };
-
- #[derive(Debug, Clone, Copy, PartialEq, Eq)]
- pub enum Theme {
- Light,
- Dark,
- }
-
- impl Theme {
- pub const ALL: [Theme; 2] = [Theme::Light, Theme::Dark];
- }
- impl Default for Theme {
- fn default() -> Theme {
- Theme::Light
- }
- }
-
- impl<'a> From<Theme> for Box<dyn container::StyleSheet + 'a> {
- fn from(theme: Theme) -> Self {
- match theme {
- Theme::Light => Default::default(),
- Theme::Dark => dark::Container.into(),
- }
- }
- }
-
- impl<'a> From<Theme> for Box<dyn radio::StyleSheet + 'a> {
- fn from(theme: Theme) -> Self {
- match theme {
- Theme::Light => Default::default(),
- Theme::Dark => dark::Radio.into(),
- }
- }
- }
-
- impl<'a> From<Theme> for Box<dyn text_input::StyleSheet + 'a> {
- fn from(theme: Theme) -> Self {
- match theme {
- Theme::Light => Default::default(),
- Theme::Dark => dark::TextInput.into(),
- }
- }
- }
-
- impl<'a> From<Theme> for Box<dyn button::StyleSheet + 'a> {
- fn from(theme: Theme) -> Self {
- match theme {
- Theme::Light => light::Button.into(),
- Theme::Dark => dark::Button.into(),
- }
- }
- }
-
- impl<'a> From<Theme> for Box<dyn scrollable::StyleSheet + 'a> {
- fn from(theme: Theme) -> Self {
- match theme {
- Theme::Light => Default::default(),
- Theme::Dark => dark::Scrollable.into(),
- }
- }
- }
-
- impl<'a> From<Theme> for Box<dyn slider::StyleSheet + 'a> {
- fn from(theme: Theme) -> Self {
- match theme {
- Theme::Light => Default::default(),
- Theme::Dark => dark::Slider.into(),
- }
- }
- }
-
- impl From<Theme> for Box<dyn progress_bar::StyleSheet> {
- fn from(theme: Theme) -> Self {
- match theme {
- Theme::Light => Default::default(),
- Theme::Dark => dark::ProgressBar.into(),
- }
- }
- }
-
- impl<'a> From<Theme> for Box<dyn checkbox::StyleSheet + 'a> {
- fn from(theme: Theme) -> Self {
- match theme {
- Theme::Light => Default::default(),
- Theme::Dark => dark::Checkbox.into(),
- }
- }
- }
-
- impl From<Theme> for Box<dyn toggler::StyleSheet> {
- fn from(theme: Theme) -> Self {
- match theme {
- Theme::Light => Default::default(),
- Theme::Dark => dark::Toggler.into(),
- }
- }
- }
-
- impl From<Theme> for Box<dyn rule::StyleSheet> {
- fn from(theme: Theme) -> Self {
- match theme {
- Theme::Light => Default::default(),
- Theme::Dark => dark::Rule.into(),
- }
- }
- }
-
- mod light {
- use iced::{button, Color, Vector};
-
- pub struct Button;
-
- impl button::StyleSheet for Button {
- fn active(&self) -> button::Style {
- button::Style {
- background: Color::from_rgb(0.11, 0.42, 0.87).into(),
- border_radius: 12.0,
- shadow_offset: Vector::new(1.0, 1.0),
- text_color: Color::from_rgb8(0xEE, 0xEE, 0xEE),
- ..button::Style::default()
- }
- }
-
- fn hovered(&self) -> button::Style {
- button::Style {
- text_color: Color::WHITE,
- shadow_offset: Vector::new(1.0, 2.0),
- ..self.active()
- }
- }
- }
- }
-
- mod dark {
- use iced::{
- button, checkbox, container, progress_bar, radio, rule, scrollable,
- slider, text_input, toggler, Color,
- };
-
- const SURFACE: Color = Color::from_rgb(
- 0x40 as f32 / 255.0,
- 0x44 as f32 / 255.0,
- 0x4B as f32 / 255.0,
- );
-
- const ACCENT: Color = Color::from_rgb(
- 0x6F as f32 / 255.0,
- 0xFF as f32 / 255.0,
- 0xE9 as f32 / 255.0,
- );
-
- const ACTIVE: Color = Color::from_rgb(
- 0x72 as f32 / 255.0,
- 0x89 as f32 / 255.0,
- 0xDA as f32 / 255.0,
- );
-
- const HOVERED: Color = Color::from_rgb(
- 0x67 as f32 / 255.0,
- 0x7B as f32 / 255.0,
- 0xC4 as f32 / 255.0,
- );
-
- pub struct Container;
-
- impl container::StyleSheet for Container {
- fn style(&self) -> container::Style {
- container::Style {
- background: Color::from_rgb8(0x36, 0x39, 0x3F).into(),
- text_color: Color::WHITE.into(),
- ..container::Style::default()
- }
- }
- }
-
- pub struct Radio;
-
- impl radio::StyleSheet for Radio {
- fn active(&self) -> radio::Style {
- radio::Style {
- background: SURFACE.into(),
- dot_color: ACTIVE,
- border_width: 1.0,
- border_color: ACTIVE,
- text_color: None,
- }
- }
-
- fn hovered(&self) -> radio::Style {
- radio::Style {
- background: Color { a: 0.5, ..SURFACE }.into(),
- ..self.active()
- }
- }
- }
-
- pub struct TextInput;
-
- impl text_input::StyleSheet for TextInput {
- fn active(&self) -> text_input::Style {
- text_input::Style {
- background: SURFACE.into(),
- border_radius: 2.0,
- border_width: 0.0,
- border_color: Color::TRANSPARENT,
- }
- }
-
- fn focused(&self) -> text_input::Style {
- text_input::Style {
- border_width: 1.0,
- border_color: ACCENT,
- ..self.active()
- }
- }
-
- fn hovered(&self) -> text_input::Style {
- text_input::Style {
- border_width: 1.0,
- border_color: Color { a: 0.3, ..ACCENT },
- ..self.focused()
- }
- }
-
- fn placeholder_color(&self) -> Color {
- Color::from_rgb(0.4, 0.4, 0.4)
- }
-
- fn value_color(&self) -> Color {
- Color::WHITE
- }
-
- fn selection_color(&self) -> Color {
- ACTIVE
- }
- }
-
- pub struct Button;
-
- impl button::StyleSheet for Button {
- fn active(&self) -> button::Style {
- button::Style {
- background: ACTIVE.into(),
- border_radius: 3.0,
- text_color: Color::WHITE,
- ..button::Style::default()
- }
- }
-
- fn hovered(&self) -> button::Style {
- button::Style {
- background: HOVERED.into(),
- text_color: Color::WHITE,
- ..self.active()
- }
- }
-
- fn pressed(&self) -> button::Style {
- button::Style {
- border_width: 1.0,
- border_color: Color::WHITE,
- ..self.hovered()
- }
- }
- }
-
- pub struct Scrollable;
-
- impl scrollable::StyleSheet for Scrollable {
- fn active(&self) -> scrollable::Scrollbar {
- scrollable::Scrollbar {
- background: SURFACE.into(),
- border_radius: 2.0,
- border_width: 0.0,
- border_color: Color::TRANSPARENT,
- scroller: scrollable::Scroller {
- color: ACTIVE,
- border_radius: 2.0,
- border_width: 0.0,
- border_color: Color::TRANSPARENT,
- },
- }
- }
-
- fn hovered(&self) -> scrollable::Scrollbar {
- let active = self.active();
-
- scrollable::Scrollbar {
- background: Color { a: 0.5, ..SURFACE }.into(),
- scroller: scrollable::Scroller {
- color: HOVERED,
- ..active.scroller
- },
- ..active
- }
- }
-
- fn dragging(&self) -> scrollable::Scrollbar {
- let hovered = self.hovered();
-
- scrollable::Scrollbar {
- scroller: scrollable::Scroller {
- color: Color::from_rgb(0.85, 0.85, 0.85),
- ..hovered.scroller
- },
- ..hovered
- }
- }
- }
-
- pub struct Slider;
-
- impl slider::StyleSheet for Slider {
- fn active(&self) -> slider::Style {
- slider::Style {
- rail_colors: (ACTIVE, Color { a: 0.1, ..ACTIVE }),
- handle: slider::Handle {
- shape: slider::HandleShape::Circle { radius: 9.0 },
- color: ACTIVE,
- border_width: 0.0,
- border_color: Color::TRANSPARENT,
- },
- }
- }
-
- fn hovered(&self) -> slider::Style {
- let active = self.active();
-
- slider::Style {
- handle: slider::Handle {
- color: HOVERED,
- ..active.handle
- },
- ..active
- }
- }
-
- fn dragging(&self) -> slider::Style {
- let active = self.active();
-
- slider::Style {
- handle: slider::Handle {
- color: Color::from_rgb(0.85, 0.85, 0.85),
- ..active.handle
- },
- ..active
- }
- }
- }
-
- pub struct ProgressBar;
-
- impl progress_bar::StyleSheet for ProgressBar {
- fn style(&self) -> progress_bar::Style {
- progress_bar::Style {
- background: SURFACE.into(),
- bar: ACTIVE.into(),
- border_radius: 10.0,
- }
- }
- }
-
- pub struct Checkbox;
-
- impl checkbox::StyleSheet for Checkbox {
- fn active(&self, is_checked: bool) -> checkbox::Style {
- checkbox::Style {
- background: if is_checked { ACTIVE } else { SURFACE }
- .into(),
- checkmark_color: Color::WHITE,
- border_radius: 2.0,
- border_width: 1.0,
- border_color: ACTIVE,
- text_color: None,
- }
- }
-
- fn hovered(&self, is_checked: bool) -> checkbox::Style {
- checkbox::Style {
- background: Color {
- a: 0.8,
- ..if is_checked { ACTIVE } else { SURFACE }
- }
- .into(),
- ..self.active(is_checked)
- }
- }
- }
-
- pub struct Toggler;
-
- impl toggler::StyleSheet for Toggler {
- fn active(&self, is_active: bool) -> toggler::Style {
- toggler::Style {
- background: if is_active { ACTIVE } else { SURFACE },
- background_border: None,
- foreground: if is_active { Color::WHITE } else { ACTIVE },
- foreground_border: None,
- }
- }
-
- fn hovered(&self, is_active: bool) -> toggler::Style {
- toggler::Style {
- background: if is_active { ACTIVE } else { SURFACE },
- background_border: None,
- foreground: if is_active {
- Color {
- a: 0.5,
- ..Color::WHITE
- }
- } else {
- Color { a: 0.5, ..ACTIVE }
- },
- foreground_border: None,
- }
- }
- }
-
- pub struct Rule;
-
- impl rule::StyleSheet for Rule {
- fn style(&self) -> rule::Style {
- rule::Style {
- color: SURFACE,
- width: 2,
- radius: 1.0,
- fill_mode: rule::FillMode::Padded(15),
- }
- }
- }
+ fn theme(&self) -> Theme {
+ self.theme
}
}
diff --git a/examples/system_information/src/main.rs b/examples/system_information/src/main.rs
index 560220b8..9e6a2f61 100644
--- a/examples/system_information/src/main.rs
+++ b/examples/system_information/src/main.rs
@@ -1,6 +1,6 @@
use iced::{
button, executor, system, Application, Button, Column, Command, Container,
- Element, Length, Settings, Text,
+ Element, Length, Settings, Text, Theme,
};
use bytesize::ByteSize;
@@ -25,6 +25,7 @@ enum Message {
impl Application for Example {
type Message = Message;
+ type Theme = Theme;
type Executor = executor::Default;
type Flags = ();
diff --git a/examples/todos/src/main.rs b/examples/todos/src/main.rs
index 0b889407..dc080ef5 100644
--- a/examples/todos/src/main.rs
+++ b/examples/todos/src/main.rs
@@ -2,9 +2,10 @@ use iced::alignment::{self, Alignment};
use iced::button::{self, Button};
use iced::scrollable::{self, Scrollable};
use iced::text_input::{self, TextInput};
+use iced::theme::{self, Theme};
use iced::{
- Application, Checkbox, Column, Command, Container, Element, Font, Length,
- Row, Settings, Text,
+ Application, Checkbox, Color, Column, Command, Container, Element, Font,
+ Length, Row, Settings, Text,
};
use serde::{Deserialize, Serialize};
@@ -42,6 +43,7 @@ enum Message {
impl Application for Todos {
type Executor = iced::executor::Default;
+ type Theme = Theme;
type Message = Message;
type Flags = ();
@@ -153,7 +155,7 @@ impl Application for Todos {
let title = Text::new("todos")
.width(Length::Fill)
.size(100)
- .color([0.5, 0.5, 0.5])
+ .style(Color::from([0.5, 0.5, 0.5]))
.horizontal_alignment(alignment::Horizontal::Center);
let input = TextInput::new(
@@ -304,7 +306,7 @@ impl Task {
Button::new(edit_button, edit_icon())
.on_press(TaskMessage::Edit)
.padding(10)
- .style(style::Button::Icon),
+ .style(theme::Button::Text),
)
.into()
}
@@ -335,7 +337,7 @@ impl Task {
)
.on_press(TaskMessage::Delete)
.padding(10)
- .style(style::Button::Destructive),
+ .style(theme::Button::Destructive),
)
.into()
}
@@ -364,9 +366,9 @@ impl Controls {
let label = Text::new(label).size(16);
let button =
Button::new(state, label).style(if filter == current_filter {
- style::Button::FilterSelected
+ theme::Button::Primary
} else {
- style::Button::FilterActive
+ theme::Button::Text
});
button.on_press(Message::FilterChanged(filter)).padding(8)
@@ -451,7 +453,7 @@ fn empty_message<'a>(message: &str) -> Element<'a, Message> {
.width(Length::Fill)
.size(25)
.horizontal_alignment(alignment::Horizontal::Center)
- .color([0.7, 0.7, 0.7]),
+ .style(Color::from([0.7, 0.7, 0.7])),
)
.width(Length::Fill)
.height(Length::Units(200))
@@ -599,57 +601,3 @@ impl SavedState {
Ok(())
}
}
-
-mod style {
- use iced::{button, Background, Color, Vector};
-
- pub enum Button {
- FilterActive,
- FilterSelected,
- Icon,
- Destructive,
- }
-
- impl button::StyleSheet for Button {
- fn active(&self) -> button::Style {
- match self {
- Button::FilterActive => button::Style::default(),
- Button::FilterSelected => button::Style {
- background: Some(Background::Color(Color::from_rgb(
- 0.2, 0.2, 0.7,
- ))),
- border_radius: 10.0,
- text_color: Color::WHITE,
- ..button::Style::default()
- },
- Button::Icon => button::Style {
- text_color: Color::from_rgb(0.5, 0.5, 0.5),
- ..button::Style::default()
- },
- Button::Destructive => button::Style {
- background: Some(Background::Color(Color::from_rgb(
- 0.8, 0.2, 0.2,
- ))),
- border_radius: 5.0,
- text_color: Color::WHITE,
- shadow_offset: Vector::new(1.0, 1.0),
- ..button::Style::default()
- },
- }
- }
-
- fn hovered(&self) -> button::Style {
- let active = self.active();
-
- button::Style {
- text_color: match self {
- Button::Icon => Color::from_rgb(0.2, 0.2, 0.7),
- Button::FilterActive => Color::from_rgb(0.2, 0.2, 0.7),
- _ => active.text_color,
- },
- shadow_offset: active.shadow_offset + Vector::new(0.0, 1.0),
- ..active
- }
- }
- }
-}
diff --git a/examples/tooltip/src/main.rs b/examples/tooltip/src/main.rs
index cfeaf6a6..1bd1133c 100644
--- a/examples/tooltip/src/main.rs
+++ b/examples/tooltip/src/main.rs
@@ -1,7 +1,9 @@
+use iced::alignment::{self, Alignment};
+use iced::button;
+use iced::theme;
use iced::tooltip::{self, Tooltip};
use iced::{
- alignment, button, Alignment, Button, Column, Container, Element, Length,
- Row, Sandbox, Settings, Text,
+ Button, Column, Container, Element, Length, Row, Sandbox, Settings, Text,
};
pub fn main() {
@@ -115,24 +117,6 @@ fn tooltip<'a>(
)
.gap(5)
.padding(10)
- .style(style::Tooltip)
+ .style(theme::Container::Box)
.into()
}
-
-mod style {
- use iced::container;
- use iced::Color;
-
- pub struct Tooltip;
-
- impl container::StyleSheet for Tooltip {
- fn style(&self) -> container::Style {
- container::Style {
- text_color: Some(Color::from_rgb8(0xEE, 0xEE, 0xEE)),
- background: Some(Color::from_rgb(0.11, 0.42, 0.87).into()),
- border_radius: 12.0,
- ..container::Style::default()
- }
- }
- }
-}
diff --git a/examples/tour/src/main.rs b/examples/tour/src/main.rs
index 2024d25a..d85f2916 100644
--- a/examples/tour/src/main.rs
+++ b/examples/tour/src/main.rs
@@ -1,7 +1,13 @@
+use iced::alignment;
+use iced::button;
+use iced::scrollable;
+use iced::slider;
+use iced::text_input;
+use iced::theme;
use iced::{
- alignment, button, scrollable, slider, text_input, Button, Checkbox, Color,
- Column, Container, ContentFit, Element, Image, Length, Radio, Row, Sandbox,
- Scrollable, Settings, Slider, Space, Text, TextInput, Toggler,
+ Button, Checkbox, Color, Column, Container, ContentFit, Element, Image,
+ Length, Radio, Row, Sandbox, Scrollable, Settings, Slider, Space, Text,
+ TextInput, Toggler,
};
pub fn main() -> iced::Result {
@@ -64,7 +70,7 @@ impl Sandbox for Tour {
controls = controls.push(
button(back_button, "Back")
.on_press(Message::BackPressed)
- .style(style::Button::Secondary),
+ .style(theme::Button::Secondary),
);
}
@@ -74,7 +80,7 @@ impl Sandbox for Tour {
controls = controls.push(
button(next_button, "Next")
.on_press(Message::NextPressed)
- .style(style::Button::Primary),
+ .style(theme::Button::Primary),
);
}
@@ -132,7 +138,7 @@ impl Steps {
size_slider: slider::State::new(),
size: 30,
color_sliders: [slider::State::new(); 3],
- color: Color::BLACK,
+ color: Color::from_rgb(0.5, 0.5, 0.5),
},
Step::Radio { selection: None },
Step::Toggler {
@@ -528,7 +534,7 @@ impl<'a> Step {
.padding(20)
.spacing(20)
.push(Text::new("And its color:"))
- .push(Text::new(format!("{:?}", color)).color(color))
+ .push(Text::new(format!("{:?}", color)).style(color))
.push(color_sliders);
Self::container("Text")
@@ -710,7 +716,7 @@ impl<'a> Step {
.push(if cfg!(target_arch = "wasm32") {
Element::new(
Text::new("Not available on web yet!")
- .color([0.7, 0.7, 0.7])
+ .style(Color::from([0.7, 0.7, 0.7]))
.horizontal_alignment(alignment::Horizontal::Center),
)
} else {
@@ -770,7 +776,7 @@ fn color_slider(
state: &mut slider::State,
component: f32,
update: impl Fn(f32) -> Color + 'static,
-) -> Slider<f64, StepMessage> {
+) -> Slider<f64, StepMessage, iced::Renderer> {
Slider::new(state, 0.0..=1.0, f64::from(component), move |c| {
StepMessage::TextColorChanged(update(c as f32))
})
@@ -818,36 +824,3 @@ pub enum Layout {
Row,
Column,
}
-
-mod style {
- use iced::button;
- use iced::{Background, Color, Vector};
-
- pub enum Button {
- Primary,
- Secondary,
- }
-
- impl button::StyleSheet for Button {
- fn active(&self) -> button::Style {
- button::Style {
- background: Some(Background::Color(match self {
- Button::Primary => Color::from_rgb(0.11, 0.42, 0.87),
- Button::Secondary => Color::from_rgb(0.5, 0.5, 0.5),
- })),
- border_radius: 12.0,
- shadow_offset: Vector::new(1.0, 1.0),
- text_color: Color::from_rgb8(0xEE, 0xEE, 0xEE),
- ..button::Style::default()
- }
- }
-
- fn hovered(&self) -> button::Style {
- button::Style {
- text_color: Color::WHITE,
- shadow_offset: Vector::new(1.0, 2.0),
- ..self.active()
- }
- }
- }
-}
diff --git a/examples/url_handler/src/main.rs b/examples/url_handler/src/main.rs
index ee2d249a..b544c30d 100644
--- a/examples/url_handler/src/main.rs
+++ b/examples/url_handler/src/main.rs
@@ -1,6 +1,7 @@
+use iced::executor;
use iced::{
- executor, Application, Command, Container, Element, Length, Settings,
- Subscription, Text,
+ Application, Command, Container, Element, Length, Settings, Subscription,
+ Text, Theme,
};
use iced_native::{
event::{MacOS, PlatformSpecific},
@@ -22,8 +23,9 @@ enum Message {
}
impl Application for App {
- type Executor = executor::Default;
type Message = Message;
+ type Theme = Theme;
+ type Executor = executor::Default;
type Flags = ();
fn new(_flags: ()) -> (App, Command<Message>) {
diff --git a/examples/websocket/src/main.rs b/examples/websocket/src/main.rs
index c03a9f3a..64addc8f 100644
--- a/examples/websocket/src/main.rs
+++ b/examples/websocket/src/main.rs
@@ -7,7 +7,7 @@ use iced::scrollable::{self, Scrollable};
use iced::text_input::{self, TextInput};
use iced::{
Application, Color, Column, Command, Container, Element, Length, Row,
- Settings, Subscription, Text,
+ Settings, Subscription, Text, Theme,
};
pub fn main() -> iced::Result {
@@ -34,6 +34,7 @@ enum Message {
impl Application for WebSocket {
type Message = Message;
+ type Theme = Theme;
type Flags = ();
type Executor = executor::Default;
@@ -91,7 +92,7 @@ impl Application for WebSocket {
let message_log = if self.messages.is_empty() {
Container::new(
Text::new("Your messages will appear here...")
- .color(Color::from_rgb8(0x88, 0x88, 0x88)),
+ .style(Color::from_rgb8(0x88, 0x88, 0x88)),
)
.width(Length::Fill)
.height(Length::Fill)