Simplify theming for Text widget
This commit is contained in:
parent
ce309db37b
commit
4130ae4be9
12 changed files with 116 additions and 122 deletions
|
|
@ -29,7 +29,7 @@ where
|
||||||
vertical_alignment: alignment::Vertical,
|
vertical_alignment: alignment::Vertical,
|
||||||
font: Option<Renderer::Font>,
|
font: Option<Renderer::Font>,
|
||||||
shaping: Shaping,
|
shaping: Shaping,
|
||||||
style: Theme::Style,
|
style: Style<Theme>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Theme, Renderer> Text<'a, Theme, Renderer>
|
impl<'a, Theme, Renderer> Text<'a, Theme, Renderer>
|
||||||
|
|
@ -49,7 +49,7 @@ where
|
||||||
horizontal_alignment: alignment::Horizontal::Left,
|
horizontal_alignment: alignment::Horizontal::Left,
|
||||||
vertical_alignment: alignment::Vertical::Top,
|
vertical_alignment: alignment::Vertical::Top,
|
||||||
shaping: Shaping::Basic,
|
shaping: Shaping::Basic,
|
||||||
style: Default::default(),
|
style: Style::Themed(Theme::default()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,8 +74,20 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the style of the [`Text`].
|
/// Sets the style of the [`Text`].
|
||||||
pub fn style(mut self, style: impl Into<Theme::Style>) -> Self {
|
pub fn style(mut self, style: fn(&Theme) -> Appearance) -> Self {
|
||||||
self.style = style.into();
|
self.style = Style::Themed(style);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the [`Color`] of the [`Text`].
|
||||||
|
pub fn color(mut self, color: impl Into<Color>) -> Self {
|
||||||
|
self.style = Style::Colored(Some(color.into()));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the [`Color`] of the [`Text`].
|
||||||
|
pub fn color_maybe(mut self, color: Option<impl Into<Color>>) -> Self {
|
||||||
|
self.style = Style::Colored(color.map(Into::into));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -175,14 +187,12 @@ where
|
||||||
) {
|
) {
|
||||||
let state = tree.state.downcast_ref::<State<Renderer::Paragraph>>();
|
let state = tree.state.downcast_ref::<State<Renderer::Paragraph>>();
|
||||||
|
|
||||||
draw(
|
let appearance = match self.style {
|
||||||
renderer,
|
Style::Themed(f) => f(theme),
|
||||||
style,
|
Style::Colored(color) => Appearance { color },
|
||||||
layout,
|
};
|
||||||
state,
|
|
||||||
theme.appearance(self.style.clone()),
|
draw(renderer, style, layout, state, appearance, viewport);
|
||||||
viewport,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -298,7 +308,7 @@ where
|
||||||
horizontal_alignment: self.horizontal_alignment,
|
horizontal_alignment: self.horizontal_alignment,
|
||||||
vertical_alignment: self.vertical_alignment,
|
vertical_alignment: self.vertical_alignment,
|
||||||
font: self.font,
|
font: self.font,
|
||||||
style: self.style.clone(),
|
style: self.style,
|
||||||
shaping: self.shaping,
|
shaping: self.shaping,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -327,11 +337,18 @@ where
|
||||||
|
|
||||||
/// The style sheet of some text.
|
/// The style sheet of some text.
|
||||||
pub trait StyleSheet {
|
pub trait StyleSheet {
|
||||||
/// The supported style of the [`StyleSheet`].
|
/// Returns the default styling strategy for [`Text`].
|
||||||
type Style: Default + Clone;
|
fn default() -> fn(&Self) -> Appearance {
|
||||||
|
|_| Appearance::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Produces the [`Appearance`] of some text.
|
impl StyleSheet for Color {
|
||||||
fn appearance(&self, style: Self::Style) -> Appearance;
|
fn default() -> fn(&Self) -> Appearance {
|
||||||
|
|color| Appearance {
|
||||||
|
color: Some(*color),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The apperance of some text.
|
/// The apperance of some text.
|
||||||
|
|
@ -342,3 +359,17 @@ pub struct Appearance {
|
||||||
/// The default, `None`, means using the inherited color.
|
/// The default, `None`, means using the inherited color.
|
||||||
pub color: Option<Color>,
|
pub color: Option<Color>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Style<Theme> {
|
||||||
|
Themed(fn(&Theme) -> Appearance),
|
||||||
|
Colored(Option<Color>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Theme> Clone for Style<Theme> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Theme> Copy for Style<Theme> {}
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,26 @@
|
||||||
use iced_wgpu::Renderer;
|
use iced_wgpu::Renderer;
|
||||||
use iced_widget::{slider, text_input, Column, Row, Text};
|
use iced_widget::{column, container, row, slider, text, text_input};
|
||||||
use iced_winit::core::{Alignment, Color, Element, Length};
|
use iced_winit::core::alignment;
|
||||||
|
use iced_winit::core::{Color, Element, Length};
|
||||||
use iced_winit::runtime::{Command, Program};
|
use iced_winit::runtime::{Command, Program};
|
||||||
use iced_winit::style::Theme;
|
use iced_winit::style::Theme;
|
||||||
|
|
||||||
pub struct Controls {
|
pub struct Controls {
|
||||||
background_color: Color,
|
background_color: Color,
|
||||||
text: String,
|
input: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
BackgroundColorChanged(Color),
|
BackgroundColorChanged(Color),
|
||||||
TextChanged(String),
|
InputChanged(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Controls {
|
impl Controls {
|
||||||
pub fn new() -> Controls {
|
pub fn new() -> Controls {
|
||||||
Controls {
|
Controls {
|
||||||
background_color: Color::BLACK,
|
background_color: Color::BLACK,
|
||||||
text: String::default(),
|
input: String::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -38,8 +39,8 @@ impl Program for Controls {
|
||||||
Message::BackgroundColorChanged(color) => {
|
Message::BackgroundColorChanged(color) => {
|
||||||
self.background_color = color;
|
self.background_color = color;
|
||||||
}
|
}
|
||||||
Message::TextChanged(text) => {
|
Message::InputChanged(input) => {
|
||||||
self.text = text;
|
self.input = input;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,60 +49,48 @@ impl Program for Controls {
|
||||||
|
|
||||||
fn view(&self) -> Element<Message, Theme, Renderer> {
|
fn view(&self) -> Element<Message, Theme, Renderer> {
|
||||||
let background_color = self.background_color;
|
let background_color = self.background_color;
|
||||||
let text = &self.text;
|
|
||||||
|
|
||||||
let sliders = Row::new()
|
let sliders = row![
|
||||||
.width(500)
|
slider(0.0..=1.0, background_color.r, move |r| {
|
||||||
.spacing(20)
|
Message::BackgroundColorChanged(Color {
|
||||||
.push(
|
r,
|
||||||
slider(0.0..=1.0, background_color.r, move |r| {
|
..background_color
|
||||||
Message::BackgroundColorChanged(Color {
|
|
||||||
r,
|
|
||||||
..background_color
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.step(0.01),
|
})
|
||||||
)
|
.step(0.01),
|
||||||
.push(
|
slider(0.0..=1.0, background_color.g, move |g| {
|
||||||
slider(0.0..=1.0, background_color.g, move |g| {
|
Message::BackgroundColorChanged(Color {
|
||||||
Message::BackgroundColorChanged(Color {
|
g,
|
||||||
g,
|
..background_color
|
||||||
..background_color
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.step(0.01),
|
})
|
||||||
)
|
.step(0.01),
|
||||||
.push(
|
slider(0.0..=1.0, background_color.b, move |b| {
|
||||||
slider(0.0..=1.0, background_color.b, move |b| {
|
Message::BackgroundColorChanged(Color {
|
||||||
Message::BackgroundColorChanged(Color {
|
b,
|
||||||
b,
|
..background_color
|
||||||
..background_color
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.step(0.01),
|
})
|
||||||
);
|
.step(0.01),
|
||||||
|
]
|
||||||
|
.width(500)
|
||||||
|
.spacing(20);
|
||||||
|
|
||||||
Row::new()
|
container(
|
||||||
.height(Length::Fill)
|
column![
|
||||||
.align_items(Alignment::End)
|
text("Background color").color(Color::WHITE),
|
||||||
.push(
|
text(format!("{background_color:?}"))
|
||||||
Column::new().align_items(Alignment::End).push(
|
.size(14)
|
||||||
Column::new()
|
.color(Color::WHITE),
|
||||||
.padding(10)
|
text_input("Placeholder", &self.input)
|
||||||
.spacing(10)
|
.on_input(Message::InputChanged),
|
||||||
.push(Text::new("Background color").style(Color::WHITE))
|
sliders,
|
||||||
.push(sliders)
|
]
|
||||||
.push(
|
.spacing(10),
|
||||||
Text::new(format!("{background_color:?}"))
|
)
|
||||||
.size(14)
|
.padding(10)
|
||||||
.style(Color::WHITE),
|
.height(Length::Fill)
|
||||||
)
|
.align_y(alignment::Vertical::Bottom)
|
||||||
.push(
|
.into()
|
||||||
text_input("Placeholder", text)
|
|
||||||
.on_input(Message::TextChanged),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -184,8 +184,7 @@ impl Sandbox for App {
|
||||||
.style(theme::Button::Destructive);
|
.style(theme::Button::Destructive);
|
||||||
|
|
||||||
row![
|
row![
|
||||||
text(&item.name)
|
text(&item.name).color(item.color),
|
||||||
.style(theme::Text::Color(item.color.into())),
|
|
||||||
horizontal_space(),
|
horizontal_space(),
|
||||||
pick_list(Color::ALL, Some(item.color), move |color| {
|
pick_list(Color::ALL, Some(item.color), move |color| {
|
||||||
Message::ItemColorChanged(item.clone(), color)
|
Message::ItemColorChanged(item.clone(), color)
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,7 @@ impl Application for Example {
|
||||||
let title = row![
|
let title = row![
|
||||||
pin_button,
|
pin_button,
|
||||||
"Pane",
|
"Pane",
|
||||||
text(pane.id.to_string()).style(if is_focused {
|
text(pane.id.to_string()).color(if is_focused {
|
||||||
PANE_ID_COLOR_FOCUSED
|
PANE_ID_COLOR_FOCUSED
|
||||||
} else {
|
} else {
|
||||||
PANE_ID_COLOR_UNFOCUSED
|
PANE_ID_COLOR_UNFOCUSED
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
use iced::futures;
|
use iced::futures;
|
||||||
use iced::widget::{self, column, container, image, row, text};
|
use iced::widget::{self, column, container, image, row, text};
|
||||||
use iced::{
|
use iced::{Alignment, Application, Command, Element, Length, Settings, Theme};
|
||||||
Alignment, Application, Color, Command, Element, Length, Settings, Theme,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
Pokedex::run(Settings::default())
|
Pokedex::run(Settings::default())
|
||||||
|
|
@ -116,7 +114,7 @@ impl Pokemon {
|
||||||
text(&self.name).size(30).width(Length::Fill),
|
text(&self.name).size(30).width(Length::Fill),
|
||||||
text(format!("#{}", self.number))
|
text(format!("#{}", self.number))
|
||||||
.size(20)
|
.size(20)
|
||||||
.style(Color::from([0.5, 0.5, 0.5])),
|
.color([0.5, 0.5, 0.5]),
|
||||||
]
|
]
|
||||||
.align_items(Alignment::Center)
|
.align_items(Alignment::Center)
|
||||||
.spacing(20),
|
.spacing(20),
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use iced::widget::{
|
||||||
};
|
};
|
||||||
use iced::window;
|
use iced::window;
|
||||||
use iced::{Application, Element};
|
use iced::{Application, Element};
|
||||||
use iced::{Color, Command, Length, Settings, Size, Subscription};
|
use iced::{Command, Length, Settings, Size, Subscription};
|
||||||
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
@ -209,7 +209,7 @@ impl Application for Todos {
|
||||||
let title = text("todos")
|
let title = text("todos")
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.size(100)
|
.size(100)
|
||||||
.style(Color::from([0.5, 0.5, 0.5]))
|
.color([0.5, 0.5, 0.5])
|
||||||
.horizontal_alignment(alignment::Horizontal::Center);
|
.horizontal_alignment(alignment::Horizontal::Center);
|
||||||
|
|
||||||
let input = text_input("What needs to be done?", input_value)
|
let input = text_input("What needs to be done?", input_value)
|
||||||
|
|
@ -467,7 +467,7 @@ fn empty_message(message: &str) -> Element<'_, Message> {
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.size(25)
|
.size(25)
|
||||||
.horizontal_alignment(alignment::Horizontal::Center)
|
.horizontal_alignment(alignment::Horizontal::Center)
|
||||||
.style(Color::from([0.7, 0.7, 0.7])),
|
.color([0.7, 0.7, 0.7]),
|
||||||
)
|
)
|
||||||
.height(200)
|
.height(200)
|
||||||
.center_y()
|
.center_y()
|
||||||
|
|
|
||||||
|
|
@ -474,7 +474,7 @@ impl<'a> Step {
|
||||||
|
|
||||||
let color_section = column![
|
let color_section = column![
|
||||||
"And its color:",
|
"And its color:",
|
||||||
text(format!("{color:?}")).style(color),
|
text(format!("{color:?}")).color(color),
|
||||||
color_sliders,
|
color_sliders,
|
||||||
]
|
]
|
||||||
.padding(20)
|
.padding(20)
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,10 @@ impl Application for Example {
|
||||||
row![
|
row![
|
||||||
text(label),
|
text(label),
|
||||||
horizontal_space(),
|
horizontal_space(),
|
||||||
text(value).font(Font::MONOSPACE).size(14).style(color),
|
text(value)
|
||||||
|
.font(Font::MONOSPACE)
|
||||||
|
.size(14)
|
||||||
|
.color_maybe(color),
|
||||||
]
|
]
|
||||||
.height(40)
|
.height(40)
|
||||||
.align_items(Alignment::Center)
|
.align_items(Alignment::Center)
|
||||||
|
|
@ -102,13 +105,12 @@ impl Application for Example {
|
||||||
})
|
})
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
{
|
{
|
||||||
Color {
|
Some(Color {
|
||||||
g: 1.0,
|
g: 1.0,
|
||||||
..Color::BLACK
|
..Color::BLACK
|
||||||
}
|
})
|
||||||
.into()
|
|
||||||
} else {
|
} else {
|
||||||
theme::Text::Default
|
None
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
@ -120,7 +122,7 @@ impl Application for Example {
|
||||||
Some(Point { x, y }) => format!("({x}, {y})"),
|
Some(Point { x, y }) => format!("({x}, {y})"),
|
||||||
None => "unknown".to_string(),
|
None => "unknown".to_string(),
|
||||||
},
|
},
|
||||||
theme::Text::Default,
|
None,
|
||||||
),
|
),
|
||||||
view_bounds("Outer container", self.outer_bounds),
|
view_bounds("Outer container", self.outer_bounds),
|
||||||
view_bounds("Inner container", self.inner_bounds),
|
view_bounds("Inner container", self.inner_bounds),
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use iced::widget::{
|
||||||
button, column, container, row, scrollable, text, text_input,
|
button, column, container, row, scrollable, text, text_input,
|
||||||
};
|
};
|
||||||
use iced::{
|
use iced::{
|
||||||
Application, Color, Command, Element, Length, Settings, Subscription, Theme,
|
color, Application, Command, Element, Length, Settings, Subscription, Theme,
|
||||||
};
|
};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
|
|
@ -99,7 +99,7 @@ impl Application for WebSocket {
|
||||||
let message_log: Element<_> = if self.messages.is_empty() {
|
let message_log: Element<_> = if self.messages.is_empty() {
|
||||||
container(
|
container(
|
||||||
text("Your messages will appear here...")
|
text("Your messages will appear here...")
|
||||||
.style(Color::from_rgb8(0x88, 0x88, 0x88)),
|
.color(color!(0x888888)),
|
||||||
)
|
)
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.height(Length::Fill)
|
.height(Length::Fill)
|
||||||
|
|
|
||||||
|
|
@ -1203,32 +1203,7 @@ impl scrollable::StyleSheet for Theme {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The style of text.
|
impl text::StyleSheet for Theme {}
|
||||||
#[derive(Clone, Copy, Default)]
|
|
||||||
pub enum Text {
|
|
||||||
/// The default style.
|
|
||||||
#[default]
|
|
||||||
Default,
|
|
||||||
/// Colored text.
|
|
||||||
Color(Color),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Color> for Text {
|
|
||||||
fn from(color: Color) -> Self {
|
|
||||||
Text::Color(color)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl text::StyleSheet for Theme {
|
|
||||||
type Style = Text;
|
|
||||||
|
|
||||||
fn appearance(&self, style: Self::Style) -> text::Appearance {
|
|
||||||
match style {
|
|
||||||
Text::Default => text::Appearance::default(),
|
|
||||||
Text::Color(c) => text::Appearance { color: Some(c) },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The style of a text input.
|
/// The style of a text input.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ pub struct Checkbox<
|
||||||
Theme = crate::Theme,
|
Theme = crate::Theme,
|
||||||
Renderer = crate::Renderer,
|
Renderer = crate::Renderer,
|
||||||
> where
|
> where
|
||||||
Theme: StyleSheet + crate::text::StyleSheet,
|
Theme: StyleSheet,
|
||||||
Renderer: text::Renderer,
|
Renderer: text::Renderer,
|
||||||
{
|
{
|
||||||
is_checked: bool,
|
is_checked: bool,
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ pub struct Tooltip<
|
||||||
Theme = crate::Theme,
|
Theme = crate::Theme,
|
||||||
Renderer = crate::Renderer,
|
Renderer = crate::Renderer,
|
||||||
> where
|
> where
|
||||||
Theme: container::StyleSheet + crate::text::StyleSheet,
|
Theme: container::StyleSheet,
|
||||||
Renderer: text::Renderer,
|
Renderer: text::Renderer,
|
||||||
{
|
{
|
||||||
content: Element<'a, Message, Theme, Renderer>,
|
content: Element<'a, Message, Theme, Renderer>,
|
||||||
|
|
@ -34,7 +34,7 @@ pub struct Tooltip<
|
||||||
|
|
||||||
impl<'a, Message, Theme, Renderer> Tooltip<'a, Message, Theme, Renderer>
|
impl<'a, Message, Theme, Renderer> Tooltip<'a, Message, Theme, Renderer>
|
||||||
where
|
where
|
||||||
Theme: container::StyleSheet + crate::text::StyleSheet,
|
Theme: container::StyleSheet,
|
||||||
Renderer: text::Renderer,
|
Renderer: text::Renderer,
|
||||||
{
|
{
|
||||||
/// The default padding of a [`Tooltip`] drawn by this renderer.
|
/// The default padding of a [`Tooltip`] drawn by this renderer.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue