add public holidays support (background color of day cell)
This commit is contained in:
parent
281aab2a7e
commit
063a74f6f3
|
@ -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
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue