diff --git a/README.md b/README.md index a0c458b..6faebfb 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,11 @@ Clandars are read only from ical files, which are taken: * from command line if given as arguments * from `/.local/share/calendars/` if no argument is given +### Public holidays + +* calendar files that are named `_bg.ical` are treated as defining public holidays + and rendered by changing the background of the day cell + ## planned features * reload the events from a calendar file if the file changes diff --git a/src/model/events.rs b/src/model/events.rs index 94c5713..1a5dd67 100644 --- a/src/model/events.rs +++ b/src/model/events.rs @@ -3,9 +3,16 @@ use std::vec::Vec; use std::default::Default; use std::string::String; +#[derive(Clone, Debug, PartialEq)] +pub enum EventType { + Regular, + Background, +} + #[derive(Clone, Debug)] pub struct Event { pub text: String, + pub ev_type: EventType, pub begin: NaiveDate, pub end: NaiveDate, } @@ -43,13 +50,13 @@ impl EventsCollection { } } - pub fn create(self: &mut Self, begin: NaiveDate, end: NaiveDate, text: &str) { - self.events.push(Event {text: text.to_string(), begin, end}); + pub fn create(self: &mut Self, begin: NaiveDate, end: NaiveDate, text: &str, ev_type: &EventType) { + self.events.push(Event {text: text.to_string(), ev_type: ev_type.clone(), begin, end}); } - pub fn is_any_in_day(&self, day: NaiveDate) -> Option { + pub fn is_any_in_day(&self, day: NaiveDate, ev_type: &EventType) -> Option { for ev_day in &self.events { - if ev_day.is_in_day(day) { + if ev_day.is_in_day(day) && &ev_day.ev_type == ev_type { return Some(ev_day.clone()); } } @@ -105,4 +112,4 @@ impl Default for EventsCollection { fn default() -> EventsCollection { EventsCollection::new() } -} \ No newline at end of file +} diff --git a/src/model/ical_bridge.rs b/src/model/ical_bridge.rs index 9638d1c..cbb8684 100644 --- a/src/model/ical_bridge.rs +++ b/src/model/ical_bridge.rs @@ -5,6 +5,8 @@ use crate::model::events::EventsCollection; use std::fs; use log::warn; +use super::events::EventType; + fn cdt_as_date(cdt: &CalendarDateTime) -> NaiveDate { match cdt { CalendarDateTime::Floating(ndt) => ndt.date(), @@ -20,8 +22,12 @@ fn as_date(cal_date: &DatePerhapsTime) -> NaiveDate { } } -fn create_event(events: &mut EventsCollection, event: &icalendar::Event) { - events.create(as_date(&event.get_start().unwrap()), as_date(&event.get_end().unwrap()).pred_opt().unwrap(), event.get_summary().unwrap()); +fn create_event(events: &mut EventsCollection, event: &icalendar::Event, ev_type: &EventType) { + events.create( + as_date(&event.get_start().unwrap()), + as_date(&event.get_end().unwrap()).pred_opt().unwrap(), + event.get_summary().unwrap(), + ev_type); } pub fn load_calendar(calendar_path: &std::path::Path, events: &mut EventsCollection) { @@ -38,9 +44,19 @@ pub fn load_calendar(calendar_path: &std::path::Path, events: &mut EventsCollect Err(e) => { warn!("Error parsing calendar {}", e); return; } } + let stem = calendar_path.file_stem().unwrap().to_str().unwrap_or(""); + + // TODO: keep it simple for now, just use a filename coding + let ev_type = if stem.ends_with("_bg") { + EventType::Background + } + else { + EventType::Regular + }; + for cc in calendar.iter() { match cc { - CalendarComponent::Event(event) => create_event(events, event), + CalendarComponent::Event(event) => create_event(events, event, &ev_type), _ => (), } } diff --git a/src/ui/calendar.rs b/src/ui/calendar.rs index 646b68b..89ecbe5 100644 --- a/src/ui/calendar.rs +++ b/src/ui/calendar.rs @@ -11,6 +11,7 @@ use super::basics::CellGrid; use super::row::CalendarRow; use super::row::RowDay; +use crate::model::events::EventType; use crate::model::events::{Event, EventsCollection}; use chrono::{ Datelike, @@ -70,6 +71,7 @@ pub struct CalendarParams { ev_height: f32, ev_margin: f32, ev_bg: Color, + ev_bg_alt: Color, ev_fontsize: f32, } @@ -87,6 +89,7 @@ impl CalendarParams { ev_height: 18.0, ev_margin: 2.0, ev_bg: Color::from_rgb8(200, 245, 200), + ev_bg_alt: Color::from_rgb8(215, 215, 215), //Color::from_rgb8(200, 200, 250), ev_fontsize: 14.0, } } @@ -129,6 +132,7 @@ fn render_events_in_row( struct EventBar<'a> { ev: &'a Event, bounds: Rectangle, + bg: Color, } let paragraph = Renderer::Paragraph::with_text(Text { content, @@ -154,6 +158,7 @@ fn render_events_in_row( let mut ev_bars: Vec = all_events .iter() + .filter(|e| e.ev_type == EventType::Regular) .map(|e| EventBar { ev: e, bounds: Rectangle { @@ -162,6 +167,7 @@ fn render_events_in_row( width: 0.0, height: ev_height, }, + bg: params.ev_bg, }) .collect(); @@ -215,7 +221,7 @@ fn render_events_in_row( }, ..renderer::Quad::default() }, - params.ev_bg, + ev_bar.bg, ); let ev_text_size = Size { height: ev_bar.bounds.height - 2.0, @@ -576,7 +582,11 @@ impl<'a> CalendarView<'a> { let fg = self.params.day_fg; // background color of the day cell - let bg_color = self.params.bg_for_day(current_day); + let bg_color = if self.events.is_any_in_day(current_day, &EventType::Background).is_some() { + self.params.ev_bg_alt + } else { + self.params.bg_for_day(current_day) + }; renderer.fill_quad( renderer::Quad {