add public holidays support (background color of day cell)

This commit is contained in:
Fabrizio Iannetti 2024-06-30 08:26:11 +02:00
parent 281aab2a7e
commit 063a74f6f3
4 changed files with 48 additions and 10 deletions

View File

@ -18,6 +18,11 @@ Clandars are read only from ical files, which are taken:
* from command line if given as arguments * from command line if given as arguments
* from `<home>/.local/share/calendars/` if no argument is given * from `<home>/.local/share/calendars/` if no argument is given
### Public holidays
* calendar files that are named `<name>_bg.ical` are treated as defining public holidays
and rendered by changing the background of the day cell
## planned features ## planned features
* reload the events from a calendar file if the file changes * reload the events from a calendar file if the file changes

View File

@ -3,9 +3,16 @@ use std::vec::Vec;
use std::default::Default; use std::default::Default;
use std::string::String; use std::string::String;
#[derive(Clone, Debug, PartialEq)]
pub enum EventType {
Regular,
Background,
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Event { pub struct Event {
pub text: String, pub text: String,
pub ev_type: EventType,
pub begin: NaiveDate, pub begin: NaiveDate,
pub end: NaiveDate, pub end: NaiveDate,
} }
@ -43,13 +50,13 @@ impl EventsCollection {
} }
} }
pub fn create(self: &mut Self, begin: NaiveDate, end: NaiveDate, text: &str) { pub fn create(self: &mut Self, begin: NaiveDate, end: NaiveDate, text: &str, ev_type: &EventType) {
self.events.push(Event {text: text.to_string(), begin, end}); 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<Event> { pub fn is_any_in_day(&self, day: NaiveDate, ev_type: &EventType) -> Option<Event> {
for ev_day in &self.events { 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()); return Some(ev_day.clone());
} }
} }

View File

@ -5,6 +5,8 @@ use crate::model::events::EventsCollection;
use std::fs; use std::fs;
use log::warn; use log::warn;
use super::events::EventType;
fn cdt_as_date(cdt: &CalendarDateTime) -> NaiveDate { fn cdt_as_date(cdt: &CalendarDateTime) -> NaiveDate {
match cdt { match cdt {
CalendarDateTime::Floating(ndt) => ndt.date(), 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) { 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()); 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) { 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; } 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() { for cc in calendar.iter() {
match cc { match cc {
CalendarComponent::Event(event) => create_event(events, event), CalendarComponent::Event(event) => create_event(events, event, &ev_type),
_ => (), _ => (),
} }
} }

View File

@ -11,6 +11,7 @@
use super::basics::CellGrid; use super::basics::CellGrid;
use super::row::CalendarRow; use super::row::CalendarRow;
use super::row::RowDay; use super::row::RowDay;
use crate::model::events::EventType;
use crate::model::events::{Event, EventsCollection}; use crate::model::events::{Event, EventsCollection};
use chrono::{ use chrono::{
Datelike, Datelike,
@ -70,6 +71,7 @@ pub struct CalendarParams {
ev_height: f32, ev_height: f32,
ev_margin: f32, ev_margin: f32,
ev_bg: Color, ev_bg: Color,
ev_bg_alt: Color,
ev_fontsize: f32, ev_fontsize: f32,
} }
@ -87,6 +89,7 @@ impl CalendarParams {
ev_height: 18.0, ev_height: 18.0,
ev_margin: 2.0, ev_margin: 2.0,
ev_bg: Color::from_rgb8(200, 245, 200), 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, ev_fontsize: 14.0,
} }
} }
@ -129,6 +132,7 @@ fn render_events_in_row<Renderer>(
struct EventBar<'a> { struct EventBar<'a> {
ev: &'a Event, ev: &'a Event,
bounds: Rectangle, bounds: Rectangle,
bg: Color,
} }
let paragraph = Renderer::Paragraph::with_text(Text { let paragraph = Renderer::Paragraph::with_text(Text {
content, content,
@ -154,6 +158,7 @@ fn render_events_in_row<Renderer>(
let mut ev_bars: Vec<EventBar> = all_events let mut ev_bars: Vec<EventBar> = all_events
.iter() .iter()
.filter(|e| e.ev_type == EventType::Regular)
.map(|e| EventBar { .map(|e| EventBar {
ev: e, ev: e,
bounds: Rectangle { bounds: Rectangle {
@ -162,6 +167,7 @@ fn render_events_in_row<Renderer>(
width: 0.0, width: 0.0,
height: ev_height, height: ev_height,
}, },
bg: params.ev_bg,
}) })
.collect(); .collect();
@ -215,7 +221,7 @@ fn render_events_in_row<Renderer>(
}, },
..renderer::Quad::default() ..renderer::Quad::default()
}, },
params.ev_bg, ev_bar.bg,
); );
let ev_text_size = Size { let ev_text_size = Size {
height: ev_bar.bounds.height - 2.0, height: ev_bar.bounds.height - 2.0,
@ -576,7 +582,11 @@ impl<'a> CalendarView<'a> {
let fg = self.params.day_fg; let fg = self.params.day_fg;
// background color of the day cell // 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.fill_quad(
renderer::Quad { renderer::Quad {