You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
2.5 KiB

use image::Rgb;
use crate::palette::Palette;
use iced::Background;
use iced::Color;
use iced::widget::container;
use iced::widget::text_input;
#[derive(Copy, Clone, Debug)]
pub struct Theme {
pub base_color: Color,
pub text_color: Color,
subtype: Subtype,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum Subtype {
Base,
ActiveLyric,
}
use Subtype::*;
impl Theme {
pub fn from_palette(palette: &Palette) -> Self {
let base_color = img_color_to_iced(palette.dominant_color());
let luma = relative_lum(base_color);
let text_color = if luma > 0.2 {
Color {
a: 0.8,
..Color::BLACK
}
} else {
Color::WHITE
};
Self {
subtype: Base,
base_color, text_color,
}
}
pub const fn reduced_text_color(&self) -> Color {
Color {
a: 0.7,
..self.text_color
}
}
pub const fn active_lyric(&self, active: bool) -> Self {
if active {
self.set_subtype(ActiveLyric)
} else {
*self
}
}
const fn set_subtype(&self, subtype: Subtype) -> Self {
Self {
subtype,
..*self
}
}
}
impl Default for Theme {
fn default() -> Self {
Self {
base_color: Color {r: 236. / 255., g: 63. / 255., b: 53. / 255., a: 1.},
text_color: Color {r: 1., g: 1., b: 1., a: 1.},
subtype: Base,
}
}
}
impl container::StyleSheet for Theme {
fn style(&self) -> container::Style {
container::Style {
text_color: Some(self.text_color),
background: Some(Background::Color(self.base_color)),
..Default::default()
}
}
}
impl text_input::StyleSheet for Theme {
fn active(&self) -> text_input::Style {
text_input::Style {
background: Background::Color(self.base_color),
border_radius: 0.,
border_width: 0.,
..Default::default()
}
}
fn focused(&self) -> text_input::Style {
self.active()
}
fn placeholder_color(&self) -> Color {
Color {
a: 0.3,
..self.text_color
}
}
fn value_color(&self) -> Color {
if self.subtype == ActiveLyric {
self.text_color
} else {
self.reduced_text_color()
}
}
fn selection_color(&self) -> Color {
self.text_color
}
}
fn img_color_to_iced(color: Rgb<u8>) -> Color {
Color {
r: color[0] as f32 / 255.,
g: color[1] as f32 / 255.,
b: color[2] as f32 / 255.,
a: 1.
}
}
pub fn relative_lum(color: Color) -> f32 {
let mut t = [color.r, color.g, color.b]
.into_iter()
.map(|val| {
if val < 0.03928 {
val / 12.92
} else {
((val+0.055)/1.055).powf(2.4)
}
});
0.2126 * t.next().unwrap() + 0.7152 * t.next().unwrap() + 0.0722 * t.next().unwrap()
}