use std::collections::BTreeSet;
use serde_json::{Map, Value, json};
pub const WHEEL: f32 = 100.0;
pub const HELP_DELAY: f32 = 0.5;
pub const SCALE: f32 = 1.0;
pub const SCALE_KEY: &str = "scale";
pub const LINGER: f32 = 0.75;
pub const EASE: f32 = 0.12;
pub const BAR_SHUT: f32 = 80.0;
pub const DESK: f32 = 1400.0;
#[derive(Debug, Clone, PartialEq)]
pub struct Settings {
pub wheel: f32,
pub help_delay: f32,
pub scale: f32,
pub linger: f32,
pub ease: f32,
pub bar_shut: Option<f32>,
pub bar_open: Option<f32>,
pub on: BTreeSet<Toggle>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum Toggle {
Help,
Bubbles,
Fold,
Confirm,
Dock,
}
impl Settings {
pub fn on(&self, switch: Toggle) -> bool {
self.on.contains(&switch)
}
pub fn set(&mut self, switch: Toggle, on: bool) {
if on {
self.on.insert(switch);
} else {
self.on.remove(&switch);
}
}
}
impl Default for Settings {
fn default() -> Self {
Self {
wheel: WHEEL,
help_delay: HELP_DELAY,
scale: SCALE,
linger: LINGER,
ease: EASE,
bar_shut: None,
bar_open: None,
on: [Toggle::Help, Toggle::Bubbles, Toggle::Fold, Toggle::Confirm].into(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Kind {
Toggle,
Number {
unit: &'static str,
floor: f32,
ceiling: f32,
step: f32,
},
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Knobbed {
On(bool),
At(f32),
}
#[derive(Debug, Clone, Copy)]
pub struct Knob {
pub key: &'static str,
pub label: &'static str,
pub help: &'static str,
pub kind: Kind,
pub get: fn(&Settings) -> Knobbed,
pub set: fn(&mut Settings, Knobbed),
}
const fn seconds(ceiling: f32, step: f32) -> Kind {
Kind::Number {
unit: " s",
floor: 0.0,
ceiling,
step,
}
}
const fn points(floor: f32, ceiling: f32, step: f32) -> Kind {
Kind::Number {
unit: " pt",
floor,
ceiling,
step,
}
}
mod knobs;
pub use knobs::KNOBS;
pub fn knob(key: &str) -> Option<&'static Knob> {
KNOBS.iter().find(|knob| knob.key == key)
}
pub fn from_json(held: &Value) -> Settings {
let mut out = Settings::default();
for knob in KNOBS {
let Some(value) = held.get(knob.key) else {
continue;
};
let read = match knob.kind {
Kind::Toggle => value.as_bool().map(Knobbed::On),
Kind::Number { .. } => serde_json::from_value(value.clone()).ok().map(Knobbed::At),
};
if let Some(read) = read {
(knob.set)(&mut out, read);
}
}
out
}
pub fn to_json(settings: &Settings) -> Value {
let rest = Settings::default();
let mut out = Map::new();
for knob in KNOBS {
let held = (knob.get)(settings);
if held == (knob.get)(&rest) {
continue;
}
let value = match held {
Knobbed::On(on) => json!(on),
Knobbed::At(at) => json!(at),
};
out.insert(knob.key.to_owned(), value);
}
Value::Object(out)
}
#[cfg(test)]
mod tests;