first_push
This commit is contained in:
commit
ca41081e8f
18 changed files with 5559 additions and 0 deletions
4215
Cargo.lock
generated
Normal file
4215
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
29
Cargo.toml
Normal file
29
Cargo.toml
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
[package]
|
||||||
|
name = "iced-material"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
palette = "*"
|
||||||
|
freedesktop-icons = "*"
|
||||||
|
|
||||||
|
[dependencies.iced]
|
||||||
|
#git = "https://github.com/ibaryshnikov/iced.git"
|
||||||
|
#rev = "901bbeb"
|
||||||
|
features = ["wgpu","lazy","svg","advanced"]
|
||||||
|
path = "../../iced"
|
||||||
|
|
||||||
|
[dependencies.iced_winit]
|
||||||
|
#git = "https://github.com/ibaryshnikov/iced.git"
|
||||||
|
#rev = "901bbeb"
|
||||||
|
path = "../../iced/winit"
|
||||||
|
|
||||||
|
|
||||||
|
[dependencies.iced_wgpu]
|
||||||
|
#git = "https://github.com/ibaryshnikov/iced.git"
|
||||||
|
#rev = "901bbeb"
|
||||||
|
path = "../../iced/wgpu"
|
||||||
|
|
||||||
|
#iced = {git="https://github.com/iced-rs/iced",features=["lazy","svg","advanced"]}
|
||||||
71
src/header.rs
Normal file
71
src/header.rs
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
use crate::iced_material;
|
||||||
|
use crate::icon;
|
||||||
|
use iced::{
|
||||||
|
alignment::Alignment,
|
||||||
|
widget::{button, container, row, text, Space},
|
||||||
|
Element, Length, Padding,
|
||||||
|
};
|
||||||
|
//pub const fun stri
|
||||||
|
pub fn header<'a, Message, Renderer>(
|
||||||
|
side_button: Message,
|
||||||
|
back_message: Message,
|
||||||
|
settings_button: Message,
|
||||||
|
exit_button: Message,
|
||||||
|
//page: &Page,
|
||||||
|
title: &str,
|
||||||
|
) -> Element<'a, Message, crate::theme::Theme, Renderer>
|
||||||
|
where
|
||||||
|
Message: 'a + Clone,
|
||||||
|
//Theme: 'a + text::Catalog + button::Catalog + svg::Catalog + container::Catalog,
|
||||||
|
Renderer: 'a + iced::advanced::text::Renderer + iced::advanced::svg::Renderer,
|
||||||
|
{
|
||||||
|
container(
|
||||||
|
row![
|
||||||
|
row!(
|
||||||
|
button(icon!("panel-left"))
|
||||||
|
.padding(4)
|
||||||
|
.width(30)
|
||||||
|
.height(30)
|
||||||
|
.on_press(side_button),
|
||||||
|
button(icon!("chevron-left"))
|
||||||
|
.padding(4)
|
||||||
|
.width(30)
|
||||||
|
.height(30)
|
||||||
|
.on_press(back_message),
|
||||||
|
)
|
||||||
|
.spacing(10),
|
||||||
|
Space::with_width(Length::Fill),
|
||||||
|
text!("{}", title),
|
||||||
|
Space::with_width(Length::Fill),
|
||||||
|
row!(
|
||||||
|
button(icon!("settings"))
|
||||||
|
.padding(4)
|
||||||
|
.on_press(settings_button)
|
||||||
|
.width(30)
|
||||||
|
.height(30),
|
||||||
|
button(icon!("x"))
|
||||||
|
.padding(4)
|
||||||
|
.on_press(exit_button)
|
||||||
|
.width(30)
|
||||||
|
.height(30)
|
||||||
|
)
|
||||||
|
.spacing(10),
|
||||||
|
]
|
||||||
|
.padding({
|
||||||
|
if cfg!(target_os = "android") {
|
||||||
|
Padding {
|
||||||
|
top: 40.,
|
||||||
|
left: 10.,
|
||||||
|
right: 10.,
|
||||||
|
bottom: 10.,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Padding::new(10.)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.align_y(Alignment::Center)
|
||||||
|
.spacing(10),
|
||||||
|
)
|
||||||
|
.style(crate::theme::container::grey)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
19
src/lib.rs
Normal file
19
src/lib.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
use iced::widget::{svg, Svg};
|
||||||
|
|
||||||
|
pub mod header;
|
||||||
|
pub mod sidebar;
|
||||||
|
pub mod theme;
|
||||||
|
|
||||||
|
pub fn svg_icon<'a>(bytes: &'static [u8]) -> Svg<'a, theme::Theme> {
|
||||||
|
svg(svg::Handle::from_memory(bytes))
|
||||||
|
}
|
||||||
|
use crate as iced_material;
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! icon {
|
||||||
|
($message_id:literal) => {{
|
||||||
|
iced_material::svg_icon(include_bytes!(concat!(
|
||||||
|
concat!("/home/me/workspace/lucide/icons/", $message_id),
|
||||||
|
".svg"
|
||||||
|
)))
|
||||||
|
}};
|
||||||
|
}
|
||||||
51
src/sidebar.rs
Normal file
51
src/sidebar.rs
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
use iced::{
|
||||||
|
alignment::Alignment,
|
||||||
|
widget::{button, column, container, scrollable, text},
|
||||||
|
Element, Length,
|
||||||
|
};
|
||||||
|
pub fn sidebar<'a, Message, Renderer>(
|
||||||
|
names: &[&str],
|
||||||
|
f: impl Fn(u8) -> Message + 'a,
|
||||||
|
) -> Element<'a, Message, crate::theme::Theme, Renderer>
|
||||||
|
where
|
||||||
|
Message: 'a + Clone,
|
||||||
|
// Theme: 'a
|
||||||
|
// + text::Catalog
|
||||||
|
// + button::Catalog
|
||||||
|
// + svg::Catalog
|
||||||
|
// + container::Catalog
|
||||||
|
// + scrollable::Catalog,
|
||||||
|
Renderer: 'a + iced::advanced::text::Renderer,
|
||||||
|
{
|
||||||
|
let options: Vec<Element<'_, _, _, _>> = names
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, title)| {
|
||||||
|
// hey
|
||||||
|
button(container(text!("{}", title)).center_y(Length::Fill))
|
||||||
|
.width(Length::Fill)
|
||||||
|
.height(50)
|
||||||
|
.on_press(f(i as u8))
|
||||||
|
// .style(move |theme, status| {
|
||||||
|
// if i as u8 == self.selected {
|
||||||
|
// text_button(theme, button::Status::Pressed)
|
||||||
|
// } else {
|
||||||
|
// text_button(theme, status)
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
.into()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
container(scrollable(
|
||||||
|
column(options)
|
||||||
|
.padding(10)
|
||||||
|
.align_x(Alignment::Center)
|
||||||
|
.spacing(10),
|
||||||
|
))
|
||||||
|
.height(Length::Fill)
|
||||||
|
.center_x(Length::Fill)
|
||||||
|
.style(crate::theme::container::light_grey)
|
||||||
|
.into()
|
||||||
|
//
|
||||||
|
}
|
||||||
366
src/theme/button.rs
Normal file
366
src/theme/button.rs
Normal file
|
|
@ -0,0 +1,366 @@
|
||||||
|
use iced::widget::button::{Catalog, Status, Style, StyleFn};
|
||||||
|
use iced::{Background, Border, Color};
|
||||||
|
|
||||||
|
use super::Theme;
|
||||||
|
|
||||||
|
impl Catalog for Theme {
|
||||||
|
type Class<'a> = StyleFn<'a, Self>;
|
||||||
|
|
||||||
|
fn default<'a>() -> Self::Class<'a> {
|
||||||
|
Box::new(text_button)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(&self, class: &Self::Class<'_>, status: Status) -> Style {
|
||||||
|
class(self, status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn text_button(theme: &Theme, status: Status) -> Style {
|
||||||
|
match status {
|
||||||
|
Status::Active | Status::Pressed => Style {
|
||||||
|
background: Some(Background::Color(theme.colors().text.high_alpha)),
|
||||||
|
text_color: theme.colors().text.base,
|
||||||
|
border: Border {
|
||||||
|
radius: 10.0.into(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Status::Hovered => Style {
|
||||||
|
background: Some(Background::Color(theme.colors().text.med_alpha)),
|
||||||
|
text_color: theme.colors().text.base,
|
||||||
|
border: Border {
|
||||||
|
radius: 10.0.into(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Status::Disabled => {
|
||||||
|
let active = text_button(theme, Status::Active);
|
||||||
|
|
||||||
|
Style {
|
||||||
|
text_color: Color {
|
||||||
|
a: 0.2,
|
||||||
|
..active.text_color
|
||||||
|
},
|
||||||
|
border: Border {
|
||||||
|
radius: 10.0.into(),
|
||||||
|
color: Color {
|
||||||
|
a: 0.2,
|
||||||
|
..active.text_color
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn icon_button(theme: &Theme, status: Status) -> Style {
|
||||||
|
match status {
|
||||||
|
Status::Active | Status::Pressed => Style {
|
||||||
|
background: Some(Background::Color(theme.colors().text.high_alpha)),
|
||||||
|
text_color: theme.colors().text.base,
|
||||||
|
border: Border {
|
||||||
|
radius: 10.0.into(),
|
||||||
|
width: 0.0.into(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Status::Hovered => Style {
|
||||||
|
background: Some(Background::Color(theme.colors().text.med_alpha)),
|
||||||
|
text_color: theme.colors().text.base,
|
||||||
|
border: Border {
|
||||||
|
radius: 10.0.into(),
|
||||||
|
width: 0.0.into(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Status::Disabled => {
|
||||||
|
let active = text_button(theme, Status::Active);
|
||||||
|
|
||||||
|
Style {
|
||||||
|
text_color: Color {
|
||||||
|
a: 0.2,
|
||||||
|
..active.text_color
|
||||||
|
},
|
||||||
|
border: Border {
|
||||||
|
color: Color {
|
||||||
|
a: 0.2,
|
||||||
|
..active.text_color
|
||||||
|
},
|
||||||
|
width: 0.0.into(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unselected(theme: &Theme, _status: Status) -> Style {
|
||||||
|
Style {
|
||||||
|
background: Some(Background::Color(theme.colors().background.dark)),
|
||||||
|
text_color: theme.colors().text.base,
|
||||||
|
border: Border {
|
||||||
|
radius: 10.0.into(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn selected(theme: &Theme, _status: Status) -> Style {
|
||||||
|
Style {
|
||||||
|
background: Some(Background::Color(theme.colors().background.darkest)),
|
||||||
|
text_color: theme.colors().text.base,
|
||||||
|
border: Border {
|
||||||
|
radius: 10.0.into(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn secondary(theme: &Theme, status: Status) -> Style {
|
||||||
|
match status {
|
||||||
|
Status::Active | Status::Pressed => Style {
|
||||||
|
background: Some(Background::Color(theme.colors().accent.high_alpha)),
|
||||||
|
text_color: theme.colors().accent.base,
|
||||||
|
border: Border {
|
||||||
|
radius: 3.0.into(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Status::Hovered => Style {
|
||||||
|
background: Some(Background::Color(theme.colors().accent.med_alpha)),
|
||||||
|
text_color: theme.colors().accent.base,
|
||||||
|
border: Border {
|
||||||
|
radius: 3.0.into(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Status::Disabled => {
|
||||||
|
let active = secondary(theme, Status::Active);
|
||||||
|
|
||||||
|
Style {
|
||||||
|
text_color: Color {
|
||||||
|
a: 0.2,
|
||||||
|
..active.text_color
|
||||||
|
},
|
||||||
|
border: Border {
|
||||||
|
color: Color {
|
||||||
|
a: 0.2,
|
||||||
|
..active.text_color
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tertiary(theme: &Theme, status: Status, selected: bool) -> Style {
|
||||||
|
match status {
|
||||||
|
Status::Active | Status::Pressed => Style {
|
||||||
|
background: Some(Background::Color(if selected {
|
||||||
|
theme.colors().action.med_alpha
|
||||||
|
} else {
|
||||||
|
theme.colors().background.dark
|
||||||
|
})),
|
||||||
|
border: Border {
|
||||||
|
color: if selected {
|
||||||
|
theme.colors().action.low_alpha
|
||||||
|
} else if theme.colors().is_dark_theme() {
|
||||||
|
theme.colors().background.lightest
|
||||||
|
} else {
|
||||||
|
theme.colors().background.darkest
|
||||||
|
},
|
||||||
|
width: 1.0,
|
||||||
|
radius: 3.0.into(),
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Status::Hovered => {
|
||||||
|
let active = tertiary(theme, Status::Active, selected);
|
||||||
|
|
||||||
|
Style {
|
||||||
|
background: Some(Background::Color(if selected {
|
||||||
|
theme.colors().action.high_alpha
|
||||||
|
} else if theme.colors().is_dark_theme() {
|
||||||
|
theme.colors().background.light
|
||||||
|
} else {
|
||||||
|
theme.colors().background.darker
|
||||||
|
})),
|
||||||
|
..active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Status::Disabled => {
|
||||||
|
let active = tertiary(theme, Status::Active, selected);
|
||||||
|
|
||||||
|
Style {
|
||||||
|
text_color: Color {
|
||||||
|
a: 0.2,
|
||||||
|
..active.text_color
|
||||||
|
},
|
||||||
|
border: Border {
|
||||||
|
color: Color {
|
||||||
|
a: 0.2,
|
||||||
|
..active.text_color
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn context(theme: &Theme, status: Status) -> Style {
|
||||||
|
match status {
|
||||||
|
Status::Active | Status::Pressed => Style {
|
||||||
|
background: Some(Background::Color(Color::TRANSPARENT)),
|
||||||
|
border: Border {
|
||||||
|
radius: 4.0.into(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Status::Hovered => {
|
||||||
|
let active = context(theme, Status::Active);
|
||||||
|
|
||||||
|
Style {
|
||||||
|
background: Some(Background::Color(theme.colors().background.darker)),
|
||||||
|
..active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Status::Disabled => {
|
||||||
|
let active = context(theme, Status::Active);
|
||||||
|
|
||||||
|
Style {
|
||||||
|
text_color: Color {
|
||||||
|
a: 0.2,
|
||||||
|
..active.text_color
|
||||||
|
},
|
||||||
|
border: Border {
|
||||||
|
color: Color {
|
||||||
|
a: 0.2,
|
||||||
|
..active.text_color
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bare(_theme: &Theme, status: Status) -> Style {
|
||||||
|
match status {
|
||||||
|
Status::Active | Status::Pressed | Status::Hovered => Style {
|
||||||
|
background: Some(Background::Color(Color::TRANSPARENT)),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Status::Disabled => {
|
||||||
|
let active = bare(_theme, Status::Active);
|
||||||
|
|
||||||
|
Style {
|
||||||
|
text_color: Color {
|
||||||
|
a: 0.2,
|
||||||
|
..active.text_color
|
||||||
|
},
|
||||||
|
border: Border {
|
||||||
|
color: Color {
|
||||||
|
a: 0.2,
|
||||||
|
..active.text_color
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn side_menu(theme: &Theme, status: Status) -> Style {
|
||||||
|
match status {
|
||||||
|
Status::Active | Status::Pressed => Style {
|
||||||
|
background: None,
|
||||||
|
border: Border {
|
||||||
|
radius: 3.0.into(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Status::Hovered => {
|
||||||
|
let active = side_menu(theme, Status::Active);
|
||||||
|
|
||||||
|
Style {
|
||||||
|
background: Some(Background::Color(theme.colors().background.dark)),
|
||||||
|
..active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Status::Disabled => {
|
||||||
|
let active = side_menu(theme, Status::Active);
|
||||||
|
|
||||||
|
Style {
|
||||||
|
text_color: Color {
|
||||||
|
a: 0.2,
|
||||||
|
..active.text_color
|
||||||
|
},
|
||||||
|
border: Border {
|
||||||
|
color: Color {
|
||||||
|
a: 0.2,
|
||||||
|
..active.text_color
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn side_menu_selected(theme: &Theme, status: Status) -> Style {
|
||||||
|
match status {
|
||||||
|
Status::Active | Status::Pressed => Style {
|
||||||
|
background: Some(Background::Color(theme.colors().background.darker)),
|
||||||
|
border: Border {
|
||||||
|
radius: 3.0.into(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Status::Hovered => {
|
||||||
|
let active = side_menu_selected(theme, Status::Active);
|
||||||
|
|
||||||
|
Style {
|
||||||
|
background: Some(Background::Color(theme.colors().background.darkest)),
|
||||||
|
..active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Status::Disabled => {
|
||||||
|
let active = side_menu_selected(theme, Status::Active);
|
||||||
|
|
||||||
|
Style {
|
||||||
|
text_color: Color {
|
||||||
|
a: 0.2,
|
||||||
|
..active.text_color
|
||||||
|
},
|
||||||
|
border: Border {
|
||||||
|
color: Color {
|
||||||
|
a: 0.2,
|
||||||
|
..active.text_color
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/theme/checkbox.rs
Normal file
33
src/theme/checkbox.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
use iced::{
|
||||||
|
widget::checkbox::{Catalog, Status, Style, StyleFn},
|
||||||
|
Border,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::Theme;
|
||||||
|
|
||||||
|
impl Catalog for Theme {
|
||||||
|
type Class<'a> = StyleFn<'a, Self>;
|
||||||
|
|
||||||
|
fn default<'a>() -> Self::Class<'a> {
|
||||||
|
Box::new(primary)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(&self, class: &Self::Class<'_>, status: iced::widget::checkbox::Status) -> Style {
|
||||||
|
class(self, status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn primary(theme: &Theme, status: Status) -> Style {
|
||||||
|
match status {
|
||||||
|
_ => Style {
|
||||||
|
background: iced::Background::Color(theme.colors().background.base),
|
||||||
|
icon_color: theme.colors().accent.base,
|
||||||
|
border: Border {
|
||||||
|
color: theme.colors().accent.base,
|
||||||
|
width: 1.0,
|
||||||
|
radius: 2.into(),
|
||||||
|
},
|
||||||
|
text_color: Some(theme.colors().text.base),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
147
src/theme/container.rs
Normal file
147
src/theme/container.rs
Normal file
|
|
@ -0,0 +1,147 @@
|
||||||
|
use iced::widget::container::{transparent, Catalog, Style, StyleFn};
|
||||||
|
use iced::{Background, Border, Color};
|
||||||
|
|
||||||
|
use super::Theme;
|
||||||
|
|
||||||
|
impl Catalog for Theme {
|
||||||
|
type Class<'a> = StyleFn<'a, Self>;
|
||||||
|
|
||||||
|
fn default<'a>() -> Self::Class<'a> {
|
||||||
|
Box::new(transparent)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(&self, class: &Self::Class<'_>) -> Style {
|
||||||
|
class(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn grey(theme: &Theme) -> Style {
|
||||||
|
let background = theme.colors().background.darker;
|
||||||
|
|
||||||
|
Style {
|
||||||
|
background: Some(Background::Color(background)),
|
||||||
|
text_color: Some(theme.colors().text.base),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn light_grey(theme: &Theme) -> Style {
|
||||||
|
let background = theme.colors().background.dark;
|
||||||
|
|
||||||
|
Style {
|
||||||
|
background: Some(Background::Color(background)),
|
||||||
|
text_color: Some(theme.colors().text.base),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn primary(theme: &Theme) -> Style {
|
||||||
|
Style {
|
||||||
|
background: Some(Background::Color(theme.colors().background.base)),
|
||||||
|
text_color: Some(theme.colors().text.base),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pane_body(theme: &Theme) -> Style {
|
||||||
|
Style {
|
||||||
|
background: Some(Background::Color(theme.colors().background.dark)),
|
||||||
|
border: Border {
|
||||||
|
radius: 4.0.into(),
|
||||||
|
width: 1.0,
|
||||||
|
color: Color::TRANSPARENT,
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pane_body_selected(theme: &Theme) -> Style {
|
||||||
|
let pane_body = pane_body(theme);
|
||||||
|
|
||||||
|
Style {
|
||||||
|
border: Border {
|
||||||
|
color: theme.colors().action.base,
|
||||||
|
..pane_body.border
|
||||||
|
},
|
||||||
|
..pane_body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn command(_theme: &Theme) -> Style {
|
||||||
|
Style {
|
||||||
|
background: None,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn command_selected(theme: &Theme) -> Style {
|
||||||
|
Style {
|
||||||
|
background: Some(Background::Color(theme.colors().background.darker)),
|
||||||
|
border: Border {
|
||||||
|
radius: 3.0.into(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn context(theme: &Theme) -> Style {
|
||||||
|
Style {
|
||||||
|
//TODO: Blur background when possible?
|
||||||
|
background: Some(Background::Color(theme.colors().background.base)),
|
||||||
|
border: Border {
|
||||||
|
radius: 4.0.into(),
|
||||||
|
width: 1.0,
|
||||||
|
color: theme.colors().background.darker,
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn highlight(theme: &Theme) -> Style {
|
||||||
|
Style {
|
||||||
|
background: Some(Background::Color(theme.colors().info.high_alpha)),
|
||||||
|
border: Border {
|
||||||
|
radius: 0.0.into(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn semi_transparent(theme: &Theme) -> Style {
|
||||||
|
Style {
|
||||||
|
background: Some(
|
||||||
|
Color {
|
||||||
|
a: 0.80,
|
||||||
|
..theme.colors().background.base
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn default_banner(theme: &Theme) -> Style {
|
||||||
|
Style {
|
||||||
|
background: Some(Background::Color(theme.colors().background.dark)),
|
||||||
|
border: Border {
|
||||||
|
radius: 4.0.into(),
|
||||||
|
width: 1.0,
|
||||||
|
color: theme.colors().background.lighter,
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn error_modal(theme: &Theme) -> Style {
|
||||||
|
Style {
|
||||||
|
background: Some(Background::Color(theme.colors().background.dark)),
|
||||||
|
border: Border {
|
||||||
|
radius: 4.0.into(),
|
||||||
|
width: 1.0,
|
||||||
|
color: theme.colors().error.base,
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
200
src/theme/data.rs
Normal file
200
src/theme/data.rs
Normal file
|
|
@ -0,0 +1,200 @@
|
||||||
|
use iced::Color;
|
||||||
|
use palette::rgb::Rgb;
|
||||||
|
use palette::{DarkenAssign, FromColor, LightenAssign, Mix, Okhsl, Srgb};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ColorTheme {
|
||||||
|
pub name: String,
|
||||||
|
pub colors: Colors,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ColorTheme {
|
||||||
|
pub fn new(name: String, palette: &Palette) -> Self {
|
||||||
|
ColorTheme {
|
||||||
|
name,
|
||||||
|
colors: Colors::new(palette),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ColorTheme {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
name: "Light".to_string(),
|
||||||
|
colors: Colors::new(&Palette::default()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Colors {
|
||||||
|
pub background: Subpalette,
|
||||||
|
pub text: Subpalette,
|
||||||
|
pub action: Subpalette,
|
||||||
|
pub accent: Subpalette,
|
||||||
|
pub alert: Subpalette,
|
||||||
|
pub error: Subpalette,
|
||||||
|
pub info: Subpalette,
|
||||||
|
pub success: Subpalette,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Colors {
|
||||||
|
pub fn new(palette: &Palette) -> Self {
|
||||||
|
Colors {
|
||||||
|
background: Subpalette::from_color(palette.background, palette),
|
||||||
|
text: Subpalette::from_color(palette.text, palette),
|
||||||
|
action: Subpalette::from_color(palette.action, palette),
|
||||||
|
accent: Subpalette::from_color(palette.accent, palette),
|
||||||
|
alert: Subpalette::from_color(palette.alert, palette),
|
||||||
|
error: Subpalette::from_color(palette.error, palette),
|
||||||
|
info: Subpalette::from_color(palette.info, palette),
|
||||||
|
success: Subpalette::from_color(palette.success, palette),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_dark_theme(&self) -> bool {
|
||||||
|
self.background.is_dark()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Subpalette {
|
||||||
|
pub base: Color,
|
||||||
|
pub light: Color,
|
||||||
|
pub lighter: Color,
|
||||||
|
pub lightest: Color,
|
||||||
|
pub dark: Color,
|
||||||
|
pub darker: Color,
|
||||||
|
pub darkest: Color,
|
||||||
|
pub low_alpha: Color,
|
||||||
|
pub med_alpha: Color,
|
||||||
|
pub high_alpha: Color,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Subpalette {
|
||||||
|
pub fn from_color(color: Color, palette: &Palette) -> Subpalette {
|
||||||
|
let is_dark = is_dark(palette.background);
|
||||||
|
|
||||||
|
Subpalette {
|
||||||
|
base: color,
|
||||||
|
light: lighten(color, 0.03),
|
||||||
|
lighter: lighten(color, 0.06),
|
||||||
|
lightest: lighten(color, 0.12),
|
||||||
|
dark: darken(color, 0.03),
|
||||||
|
darker: darken(color, 0.06),
|
||||||
|
darkest: darken(color, 0.12),
|
||||||
|
low_alpha: if is_dark {
|
||||||
|
alpha(color, 0.4)
|
||||||
|
} else {
|
||||||
|
alpha(color, 0.8)
|
||||||
|
},
|
||||||
|
med_alpha: if is_dark {
|
||||||
|
alpha(color, 0.2)
|
||||||
|
} else {
|
||||||
|
alpha(color, 0.4)
|
||||||
|
},
|
||||||
|
high_alpha: if is_dark {
|
||||||
|
alpha(color, 0.1)
|
||||||
|
} else {
|
||||||
|
alpha(color, 0.3)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_dark(&self) -> bool {
|
||||||
|
is_dark(self.base)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct Palette {
|
||||||
|
pub background: Color,
|
||||||
|
pub text: Color,
|
||||||
|
pub action: Color,
|
||||||
|
pub accent: Color,
|
||||||
|
pub alert: Color,
|
||||||
|
pub error: Color,
|
||||||
|
pub info: Color,
|
||||||
|
pub success: Color,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Palette {
|
||||||
|
fn default() -> Palette {
|
||||||
|
Palette {
|
||||||
|
background: hex_to_color("#2b292d").unwrap(),
|
||||||
|
text: hex_to_color("#fecdb2").unwrap(),
|
||||||
|
action: hex_to_color("#b1b695").unwrap(),
|
||||||
|
accent: hex_to_color("#d1d1e0").unwrap(),
|
||||||
|
alert: hex_to_color("#ffa07a").unwrap(),
|
||||||
|
error: hex_to_color("#e06b75").unwrap(),
|
||||||
|
info: hex_to_color("#f5d76e").unwrap(),
|
||||||
|
success: hex_to_color("#b1b695").unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hex_to_color(hex: &str) -> Option<Color> {
|
||||||
|
if hex.len() == 7 {
|
||||||
|
let hash = &hex[0..1];
|
||||||
|
let r = u8::from_str_radix(&hex[1..3], 16);
|
||||||
|
let g = u8::from_str_radix(&hex[3..5], 16);
|
||||||
|
let b = u8::from_str_radix(&hex[5..7], 16);
|
||||||
|
|
||||||
|
return match (hash, r, g, b) {
|
||||||
|
("#", Ok(r), Ok(g), Ok(b)) => Some(Color {
|
||||||
|
r: r as f32 / 255.0,
|
||||||
|
g: g as f32 / 255.0,
|
||||||
|
b: b as f32 / 255.0,
|
||||||
|
a: 1.0,
|
||||||
|
}),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
pub fn is_dark(color: Color) -> bool {
|
||||||
|
to_hsl(color).lightness < 0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_hsl(color: Color) -> Okhsl {
|
||||||
|
let mut hsl = Okhsl::from_color(Srgb::new(color.r, color.g, color.b));
|
||||||
|
if hsl.saturation.is_nan() {
|
||||||
|
hsl.saturation = Okhsl::max_saturation();
|
||||||
|
}
|
||||||
|
|
||||||
|
hsl
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_hsl(hsl: Okhsl) -> Color {
|
||||||
|
let color = Srgb::from_color(hsl);
|
||||||
|
Color::from_rgb(color.red, color.green, color.blue)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn alpha(color: Color, alpha: f32) -> Color {
|
||||||
|
Color { a: alpha, ..color }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mix(a: Color, b: Color, factor: f32) -> Color {
|
||||||
|
let a_hsl = to_hsl(a);
|
||||||
|
let b_hsl = to_hsl(b);
|
||||||
|
|
||||||
|
let mixed = a_hsl.mix(b_hsl, factor);
|
||||||
|
from_hsl(mixed)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lighten(color: Color, amount: f32) -> Color {
|
||||||
|
let mut hsl = to_hsl(color);
|
||||||
|
|
||||||
|
hsl.lighten_fixed_assign(amount);
|
||||||
|
|
||||||
|
from_hsl(hsl)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn darken(color: Color, amount: f32) -> Color {
|
||||||
|
let mut hsl = to_hsl(color);
|
||||||
|
|
||||||
|
hsl.darken_fixed_assign(amount);
|
||||||
|
|
||||||
|
from_hsl(hsl)
|
||||||
|
}
|
||||||
33
src/theme/menu.rs
Normal file
33
src/theme/menu.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
pub use iced::widget::overlay::menu::Style;
|
||||||
|
use iced::{
|
||||||
|
widget::overlay::menu::{Catalog, StyleFn},
|
||||||
|
Background, Border,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::Theme;
|
||||||
|
|
||||||
|
impl Catalog for Theme {
|
||||||
|
type Class<'a> = StyleFn<'a, Self>;
|
||||||
|
|
||||||
|
fn default<'a>() -> StyleFn<'a, Self> {
|
||||||
|
Box::new(primary)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(&self, class: &StyleFn<'_, Self>) -> Style {
|
||||||
|
class(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn primary(theme: &Theme) -> Style {
|
||||||
|
Style {
|
||||||
|
text_color: theme.colors().text.base,
|
||||||
|
background: Background::Color(theme.colors().background.darker),
|
||||||
|
border: Border {
|
||||||
|
width: 1.0,
|
||||||
|
radius: 4.0.into(),
|
||||||
|
color: theme.colors().background.darker,
|
||||||
|
},
|
||||||
|
selected_text_color: theme.colors().text.low_alpha,
|
||||||
|
selected_background: Background::Color(theme.colors().background.dark),
|
||||||
|
}
|
||||||
|
}
|
||||||
100
src/theme/mod.rs
Normal file
100
src/theme/mod.rs
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
pub mod button;
|
||||||
|
pub mod checkbox;
|
||||||
|
pub mod container;
|
||||||
|
pub mod data;
|
||||||
|
pub mod menu;
|
||||||
|
pub mod pick_list;
|
||||||
|
pub mod scrollable;
|
||||||
|
pub mod svg;
|
||||||
|
pub mod text;
|
||||||
|
pub mod text_editor;
|
||||||
|
pub mod text_input;
|
||||||
|
pub mod toggler;
|
||||||
|
use data::ColorTheme;
|
||||||
|
use data::Colors;
|
||||||
|
use iced::color;
|
||||||
|
// TODO: If we use non-standard font sizes, we should consider
|
||||||
|
// Config.font.size since it's user configurable
|
||||||
|
pub const TEXT_SIZE: f32 = 13.0;
|
||||||
|
pub const ICON_SIZE: f32 = 12.0;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Theme {
|
||||||
|
Selected(ColorTheme),
|
||||||
|
Preview {
|
||||||
|
selected: ColorTheme,
|
||||||
|
preview: ColorTheme,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Theme {
|
||||||
|
pub fn light() -> Self {
|
||||||
|
let palette = data::Palette {
|
||||||
|
accent: color!(0x1c71d8),
|
||||||
|
success: color!(0x1b8553),
|
||||||
|
error: color!(0xc01c28),
|
||||||
|
background: color!(0xfafafa),
|
||||||
|
alert: color!(0x9c6e03),
|
||||||
|
text: color!(0x000000),
|
||||||
|
//
|
||||||
|
action: color!(0x62a0ea),
|
||||||
|
info: color!(0x1b8553),
|
||||||
|
};
|
||||||
|
Theme::Selected(ColorTheme {
|
||||||
|
name: String::from("light"),
|
||||||
|
colors: Colors::new(&palette),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pub fn dark() -> Self {
|
||||||
|
let palette = data::Palette {
|
||||||
|
accent: color!(0x78aeed),
|
||||||
|
success: color!(0x8ff0a4),
|
||||||
|
error: color!(0xff7b63),
|
||||||
|
background: color!(0x242424),
|
||||||
|
alert: color!(0xf8e45c),
|
||||||
|
text: color!(0xffffff),
|
||||||
|
//
|
||||||
|
action: color!(0x99c1f1),
|
||||||
|
info: color!(0x1b8553),
|
||||||
|
};
|
||||||
|
Theme::Selected(ColorTheme {
|
||||||
|
name: String::from("light"),
|
||||||
|
colors: Colors::new(&palette),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pub fn preview(&self, theme: ColorTheme) -> Self {
|
||||||
|
match self {
|
||||||
|
Theme::Selected(selected) | Theme::Preview { selected, .. } => Self::Preview {
|
||||||
|
selected: selected.clone(),
|
||||||
|
preview: theme,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn selected(&self) -> Self {
|
||||||
|
match self {
|
||||||
|
Theme::Selected(selected) | Theme::Preview { selected, .. } => {
|
||||||
|
Self::Selected(selected.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn colors(&self) -> &Colors {
|
||||||
|
match self {
|
||||||
|
Theme::Selected(selected) => &selected.colors,
|
||||||
|
Theme::Preview { preview, .. } => &preview.colors,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ColorTheme> for Theme {
|
||||||
|
fn from(theme: ColorTheme) -> Self {
|
||||||
|
Theme::Selected(theme)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Theme {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::from(ColorTheme::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/theme/pick_list.rs
Normal file
26
src/theme/pick_list.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
use iced::widget::pick_list::{Catalog, Status, Style, StyleFn};
|
||||||
|
use iced::{Background, Border};
|
||||||
|
|
||||||
|
use super::Theme;
|
||||||
|
|
||||||
|
impl Catalog for Theme {
|
||||||
|
type Class<'a> = StyleFn<'a, Self>;
|
||||||
|
|
||||||
|
fn default<'a>() -> StyleFn<'a, Self> {
|
||||||
|
Box::new(primary)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(&self, class: &StyleFn<'_, Self>, status: Status) -> Style {
|
||||||
|
class(self, status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn primary(theme: &Theme, _status: Status) -> Style {
|
||||||
|
Style {
|
||||||
|
text_color: theme.colors().text.base,
|
||||||
|
placeholder_color: theme.colors().background.dark,
|
||||||
|
handle_color: theme.colors().background.darkest,
|
||||||
|
background: Background::Color(theme.colors().background.darker),
|
||||||
|
border: Border::default().rounded(5),
|
||||||
|
}
|
||||||
|
}
|
||||||
87
src/theme/scrollable.rs
Normal file
87
src/theme/scrollable.rs
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
use iced::{
|
||||||
|
widget::{
|
||||||
|
container,
|
||||||
|
scrollable::{Catalog, Rail, Scrollbar, Scroller, Status, Style, StyleFn},
|
||||||
|
},
|
||||||
|
Background, Border, Color, Shadow,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::Theme;
|
||||||
|
|
||||||
|
impl Catalog for Theme {
|
||||||
|
type Class<'a> = StyleFn<'a, Self>;
|
||||||
|
|
||||||
|
fn default<'a>() -> Self::Class<'a> {
|
||||||
|
Box::new(primary)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(&self, class: &Self::Class<'_>, status: Status) -> Style {
|
||||||
|
class(self, status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn primary(theme: &Theme, status: Status) -> Style {
|
||||||
|
let rail = Rail {
|
||||||
|
background: None,
|
||||||
|
border: Border::default(),
|
||||||
|
scroller: Scroller {
|
||||||
|
color: theme.colors().background.darker,
|
||||||
|
border: Border {
|
||||||
|
radius: 8.0.into(),
|
||||||
|
width: 0.0,
|
||||||
|
color: Color::TRANSPARENT,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
match status {
|
||||||
|
Status::Active { .. } | Status::Hovered { .. } | Status::Dragged { .. } => Style {
|
||||||
|
container: container::Style {
|
||||||
|
text_color: None,
|
||||||
|
background: None,
|
||||||
|
border: Border {
|
||||||
|
radius: 8.0.into(),
|
||||||
|
width: 1.0,
|
||||||
|
color: Color::TRANSPARENT,
|
||||||
|
},
|
||||||
|
shadow: Shadow::default(),
|
||||||
|
},
|
||||||
|
vertical_rail: rail,
|
||||||
|
horizontal_rail: rail,
|
||||||
|
gap: None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hidden(_theme: &Theme, status: Status) -> Style {
|
||||||
|
let rail = Rail {
|
||||||
|
background: None,
|
||||||
|
border: Border::default(),
|
||||||
|
scroller: Scroller {
|
||||||
|
color: Color::TRANSPARENT,
|
||||||
|
border: Border {
|
||||||
|
radius: 0.0.into(),
|
||||||
|
width: 0.0,
|
||||||
|
color: Color::TRANSPARENT,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
match status {
|
||||||
|
Status::Active { .. } | Status::Hovered { .. } | Status::Dragged { .. } => Style {
|
||||||
|
container: container::Style {
|
||||||
|
text_color: None,
|
||||||
|
background: Some(Background::Color(Color::TRANSPARENT)),
|
||||||
|
border: Border {
|
||||||
|
radius: 8.0.into(),
|
||||||
|
width: 1.0,
|
||||||
|
color: Color::TRANSPARENT,
|
||||||
|
},
|
||||||
|
shadow: Shadow::default(),
|
||||||
|
},
|
||||||
|
vertical_rail: rail,
|
||||||
|
horizontal_rail: rail,
|
||||||
|
gap: None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/theme/svg.rs
Normal file
31
src/theme/svg.rs
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
use super::Theme;
|
||||||
|
use iced::widget::svg::{Catalog, Status, Style, StyleFn};
|
||||||
|
|
||||||
|
impl Catalog for Theme {
|
||||||
|
type Class<'a> = StyleFn<'a, Self>;
|
||||||
|
|
||||||
|
fn default<'a>() -> Self::Class<'a> {
|
||||||
|
Box::new(primary)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(&self, class: &Self::Class<'_>, status: Status) -> Style {
|
||||||
|
class(self, status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn primary(_theme: &Theme, _status: Status) -> Style {
|
||||||
|
Style::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn error(theme: &Theme, _status: Status) -> Style {
|
||||||
|
Style {
|
||||||
|
color: Some(theme.colors().error.base),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn success(theme: &Theme, _status: Status) -> Style {
|
||||||
|
Style {
|
||||||
|
color: Some(theme.colors().success.base),
|
||||||
|
}
|
||||||
|
}
|
||||||
67
src/theme/text.rs
Normal file
67
src/theme/text.rs
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
use iced::widget::text::{Catalog, Style, StyleFn};
|
||||||
|
|
||||||
|
use super::Theme;
|
||||||
|
|
||||||
|
impl Catalog for Theme {
|
||||||
|
type Class<'a> = StyleFn<'a, Self>;
|
||||||
|
|
||||||
|
fn default<'a>() -> Self::Class<'a> {
|
||||||
|
Box::new(none)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(&self, class: &Self::Class<'_>) -> Style {
|
||||||
|
class(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn none(_theme: &Theme) -> Style {
|
||||||
|
Style { color: None }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn primary(theme: &Theme) -> Style {
|
||||||
|
Style {
|
||||||
|
color: Some(theme.colors().text.base),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn accent(theme: &Theme) -> Style {
|
||||||
|
Style {
|
||||||
|
color: Some(theme.colors().accent.base),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn alert(theme: &Theme) -> Style {
|
||||||
|
Style {
|
||||||
|
color: Some(theme.colors().alert.base),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn info(theme: &Theme) -> Style {
|
||||||
|
Style {
|
||||||
|
color: Some(theme.colors().info.base),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn error(theme: &Theme) -> Style {
|
||||||
|
Style {
|
||||||
|
color: Some(theme.colors().error.base),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn success(theme: &Theme) -> Style {
|
||||||
|
Style {
|
||||||
|
color: Some(theme.colors().success.base),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn transparent(theme: &Theme) -> Style {
|
||||||
|
Style {
|
||||||
|
color: Some(theme.colors().text.low_alpha),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn transparent_accent(theme: &Theme) -> Style {
|
||||||
|
Style {
|
||||||
|
color: Some(theme.colors().accent.low_alpha),
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/theme/text_editor.rs
Normal file
29
src/theme/text_editor.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
use iced::{
|
||||||
|
widget::text_editor::{Catalog, Status, Style, StyleFn},
|
||||||
|
Border,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::Theme;
|
||||||
|
|
||||||
|
impl Catalog for Theme {
|
||||||
|
type Class<'a> = StyleFn<'a, Self>;
|
||||||
|
|
||||||
|
fn default<'a>() -> Self::Class<'a> {
|
||||||
|
Box::new(none)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(&self, class: &Self::Class<'_>, status: Status) -> Style {
|
||||||
|
class(self, status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn none(_theme: &Theme, _state: Status) -> Style {
|
||||||
|
Style {
|
||||||
|
value: _theme.colors().text.base,
|
||||||
|
selection: _theme.colors().text.light,
|
||||||
|
icon: _theme.colors().text.base,
|
||||||
|
placeholder: _theme.colors().text.lighter,
|
||||||
|
border: Border::default().rounded(5.),
|
||||||
|
background: iced::Background::from(_theme.colors().background.darker),
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/theme/text_input.rs
Normal file
29
src/theme/text_input.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
use iced::{
|
||||||
|
widget::text_input::{Catalog, Status, Style, StyleFn},
|
||||||
|
Border,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::Theme;
|
||||||
|
|
||||||
|
impl Catalog for Theme {
|
||||||
|
type Class<'a> = StyleFn<'a, Self>;
|
||||||
|
|
||||||
|
fn default<'a>() -> Self::Class<'a> {
|
||||||
|
Box::new(none)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(&self, class: &Self::Class<'_>, status: Status) -> Style {
|
||||||
|
class(self, status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn none(_theme: &Theme, _state: Status) -> Style {
|
||||||
|
Style {
|
||||||
|
value: _theme.colors().text.base,
|
||||||
|
selection: _theme.colors().text.light,
|
||||||
|
icon: _theme.colors().text.base,
|
||||||
|
placeholder: _theme.colors().text.lighter,
|
||||||
|
border: Border::default().rounded(10.),
|
||||||
|
background: iced::Background::from(_theme.colors().background.base),
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/theme/toggler.rs
Normal file
26
src/theme/toggler.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
use iced::widget::toggler::{Catalog, Status, Style, StyleFn};
|
||||||
|
|
||||||
|
use super::Theme;
|
||||||
|
|
||||||
|
impl Catalog for Theme {
|
||||||
|
type Class<'a> = StyleFn<'a, Self>;
|
||||||
|
|
||||||
|
fn default<'a>() -> Self::Class<'a> {
|
||||||
|
Box::new(primary)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn style(&self, class: &Self::Class<'_>, status: iced::widget::toggler::Status) -> Style {
|
||||||
|
class(self, status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn primary(_theme: &Theme, _status: Status) -> Style {
|
||||||
|
Style {
|
||||||
|
background: _theme.colors().background.darkest,
|
||||||
|
background_border_width: 10.0,
|
||||||
|
background_border_color: _theme.colors().background.darkest,
|
||||||
|
foreground: _theme.colors().text.lightest,
|
||||||
|
foreground_border_width: 10.0,
|
||||||
|
foreground_border_color: _theme.colors().text.high_alpha,
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue