diff --git a/Cargo.lock b/Cargo.lock index c585b42..b44fe7e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -161,7 +161,7 @@ dependencies = [ "serde", "slint", "slint-build", - "toml 1.1.2+spec-1.1.0", + "toml", ] [[package]] @@ -722,9 +722,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.60" +version = "1.2.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" +checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" dependencies = [ "find-msvc-tools", "jobserver", @@ -1685,9 +1685,9 @@ dependencies = [ [[package]] name = "gif" -version = "0.14.2" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee8cfcc411d9adbbaba82fb72661cc1bcca13e8bba98b364e62b2dba8f960159" +checksum = "f5df2ba84018d80c213569363bdcd0c64e6933c67fe4c1d60ecf822971a3c35e" dependencies = [ "color_quant", "weezl", @@ -1841,12 +1841,6 @@ dependencies = [ "foldhash 0.2.0", ] -[[package]] -name = "hashbrown" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" - [[package]] name = "heck" version = "0.5.0" @@ -2339,12 +2333,12 @@ checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8" [[package]] name = "indexmap" -version = "2.14.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" dependencies = [ "equivalent", - "hashbrown 0.17.0", + "hashbrown 0.16.1", "serde", "serde_core", ] @@ -2594,14 +2588,14 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.16" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" +checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" dependencies = [ "bitflags 2.11.0", "libc", "plain", - "redox_syscall 0.7.4", + "redox_syscall 0.7.3", ] [[package]] @@ -3828,9 +3822,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.7.4" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a" +checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" dependencies = [ "bitflags 2.11.0", ] @@ -4180,7 +4174,7 @@ dependencies = [ "regex", "serde_json", "tar", - "toml 0.9.12+spec-1.1.0", + "toml", ] [[package]] @@ -4686,21 +4680,6 @@ dependencies = [ "winnow 0.7.15", ] -[[package]] -name = "toml" -version = "1.1.2+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" -dependencies = [ - "indexmap", - "serde_core", - "serde_spanned", - "toml_datetime 1.1.1+spec-1.1.0", - "toml_parser", - "toml_writer", - "winnow 1.0.1", -] - [[package]] name = "toml_datetime" version = "0.7.5+spec-1.1.0" diff --git a/Cargo.toml b/Cargo.toml index 8a492a5..0b1de00 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" chrono = "0.4.42" serde = "1.0.219" slint = "1.15.1" -toml = "1.1.2" +toml = "0.9.5" [build-dependencies] slint-build = "1.15.1" diff --git a/build.rs b/build.rs index 0ac588d..237d430 100644 --- a/build.rs +++ b/build.rs @@ -1,4 +1,5 @@ fn main() { + let mut style = String::from("cosmic"); #[cfg(all(feature = "dark", feature = "light"))] diff --git a/config.toml b/config.toml index 93d766b..1bfb6b9 100644 --- a/config.toml +++ b/config.toml @@ -1,50 +1,53 @@ -# Default Aliveline config +# This is the default config for Aliveline. +# Note: All colors are of format 0xAARRGGBB -# Paths may be relative to config directory or absolute -[paths] -logs = "logs" +# Path where logs are saved. May be relative to config dir or absolute. +log_path = "logs" -# Colors may be defined either as alias (string) or as 0xAARRGGBB (integer) +# Colors used for events. For now Aliveline expects to have exactly 16 colors, but this is subject to change in future. +event_colors = [ + 0xff_97f9f9, + 0xff_a4def9, + 0xff_c1e0f7, + 0xff_cfbae1, + 0xff_c59fc9, + 0xff_4e3d42, + 0xff_c9d5b5, + 0xff_2d82b7, + 0xff_556f44, + 0xff_772e25, + 0xff_c44536, + 0xff_7c6a0a, + 0xff_babd8d, + 0xff_ffdac6, + 0xff_fa9500, + 0xff_eb6424 +] -# Aliases must be declared here, otherwise fallback color is used -[colors.aliases] -background = 0xFF_808080 -timeline = 0xFF_A9A9A9 -black = 0xFF_000000 -white = 0xFF_FFFFFF -"very aggressive pink color to use with fallback so you definitely notice it" = 0xFF_FF00E7 +# Colors used for event colors. Aliveline expects it to have same size as events. +text_colors = [ + 0xff_000000, + 0xff_000000, + 0xff_000000, + 0xff_000000, + 0xff_000000, + 0xff_ffffff, + 0xff_000000, + 0xff_000000, + 0xff_000000, + 0xff_ffffff, + 0xff_000000, + 0xff_000000, + 0xff_000000, + 0xff_000000, + 0xff_000000, + 0xff_000000 +] [colors] -# Timeline background -background = "background" -# Timeline foreground -timeline = "timeline" -# Background text (timestamps, event names, etc.) -text = "black" -# Used when alias was not found -fallback = "very aggressive pink color to use with fallback so you definitely notice it" - -# Event colors are chosen pseudorandomly from this array, respecting each color's priority -# Event color consists of: -# - Background color (default: black) -# - Text color (default: same as colors.text) -# - Priority (default: 1) -# Full example: { background = "color", text = "color", priority = 1337 } -events = [ - { background = 0xff_97f9f9 }, - { background = 0xff_a4def9 }, - { background = 0xff_c1e0f7 }, - { background = 0xff_cfbae1 }, - { background = 0xff_c59fc9 }, - { background = 0xff_4e3d42, text = "white" }, - { background = 0xff_c9d5b5 }, - { background = 0xff_2d82b7 }, - { background = 0xff_556f44 }, - { background = 0xff_772e25, text = "white" }, - { background = 0xff_c44536 }, - { background = 0xff_7c6a0a }, - { background = 0xff_babd8d }, - { background = 0xff_ffdac6 }, - { background = 0xff_fa9500 }, - { background = 0xff_eb6424 }, -] +# Color behind the timeline +background = 0xFF_808080 +# Color of the base timeline +timeline = 0xFF_a9a9a9 +# Color of background text (timestamps, event names, etc.) +background_text = 0xFF_000000 diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..22ce814 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,104 @@ +use std::path::PathBuf; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Debug)] +#[serde(default)] +pub struct Colors { + pub background: u32, + pub timeline: u32, + pub background_text: u32, +} + +impl Default for Colors { + fn default() -> Self { + Colors { + background: 0xff_808080, + timeline: 0xff_a9a9a9, + background_text: 0xff_000000, + } + } +} + +#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] +pub struct Config { + /// directory, where config is located + #[serde(skip)] + pub conf_path: PathBuf, + pub log_path: PathBuf, + #[serde(default)] + pub colors: Colors, + #[serde(default)] + pub event_colors: Vec, + #[serde(default)] + pub text_colors: Vec, +} + +impl Default for Config { + fn default() -> Self { + let conf_path = PathBuf::new(); + let colors: Colors = Default::default(); + let event_colors: Vec = vec![ + 0xff_97f9f9, + 0xff_a4def9, + 0xff_c1e0f7, + 0xff_cfbae1, + 0xff_c59fc9, + 0xff_4e3d42, + 0xff_c9d5b5, + 0xff_2d82b7, + 0xff_556f44, + 0xff_772e25, + 0xff_c44536, + 0xff_7c6a0a, + 0xff_babd8d, + 0xff_ffdac6, + 0xff_fa9500, + 0xff_eb6424 + ]; + let text_colors: Vec = vec![ + 0xff000000, + 0xff000000, + 0xff000000, + 0xff000000, + 0xff000000, + 0xffffffff, + 0xff000000, + 0xff000000, + 0xff000000, + 0xffffffff, + 0xff000000, + 0xff000000, + 0xff000000, + 0xff000000, + 0xff000000, + 0xff000000 + ]; + Config { + conf_path, + log_path: PathBuf::from("./logs"), + colors, + event_colors, + text_colors, + } + } +} + +impl Config { + pub fn new(conf_path: PathBuf) -> Self { + let conf_dir: PathBuf = conf_path.parent().unwrap().into(); + Config { + conf_path: conf_dir, + ..Default::default() + } + } + + pub fn load(path: PathBuf) -> Option { + if let Ok(toml_string) = std::fs::read_to_string(path.clone()) { + if let Ok(mut conf) = toml::from_str::(&toml_string) { + conf.conf_path = path.parent().unwrap().into(); + return Some(conf); + } + } + None + } +} diff --git a/src/config/color.rs b/src/config/color.rs deleted file mode 100644 index b819aa2..0000000 --- a/src/config/color.rs +++ /dev/null @@ -1,99 +0,0 @@ -use std::{collections::HashMap, hash::{DefaultHasher, Hash, Hasher}}; -use serde::{Serialize, Deserialize}; -use slint::Color; - -#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] -#[serde(untagged)] -pub enum ConfigColor { - Raw(u32), - Alias(String), -} - -impl Default for ConfigColor { - fn default() -> Self { - Self::Raw(0xFF000000) - } -} - -#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] -#[serde(default)] -pub struct EventColor { - pub background: ConfigColor, - pub text: Option, - pub priority: u64, -} - -impl Default for EventColor { - fn default() -> Self { - Self { - background: ConfigColor::default(), - text: None, - priority: 1, - } - } -} - -#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] -#[serde(default)] -pub struct Colors { - pub aliases: HashMap, - - pub background: ConfigColor, - pub timeline: ConfigColor, - pub text: ConfigColor, - pub fallback: ConfigColor, - - pub events: Vec, -} - -impl Default for Colors { - fn default() -> Self { - super::default::default_config().colors.into() - } -} - -#[inline(always)] -fn argb(value: u32) -> Color { - Color::from_argb_encoded(value) -} - -impl Colors { - #[inline(always)] - pub fn fallback_color(&self) -> Color { - self.try_get_color(&self.fallback).unwrap_or_default() - } - - pub fn try_get_color(&self, color: &ConfigColor) -> Option { - match color { - ConfigColor::Raw(color) => Some(argb(*color)), - ConfigColor::Alias(alias) => self.aliases.get(alias).map(|c| argb(*c)), - } - } - - pub fn get_color(&self, color: &ConfigColor) -> Color { - self.try_get_color(color).unwrap_or_else(|| self.fallback_color()) - } - - pub fn event_color_for(&self, text: &str) -> &EventColor { - let priority_sum: u64 = self.events.iter().map(|e| e.priority).sum(); - - let mut s = DefaultHasher::new(); - text.hash(&mut s); - let hash = s.finish(); - - let mut chosen = hash % priority_sum; - - for (id, color) in self.events.iter().enumerate() { - match chosen.checked_sub(color.priority) { - Some(new_count) => { - chosen = new_count; - }, - None => { - return &self.events[id]; - }, - } - } - - unreachable!() - } -} diff --git a/src/config/default.rs b/src/config/default.rs deleted file mode 100644 index 73b0588..0000000 --- a/src/config/default.rs +++ /dev/null @@ -1,53 +0,0 @@ -use std::collections::HashMap; - -use crate::config::color::{ConfigColor, EventColor}; - -use super::*; - -const DEFAULT_CFG: &'static str = include_str!("../../config.toml"); - -#[derive(Deserialize)] -pub(super) struct DefaultConfig { - pub(super) colors: DefaultColors, - pub(super) paths: DefaultPaths, -} - -#[derive(Deserialize)] -pub struct DefaultColors { - pub aliases: HashMap, - - pub background: ConfigColor, - pub timeline: ConfigColor, - pub text: ConfigColor, - pub fallback: ConfigColor, - - pub events: Vec, -} - -impl From for Colors { - fn from(value: DefaultColors) -> Self { - Self { - aliases: value.aliases, - background: value.background, - timeline: value.timeline, - text: value.text, - fallback: value.fallback, - events: value.events - } - } -} - -#[derive(Deserialize)] -pub struct DefaultPaths { - pub logs: PathBuf, -} - -impl From for Paths { - fn from(value: DefaultPaths) -> Self { - Self { logs: value.logs } - } -} - -pub(super) fn default_config() -> DefaultConfig { - toml::de::from_str(DEFAULT_CFG).unwrap() -} diff --git a/src/config/mod.rs b/src/config/mod.rs deleted file mode 100644 index cf5a592..0000000 --- a/src/config/mod.rs +++ /dev/null @@ -1,57 +0,0 @@ -use std::path::PathBuf; -use serde::{Deserialize, Serialize}; -use color::Colors; - -pub mod color; -mod default; - -#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] -#[serde(default)] -pub struct Paths { - pub logs: PathBuf, -} - -impl Default for Paths { - fn default() -> Self { - default::default_config().paths.into() - } -} - -#[derive(Serialize, Deserialize, Default, Clone, PartialEq, Eq, Debug)] -#[serde(default)] -pub struct Config { - /// directory, where config is located - #[serde(skip)] - pub conf_path: PathBuf, - pub colors: Colors, - pub paths: Paths, -} - -impl Config { - pub fn new(conf_path: PathBuf) -> Self { - let conf_dir: PathBuf = conf_path.parent().unwrap().into(); - Config { - conf_path: conf_dir, - ..Default::default() - } - } - - fn replace_missing_fields(&mut self) { - let default = Config::default(); - - if self.colors.events.len() == 0 { - self.colors.events = default.colors.events; - } - } - - pub fn load(path: PathBuf) -> Option { - if let Ok(toml_string) = std::fs::read_to_string(path.clone()) { - if let Ok(mut conf) = toml::from_str::(&toml_string) { - conf.replace_missing_fields(); - conf.conf_path = path.parent().unwrap().into(); - return Some(conf); - } - } - None - } -} diff --git a/src/lib.rs b/src/lib.rs index 0740372..df734c9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ use config::Config; -use std::path::PathBuf; +use std::{hash::{DefaultHasher, Hash, Hasher}, path::PathBuf}; pub mod config; pub mod log; @@ -45,3 +45,9 @@ pub fn load_config() -> Config { println!("Using config path ./config.toml"); Config::new(PathBuf::from("./config.toml")) } +/// Get random-like color id in range 0..16 by computing string hash +pub fn color_id_from_name(name: String) -> i32 { + let mut s = DefaultHasher::new(); + name.hash(&mut s); + let hash = s.finish(); + (hash % 16) as i32 } diff --git a/src/log.rs b/src/log.rs index 9d42ad1..8f0bcbb 100644 --- a/src/log.rs +++ b/src/log.rs @@ -46,12 +46,12 @@ impl Log { } fn get_log_dir(config: &Config) -> PathBuf { - if config.paths.logs.is_relative() { + if config.log_path.is_relative() { let mut path = config.conf_path.clone(); - path.push(&config.paths.logs); + path.push(&config.log_path); return path; } else { - return config.paths.logs.clone(); + return config.log_path.clone(); } } @@ -77,14 +77,14 @@ impl Event { let start = Time { hour: (start / 3600) as u8, minute: ((start / 3600) / 60) as u8, - second: Some((start % 60) as u8), - nanosecond: None, + second: (start % 60) as u8, + nanosecond: 0 }; let end = Time { hour: (end / 3600) as u8, minute: ((end % 3600) / 60) as u8, - second: Some((end % 60) as u8), - nanosecond: None, + second: (end % 60) as u8, + nanosecond: 0 }; Event { name, start, end, finished } } diff --git a/src/main.rs b/src/main.rs index 3b8ba68..dd5c9a3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,40 +3,27 @@ use std::{error::Error, rc::Rc, sync::{Arc, Mutex}}; -use aliveline::{config::{Config, color::Colors}, load_config, log::{Event, Log}}; +use aliveline::{color_id_from_name, config::Config, load_config, log::{Event, Log}}; use chrono::{Datelike, Timelike}; use slint::{Color, Model, ModelRc, SharedString, ToSharedString, VecModel, Weak}; use toml::value::{Date as TomlDate, Time}; slint::include_modules!(); -impl TimelineEvent { - pub fn colors(colors: &Colors, text: &str) -> (Color, Color) { - let event_colors = colors.event_color_for(text); - let background_color = colors.get_color(&event_colors.background); - let text_color = match &event_colors.text { - Some(color) => colors.get_color(color), - None => colors.get_color(&colors.text), - }; - (background_color, text_color) - } - - pub fn from_event(event: Event, colors: &Colors) -> Self { +impl From for TimelineEvent { + fn from(event: Event) -> Self { let start = (event.start.hour as i32) * 3600 + (event.start.minute as i32) * 60 - + (event.start.second.unwrap() as i32); + + (event.start.second as i32); let end = (event.end.hour as i32) * 3600 + (event.end.minute as i32) * 60 - + (event.end.second.unwrap() as i32); - let (background_color, text_color) = TimelineEvent::colors(colors, event.name.as_str()); - + + (event.end.second as i32); TimelineEvent { start, duration: end - start, label: event.name.to_shared_string(), finished: event.finished, - background_color, - text_color, + color_id: color_id_from_name(event.name) } } } @@ -46,27 +33,27 @@ impl From for Event { let start = Time { hour: (event.start / 3600) as u8, minute: ((event.start % 3600) / 60) as u8, - second: Some((event.start % 60) as u8), - nanosecond: None, + second: (event.start % 60) as u8, + nanosecond: 0 }; let endsecs = event.start + event.duration; let end = Time { hour: (endsecs / 3600) as u8, minute: ((endsecs % 3600) / 60) as u8, - second: Some((endsecs % 60) as u8), - nanosecond: None, + second: (endsecs % 60) as u8, + nanosecond: 0 }; Event { start, end, name: event.label.to_string(), finished: event.finished } } } -fn load_log(ui_weak: Weak, log: Arc>, config: Arc) { +fn load_log(ui_weak: Weak, log: Arc>) { let ui = ui_weak.unwrap(); let log_guard = log.lock().expect("Log shouldn't be used twice"); let events: Vec = (*log_guard) .events .iter() - .map(|event| TimelineEvent::from_event(event.clone(), &config.colors)) + .map(|event| TimelineEvent::from((*event).clone())) .collect(); let in_progress = events.iter().any(|event| !event.finished); let model: ModelRc = Rc::new(VecModel::from(events)).into(); @@ -80,9 +67,21 @@ fn load_log(ui_weak: Weak, log: Arc>, config: Arc) fn load_colors(ui_weak: Weak, config: Arc) { let ui = ui_weak.unwrap(); let pal = ui.global::(); - pal.set_background(config.colors.get_color(&config.colors.background)); - pal.set_timeline(config.colors.get_color(&config.colors.timeline)); - pal.set_background_text(config.colors.get_color(&config.colors.text)); + pal.set_background(Color::from_argb_encoded(config.colors.background)); + pal.set_timeline(Color::from_argb_encoded(config.colors.timeline)); + pal.set_background_text(Color::from_argb_encoded(config.colors.background_text)); + + // This looks like war crime + let event_colors_rc: ModelRc = Rc::new(VecModel::from( + config.event_colors.iter() + .map(|value| Color::from_argb_encoded(*value)).collect::>() + )).into(); + pal.set_event_colors(event_colors_rc); + let event_text_rc: ModelRc = Rc::new(VecModel::from( + config.text_colors.iter() + .map(|value| Color::from_argb_encoded(*value)).collect::>() + )).into(); + pal.set_event_text(event_text_rc); } fn main() -> Result<(), Box> { @@ -102,8 +101,7 @@ fn main() -> Result<(), Box> { let ui_weak = ui.as_weak(); let log = writing_log.clone(); - let config_arc = config.clone(); - load_log(ui_weak, log, config_arc); + load_log(ui_weak, log); let ui_weak = ui.as_weak(); let config_arc = config.clone(); @@ -124,7 +122,7 @@ fn main() -> Result<(), Box> { let events: Vec = Log::load_from(&config, date) .events .iter() - .map(|event| TimelineEvent::from_event(event.clone(), &config.colors)) + .map(|event| TimelineEvent::from((*event).clone())) .collect(); let model: ModelRc = Rc::new(VecModel::from(events)).into(); let mut state = ui.get_review_state(); @@ -167,7 +165,6 @@ fn main() -> Result<(), Box> { ui.on_start_new_event({ let ui_weak = ui.as_weak(); let log = writing_log.clone(); - let config = config.clone(); move |event_name: SharedString| { let ui = ui_weak.unwrap(); @@ -175,16 +172,13 @@ fn main() -> Result<(), Box> { let events = state.events.as_any() .downcast_ref::>() .unwrap(); - - let (background_color, text_color) = TimelineEvent::colors(&config.colors, event_name.as_str()); let event = TimelineEvent { duration: 0, finished: false, label: event_name.clone(), start: state.offset, - background_color, - text_color, + color_id: color_id_from_name(event_name.to_string()) }; { @@ -201,7 +195,6 @@ fn main() -> Result<(), Box> { ui.on_stop_event({ let ui_weak = ui.as_weak(); let log = writing_log.clone(); - let config = config.clone(); move || { let ui = ui_weak.unwrap(); let state = ui.get_record_state(); @@ -214,16 +207,12 @@ fn main() -> Result<(), Box> { .unwrap(); let event = events.row_data(event_id) .expect("stop-event called without unfinished events"); - - let (background_color, text_color) = TimelineEvent::colors(&config.colors, event.label.as_str()); - let new_event = TimelineEvent { duration: state.offset - event.start, finished: true, label: event.label.clone(), start: event.start, - background_color, - text_color, + color_id: color_id_from_name(event.label.to_string()) }; { @@ -274,7 +263,6 @@ fn main() -> Result<(), Box> { ui.on_new_day_started({ let ui_weak = ui.as_weak(); let log = writing_log.clone(); - let config = config.clone(); move || { let ui = ui_weak.unwrap(); @@ -309,7 +297,7 @@ fn main() -> Result<(), Box> { } } - load_log(ui.as_weak(), log.clone(), config.clone()); + load_log(ui.as_weak(), log.clone()); ui.invoke_save_log(); } }); diff --git a/ui/theme.slint b/ui/theme.slint index 03a7282..30b211a 100644 --- a/ui/theme.slint +++ b/ui/theme.slint @@ -2,4 +2,42 @@ export global Palette { in-out property background: gray; in-out property timeline: darkgray; in-out property background-text: black; + // Note: these colors were almost randomly picked + in-out property<[color]> event-colors: [ + #97f9f9, + #a4def9, + #c1e0f7, + #cfbae1, + #c59fc9, + #4e3d42, + #c9d5b5, + #2d82b7, + #556f44, + #772e25, + #c44536, + #7c6a0a, + #babd8d, + #ffdac6, + #fa9500, + #eb6424 + ]; + + in-out property <[color]> event-text: [ + #000000, + #000000, + #000000, + #000000, + #000000, + #ffffff, + #000000, + #000000, + #000000, + #ffffff, + #000000, + #000000, + #000000, + #000000, + #000000, + #000000 + ]; } diff --git a/ui/timeline.slint b/ui/timeline.slint index 94753fc..1fa828b 100644 --- a/ui/timeline.slint +++ b/ui/timeline.slint @@ -6,8 +6,7 @@ export struct TimelineEvent { duration: int, finished: bool, label: string, - background-color: color, - text-color: color, + color-id: int, } export struct TimelineState { @@ -70,7 +69,7 @@ export component Timeline inherits Rectangle { visible: self.width > 0 && self.real-x < parent.width; border-color: black; border-width: 1px; - background: event.background-color; + background: Palette.event-colors[event.color-id]; Text { x: 0; @@ -88,7 +87,7 @@ export component Timeline inherits Rectangle { visible: timeline-event.visible && (self.width * 2 < timeline-event.width || (!end-txt.visible && self.width < timeline-event.width)); - color: event.text-color; + color: Palette.event-text[event.color-id]; } end-txt := Text { x: timeline-event.width - self.width; @@ -97,7 +96,7 @@ export component Timeline inherits Rectangle { TimeString.from(event.start + event.duration) : TimeString.from(visible-offset); visible: timeline-event.visible && timeline-event.width - self.width * 2 > 0; - color: event.text-color; + color: Palette.event-text[event.color-id]; } } @children