Files
wldash/src/config.rs
T

361 lines
11 KiB
Rust
Raw Normal View History

2023-02-11 18:24:34 +01:00
use serde::{self, Deserialize, Serialize};
use std::collections::HashMap;
use std::default::Default;
use std::sync::{Arc, Mutex};
use crate::{
event::Events,
2023-02-13 18:49:44 +01:00
fonts::{find_font, FontMap},
2023-02-11 18:24:34 +01:00
widgets::{
Backlight, Battery, Calendar, Clock, Date, HorizontalLayout, IndexedLayout, Interface,
2023-02-14 10:23:12 +01:00
InvertedHorizontalLayout, InvertedVerticalLayout, Layout, Line, Margin, PulseAudio,
VerticalLayout, Widget as RealWidget,
2023-02-11 18:24:34 +01:00
},
};
#[derive(Serialize, Deserialize, Clone, Debug)]
2023-02-12 17:02:44 +01:00
#[serde(rename_all = "snake_case")]
pub enum OperationMode {
LayerSurface((u32, u32)),
XdgToplevel,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "snake_case")]
2023-02-11 18:24:34 +01:00
pub enum Widget {
Margin {
margins: (u32, u32, u32, u32),
widget: Box<Widget>,
},
HorizontalLayout(Vec<Widget>),
InvertedHorizontalLayout(Vec<Widget>),
VerticalLayout(Vec<Widget>),
2023-02-14 10:23:12 +01:00
InvertedVerticalLayout(Vec<Widget>),
2023-02-14 00:04:19 +01:00
HorizontalLine(u32),
VerticalLine(u32),
2023-02-11 18:24:34 +01:00
Clock {
font: Option<String>,
font_size: f32,
},
Date {
font: Option<String>,
font_size: f32,
},
Calendar {
font_primary: Option<String>,
font_secondary: Option<String>,
font_size: f32,
sections_x: i32,
sections_y: i32,
},
Launcher {
font: Option<String>,
font_size: f32,
},
Battery {
font: Option<String>,
font_size: f32,
},
Backlight {
device: Option<String>,
font: Option<String>,
font_size: f32,
},
PulseAudio {
font: Option<String>,
font_size: f32,
},
}
2023-02-12 17:02:44 +01:00
impl Default for OperationMode {
fn default() -> OperationMode {
OperationMode::LayerSurface((1024, 768))
}
}
2023-02-11 18:24:34 +01:00
#[derive(Serialize, Deserialize, Clone, Debug)]
2023-02-12 17:02:44 +01:00
#[serde(rename_all = "snake_case")]
2023-02-11 18:24:34 +01:00
pub struct Config {
pub font_paths: Option<HashMap<String, String>>,
2023-02-12 17:02:44 +01:00
pub widget: Widget,
pub mode: OperationMode,
2023-02-11 18:24:34 +01:00
}
2023-02-12 17:02:44 +01:00
impl Config {
pub fn generate_v1() -> Config {
let has_battery = Battery::detect();
let has_backlight = Backlight::detect("intel_backlight");
let sans = find_font("sans");
let monospace = find_font("monospace");
2023-02-11 18:24:34 +01:00
2023-02-12 17:02:44 +01:00
let mut bars = Vec::new();
if has_battery {
2023-02-13 18:49:44 +01:00
bars.push(Widget::Margin {
margins: (0, 0, 0, 8),
widget: Box::new(Widget::Battery {
font: None,
font_size: 24.,
}),
});
2023-02-12 17:02:44 +01:00
}
if has_backlight {
2023-02-13 18:49:44 +01:00
bars.push(Widget::Margin {
margins: (0, 0, 0, 8),
widget: Box::new(Widget::Backlight {
device: Some("intel_backlight".to_string()),
font: None,
font_size: 24.,
}),
});
2023-02-12 17:02:44 +01:00
}
2023-02-13 18:49:44 +01:00
bars.push(Widget::Margin {
margins: (0, 0, 0, 8),
widget: Box::new(Widget::PulseAudio {
font: None,
font_size: 24.,
}),
});
2023-02-11 18:24:34 +01:00
2023-02-12 17:02:44 +01:00
let widget = Widget::Margin {
2023-02-11 18:24:34 +01:00
margins: (20, 20, 20, 20),
widget: Box::new(Widget::VerticalLayout(vec![
Widget::HorizontalLayout(vec![
Widget::VerticalLayout(vec![
Widget::Date {
font: None,
font_size: 48.,
},
Widget::Clock {
font: None,
font_size: 256.,
},
]),
Widget::Margin {
margins: (88, 0, 0, 0),
2023-02-12 17:02:44 +01:00
widget: Box::new(Widget::VerticalLayout(bars)),
2023-02-11 18:24:34 +01:00
},
]),
Widget::Calendar {
font_primary: None,
font_secondary: None,
font_size: 36.,
sections_x: 3,
sections_y: 1,
},
Widget::Launcher {
font: None,
font_size: 32.,
},
])),
2023-02-12 17:02:44 +01:00
};
let map = HashMap::from([
("sans".to_string(), sans),
("monospace".to_string(), monospace),
]);
2023-02-13 18:49:44 +01:00
Config {
2023-02-12 17:02:44 +01:00
font_paths: Some(map),
widget: widget,
mode: OperationMode::LayerSurface((1024, 768)),
2023-02-11 18:24:34 +01:00
}
}
2023-02-12 17:02:44 +01:00
pub fn generate_v2(clay: bool) -> Config {
let has_battery = Battery::detect();
let has_backlight = Backlight::detect("intel_backlight");
let sans = find_font("sans");
let monospace = find_font("monospace");
let mut bars = Vec::new();
if has_battery {
2023-02-13 18:49:44 +01:00
bars.push(Widget::Margin {
margins: (16, 8, 8, 0),
widget: Box::new(Widget::Battery {
font: None,
font_size: 24.,
}),
});
2023-02-12 17:02:44 +01:00
}
if has_backlight {
2023-02-13 18:49:44 +01:00
bars.push(Widget::Margin {
margins: (16, 8, 8, 0),
widget: Box::new(Widget::Backlight {
device: Some("intel_backlight".to_string()),
font: None,
font_size: 24.,
}),
});
2023-02-12 17:02:44 +01:00
}
2023-02-13 18:49:44 +01:00
bars.push(Widget::Margin {
margins: (16, 8, 8, 0),
widget: Box::new(Widget::PulseAudio {
font: None,
font_size: 24.,
}),
});
2023-02-12 17:02:44 +01:00
let widget = Widget::VerticalLayout(vec![
Widget::HorizontalLayout(vec![
Widget::Clock {
font: None,
font_size: 128.,
},
Widget::Margin {
margins: (16, 16, 0, 0),
widget: Box::new(Widget::Date {
font: None,
font_size: 48.,
}),
},
Widget::VerticalLayout(bars),
]),
2023-02-14 00:04:19 +01:00
Widget::HorizontalLine(1),
2023-02-12 17:02:44 +01:00
Widget::InvertedHorizontalLayout(vec![
2023-02-14 00:04:19 +01:00
Widget::Margin {
margins: (16, 8, 16, 0),
widget: Box::new(Widget::Calendar {
font_primary: None,
font_secondary: None,
font_size: 24.,
sections_x: 1,
sections_y: if clay { -1 } else { 3 },
}),
2023-02-12 17:02:44 +01:00
},
2023-02-14 00:04:19 +01:00
Widget::VerticalLine(1),
2023-02-12 17:02:44 +01:00
Widget::Launcher {
font: None,
font_size: 32.,
},
]),
]);
let map = HashMap::from([
("sans".to_string(), sans),
("monospace".to_string(), monospace),
]);
2023-02-13 18:49:44 +01:00
Config {
2023-02-12 17:02:44 +01:00
font_paths: Some(map),
widget: widget,
2023-02-13 18:49:44 +01:00
mode: if clay {
OperationMode::XdgToplevel
} else {
2023-02-14 00:04:19 +01:00
OperationMode::LayerSurface((1024, 1))
2023-02-13 18:49:44 +01:00
},
2023-02-12 17:02:44 +01:00
}
}
}
fn leak_or_default(v: Option<String>, d: &'static str) -> &'static str {
match v {
Some(v) => Box::leak(v.into_boxed_str()),
None => d,
}
}
impl Widget {
2023-02-11 18:24:34 +01:00
pub fn construct_widgets(
self,
v: &mut Vec<Box<dyn RealWidget>>,
mut fm: &mut FontMap,
events: &Arc<Mutex<Events>>,
) {
match self {
Widget::Margin { widget, .. } => widget.construct_widgets(v, fm, events),
Widget::HorizontalLayout(widgets) => widgets
.into_iter()
.for_each(|w| w.construct_widgets(v, fm, events)),
Widget::InvertedHorizontalLayout(widgets) => widgets
.into_iter()
.for_each(|w| w.construct_widgets(v, fm, events)),
Widget::VerticalLayout(widgets) => widgets
.into_iter()
.for_each(|w| w.construct_widgets(v, fm, events)),
2023-02-14 10:23:12 +01:00
Widget::InvertedVerticalLayout(widgets) => widgets
.into_iter()
.for_each(|w| w.construct_widgets(v, fm, events)),
2023-02-14 00:04:19 +01:00
Widget::HorizontalLine(width) => v.push(Box::new(Line::new(width, false))),
Widget::VerticalLine(width) => v.push(Box::new(Line::new(width, true))),
2023-02-11 18:24:34 +01:00
Widget::Clock { font, font_size } => v.push(Box::new(Clock::new(
&mut fm,
leak_or_default(font, "sans"),
font_size,
))),
Widget::Date { font, font_size } => v.push(Box::new(Date::new(
&mut fm,
leak_or_default(font, "sans"),
font_size,
))),
Widget::Calendar {
font_primary,
font_secondary,
font_size,
sections_x,
sections_y,
} => v.push(Box::new(Calendar::new(
&mut fm,
leak_or_default(font_primary, "monospace"),
leak_or_default(font_secondary, "sans"),
font_size,
sections_x,
sections_y,
))),
Widget::Launcher { font, font_size } => v.push(Box::new(Interface::new(
events.clone(),
&mut fm,
leak_or_default(font, "sans"),
font_size,
))),
Widget::Battery { font, font_size } => v.push(Box::new(Battery::new(
events.clone(),
&mut fm,
leak_or_default(font, "sans"),
font_size,
))),
Widget::Backlight {
device,
font,
font_size,
} => v.push(Box::new(Backlight::new(
leak_or_default(device, "intel_backlight"),
&mut fm,
leak_or_default(font, "sans"),
font_size,
))),
Widget::PulseAudio { font, font_size } => v.push(Box::new(PulseAudio::new(
events.clone(),
&mut fm,
Box::leak(font.unwrap_or_else(|| "sans".to_string()).into_boxed_str()),
font_size,
))),
}
}
pub fn construct_layout(&self, idx: &mut usize) -> Box<dyn Layout> {
match self {
Widget::Margin { margins, widget } => {
Margin::new(widget.construct_layout(idx), *margins)
}
Widget::HorizontalLayout(widgets) => {
HorizontalLayout::new(widgets.iter().map(|w| w.construct_layout(idx)).collect())
}
Widget::InvertedHorizontalLayout(widgets) => InvertedHorizontalLayout::new(
widgets.iter().map(|w| w.construct_layout(idx)).collect(),
),
Widget::VerticalLayout(widgets) => {
VerticalLayout::new(widgets.iter().map(|w| w.construct_layout(idx)).collect())
}
2023-02-14 10:23:12 +01:00
Widget::InvertedVerticalLayout(widgets) => InvertedVerticalLayout::new(
widgets.iter().map(|w| w.construct_layout(idx)).collect(),
),
2023-02-11 18:24:34 +01:00
_ => IndexedLayout::new({
let i = *idx;
*idx += 1;
i
}),
}
}
}