pub(crate) mod serial;
use crate::{ Border, Color, Theme };
use iced_native::{
widget::{
pick_list::{
Appearance, StyleSheet,
},
},
};
use serial::{ MenuComponent, StateComponent };
#[derive(Clone, Copy, Debug)]
pub struct Picklist {
pub state: [State; 2],
pub menu: Menu,
}
impl Picklist {
pub(crate) fn create(serial: &serial::Picklist, theme: &Theme) -> Result<Self, ()> {
let active = Self::state( &serial.active , theme, 0 )?;
let hovered = Self::state( &serial.hovered , theme, 1 )?;
let menu = Self::menu( &serial.menu, theme )?;
let default = match (active, hovered) {
(Some(d), _) => d,
(_, Some(d)) => d,
_ => return Err(()),
};
Ok(Picklist {
state: [
if active.is_some() { active.unwrap() } else { default },
if hovered.is_some() { hovered.unwrap() } else { default },
],
menu,
})
}
fn state(serial: &serial::StateComponent, theme: &Theme, index: usize) -> Result<Option<State>, ()> {
match serial {
StateComponent::Defined( state ) => Ok( Some( State::from(&state, &theme)? ) ),
StateComponent::Inherited( name ) => match theme.picklist.get( name ) {
Some( picklist ) => Ok( Some( picklist.state[index].clone() ) ),
_ => Err(()),
},
StateComponent::None => Ok( None ),
}
}
fn menu(serial: &serial::MenuComponent, theme: &Theme) -> Result<Menu, ()> {
match serial {
MenuComponent::Defined( state ) => Ok( Menu::from(&state, &theme)? ),
MenuComponent::Inherited( name ) => match theme.picklist.get( name ) {
Some( picklist ) => Ok( picklist.menu.clone() ),
_ => Err(()),
},
}
}
}
impl StyleSheet for Picklist {
type Style = iced::Theme;
fn active(&self, _: &Self::Style) -> Appearance {
Appearance {
text_color: self.state[0].text.into(),
placeholder_color: self.state[0].placeholder.into(),
background: self.state[0].background.into(),
border_radius: self.state[0].border.radius,
border_width: self.state[0].border.width,
border_color: self.state[0].border.color.into(),
icon_size: self.state[0].iconsize,
}
}
fn hovered(&self, _: &Self::Style) -> Appearance {
Appearance {
text_color: self.state[1].text.into(),
placeholder_color: self.state[1].placeholder.into(),
background: self.state[1].background.into(),
border_radius: self.state[1].border.radius,
border_width: self.state[1].border.width,
border_color: self.state[1].border.color.into(),
icon_size: self.state[1].iconsize,
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct State {
pub background: Color,
pub text: Color,
pub placeholder: Color,
pub border: Border,
pub iconsize: f32,
}
impl State {
fn from(serial: &serial::State, theme: &Theme) -> Result<Self, ()> {
let background = match theme.color.get(&serial.background) {
Some(color) => *color,
_ => return Err(()),
};
let text = match theme.color.get(&serial.text) {
Some(color) => *color,
_ => return Err(()),
};
let placeholder = match theme.color.get(&serial.placeholder) {
Some(color) => *color,
_ => return Err(()),
};
let border = match theme.border.get(&serial.border) {
Some(border) => *border,
_ => return Err(()),
};
Ok( State { background, text, placeholder, border, iconsize: serial.iconsize } )
}
}
#[derive(Clone, Copy, Debug)]
pub struct Menu {
pub background: [Color; 2],
pub text: [Color; 2],
pub border: Border,
}
impl Menu {
fn from(serial: &serial::Menu, theme: &Theme) -> Result<Self, ()> {
let background = match theme.color.get(&serial.background) {
Some(color) => *color,
_ => return Err(()),
};
let sbackground = match theme.color.get(&serial.sbackground) {
Some(color) => *color,
_ => return Err(()),
};
let text = match theme.color.get(&serial.text) {
Some(color) => *color,
_ => return Err(()),
};
let stext = match theme.color.get(&serial.stext) {
Some(color) => *color,
_ => return Err(()),
};
let border = match theme.border.get(&serial.border) {
Some(border) => *border,
_ => return Err(()),
};
Ok( Menu { background: [background, sbackground], text: [text, stext], border } )
}
}