use serde::{Deserialize, Deserializer, de};
#[derive(Deserialize, Clone, Debug, Default)]
#[cfg_attr(test, derive(serde::Serialize))]
pub struct DecorationsOptions {
pub active: Option<GeneralDecorationsOptions>,
pub inactive: Option<GeneralDecorationsOptions>,
pub workspace_menu_status: Option<bool>,
pub menu: Option<MenubarOptions>,
pub workspace_popup_status: Option<bool>,
}
#[derive(Deserialize, Clone, Debug, Default)]
#[cfg_attr(test, derive(serde::Serialize))]
pub struct GeneralDecorationsOptions {
pub border: Option<GeneralBorderOptions>,
pub dim: Option<GeneralDimOptions>,
}
#[derive(Deserialize, Clone, Debug, Default)]
#[cfg_attr(test, derive(serde::Serialize))]
pub struct GeneralBorderOptions {
pub enabled: Option<bool>,
pub color: Option<String>,
pub opacity: Option<f64>,
pub width: Option<f64>,
#[serde(default, deserialize_with = "deserialize_border_radius_option")]
pub radius: Option<BorderRadiusOption>,
}
#[derive(Deserialize, Clone, Debug, Default)]
#[cfg_attr(test, derive(serde::Serialize))]
pub struct GeneralDimOptions {
pub opacity: Option<f32>,
pub opacity_night: Option<f32>,
pub color: Option<String>,
}
#[derive(Deserialize, Debug, Clone, Default)]
#[cfg_attr(test, derive(serde::Serialize))]
pub struct MenubarOptions {
pub orientation: Option<MenubarOrientation>,
pub colors: Option<Vec<String>>,
pub angle: Option<f64>,
pub descriptor: Option<MenubarDescriptorOptions>,
pub indicator: Option<MenubarIndicatorOptions>,
}
#[derive(Deserialize, Debug, Clone, Default)]
#[cfg_attr(test, derive(serde::Serialize))]
pub struct MenubarDescriptorOptions {
pub style: Option<DescriptorStyle>,
pub text: Option<String>,
pub symbol: Option<String>,
}
#[derive(Deserialize, Debug, Clone, Copy, Default)]
#[cfg_attr(test, derive(serde::Serialize))]
pub struct MenubarIndicatorOptions {
pub style: Option<IndicatorStyle>,
pub format: Option<IndicatorFormat>,
pub font_size: Option<f64>,
pub active_character: Option<char>,
pub inactive_character: Option<char>,
}
#[derive(Deserialize, Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize))]
#[serde(rename_all = "lowercase")]
pub enum IndicatorFormat {
Default,
Roman,
Unicode,
Marked,
}
#[derive(Deserialize, Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize))]
#[serde(rename_all = "lowercase")]
pub enum MenubarOrientation {
Default,
Flipped,
}
#[derive(Deserialize, Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize))]
#[serde(rename_all = "lowercase")]
pub enum IndicatorStyle {
Mono,
Multi,
Paged,
}
#[derive(Deserialize, Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize))]
#[serde(rename_all = "lowercase")]
pub enum DescriptorStyle {
Symbol,
Text,
Both,
Hidden,
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(test, derive(serde::Serialize))]
pub enum BorderRadiusOption {
Auto,
Value(f64),
}
#[derive(Deserialize)]
#[serde(untagged)]
enum BorderRadiusValue {
Number(f64),
Text(String),
}
pub fn deserialize_border_radius_option<'de, D>(
deserializer: D,
) -> std::result::Result<Option<BorderRadiusOption>, D::Error>
where
D: Deserializer<'de>,
{
let input = Option::<BorderRadiusValue>::deserialize(deserializer)?;
input
.map(|value| match value {
BorderRadiusValue::Number(radius) => Ok(BorderRadiusOption::Value(radius)),
BorderRadiusValue::Text(value) if value.eq_ignore_ascii_case("auto") => {
Ok(BorderRadiusOption::Auto)
}
BorderRadiusValue::Text(value) => Err(de::Error::custom(format!(
"invalid border_radius value: {value}. Expected a number or \"auto\"",
))),
})
.transpose()
}