aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--karlgui/src/globals.rs18
-rw-r--r--karlgui/src/views/calendar.rs195
2 files changed, 136 insertions, 77 deletions
diff --git a/karlgui/src/globals.rs b/karlgui/src/globals.rs
index 202cce6..48af280 100644
--- a/karlgui/src/globals.rs
+++ b/karlgui/src/globals.rs
@@ -52,23 +52,7 @@ impl Globals {
}
}
}
- pub fn get_all_instances_range(
- &mut self,
- start: NaiveDateTime,
- end: NaiveDateTime,
- ) -> Option<Vec<(u64, Range<Option<NaiveDateTime>>)>> {
- let mut l = vec![];
- for t in &self.tasks.values().map(|e| e.id).collect::<Vec<_>>() {
- if let Some(r) = self.get_instances_range(*t, start, end) {
- l.extend(r.into_iter().map(|e| (*t, e.clone())));
- }
- }
- if l.len() > 0 {
- Some(l)
- } else {
- None
- }
- }
+
pub fn get_instances_range(
&mut self,
task: u64,
diff --git a/karlgui/src/views/calendar.rs b/karlgui/src/views/calendar.rs
index a861c73..ecb70dd 100644
--- a/karlgui/src/views/calendar.rs
+++ b/karlgui/src/views/calendar.rs
@@ -1,9 +1,8 @@
-use std::ops::Range;
-
use crate::{helper::weekday_to_str, Globals};
-use chrono::{Duration, NaiveDateTime};
-use egui::{Color32, Sense, Stroke, Ui, Vec2};
-use egui_extras::TableBuilder;
+use chrono::{Datelike, Duration, NaiveDateTime, Timelike};
+use egui::{Color32, Label, Rect, ScrollArea, Sense, Stroke, Ui, Vec2};
+use egui_extras::{Size, StripBuilder};
+use std::{collections::BTreeMap, ops::Range};
#[derive(Default)]
pub struct Calendar {
@@ -17,67 +16,143 @@ impl Calendar {
let start_dt = start_date.and_hms(0, 0, 0);
let end_dt = end_date.and_hms(0, 0, 0);
- let instances = if let Some(instances) = g.get_all_instances_range(start_dt, end_dt) {
- instances
- } else {
- ui.horizontal(|ui| {
- ui.spinner();
- ui.label("Loading…");
- });
- return;
- };
+ let task_ids = g.tasks.keys().map(|e| e.to_owned()).collect::<Vec<_>>();
+ let instances =
+ BTreeMap::from_iter(task_ids.iter().filter_map(|id| {
+ Some((id, g.get_instances_range(*id, start_dt, end_dt).to_owned()?))
+ }));
- let height = 50.0;
+ let height = 2000.0;
- TableBuilder::new(ui)
- .column(egui_extras::Size::exact(50.0))
- .columns(egui_extras::Size::remainder(), 7)
- .header(25.0, |mut ui| {
- ui.col(|_| {});
- for d in 0..7 {
- ui.col(|ui| {
- ui.heading(weekday_to_str(d));
+ ScrollArea::vertical().show(ui, |ui| {
+ StripBuilder::new(ui)
+ .size(Size::exact(50.0))
+ .sizes(Size::remainder(), 7)
+ .horizontal(|mut ui| {
+ ui.cell(|ui| {
+ for h in 0..24 {
+ ui.add_sized(
+ Vec2::new(50.0, height / 24.0),
+ Label::new(&format!("{h:02}:00")),
+ );
+ }
});
- }
- })
- .body(|mut ui| {
- let mut cols: [Vec<u64>; 7] =
- [vec![], vec![], vec![], vec![], vec![], vec![], vec![]];
- for h in 0..24 {
- ui.row(height, |mut ui| {
- ui.col(|ui| {
- ui.heading(&format!("{h:02}:00"));
- });
- for d in 0..7 {
- let _col = &mut cols[d];
- let time = start_dt + Duration::days(d as i64) + Duration::hours(h);
- let time_end = time + Duration::hours(1) - Duration::seconds(1);
- let instances_here =
- instances.iter().filter(|(_, r)| r.overlaps(time..time_end));
+ for d in 0..7 {
+ ui.cell(|ui| {
+ let time = start_dt + Duration::days(d as i64);
+ let time_end = time + Duration::days(1) - Duration::seconds(1);
+ let instances_here = instances
+ .iter()
+ .map(|(id, rs)| {
+ (
+ id,
+ rs.iter()
+ .filter(|r| r.overlaps(time..time_end))
+ .collect::<Vec<_>>(),
+ )
+ })
+ .filter(|(_, l)| l.len() != 0);
+
+ ui.vertical(|ui| {
+ ui.heading(weekday_to_str(
+ time.date().weekday().num_days_from_monday().into(),
+ ));
+ ui.horizontal(|ui| {
+ for (id, rs) in instances_here {
+ let task = g.tasks.get(id).unwrap();
+
+ let (rect, response) = ui.allocate_exact_size(
+ Vec2::new(10.0, height),
+ Sense::hover(),
+ );
- ui.col(|ui| {
- for (id, _) in instances_here {
- let task = g.tasks.get(id).unwrap();
- let (rect, response) =
- ui.allocate_at_least(Vec2::new(10.0, 50.0), Sense::hover());
- ui.painter().rect(
- rect,
- 0.0,
- Color32::KHAKI,
- Stroke::new(0.0, Color32::WHITE),
- );
- response.on_hover_ui_at_pointer(|ui| {
- ui.heading(&task.name);
- if let Some(d) = &task.description {
- ui.label(d);
+ for r in &rs {
+ let r =
+ r.start.unwrap_or(time)..r.end.unwrap_or(time_end);
+ let rect_start = (r.start.hour() as f32
+ + (r.start.minute() as f32 / 60.0))
+ / 24.0
+ * height;
+ let rect_end = (r.end.hour() as f32
+ + (r.end.minute() as f32 / 60.0))
+ / 24.0
+ * height;
+ ui.painter().rect(
+ Rect::from_two_pos(
+ rect.min + Vec2::new(0.0, rect_start),
+ rect.min + Vec2::new(10.0, rect_end),
+ ),
+ 0.0,
+ Color32::KHAKI,
+ Stroke::new(0.0, Color32::WHITE),
+ );
}
- });
- }
+
+ response.on_hover_ui_at_pointer(|ui| {
+ ui.heading(&task.name);
+ if let Some(d) = &task.description {
+ ui.label(d);
+ }
+ });
+ }
+ })
});
- }
- })
- }
- })
+ // });
+ // });
+ });
+ }
+ });
+ });
+
+ // TableBuilder::new(ui)
+ // .column(egui_extras::Size::exact(50.0))
+ // .columns(egui_extras::Size::remainder(), 7)
+ // .header(25.0, |mut ui| {
+ // ui.col(|_| {});
+ // for d in 0..7 {
+ // ui.col(|ui| {
+ // ui.heading(weekday_to_str(d));
+ // });
+ // }
+ // })
+ // .body(|mut ui| {
+ // let mut cols: [Vec<u64>; 7] =
+ // [vec![], vec![], vec![], vec![], vec![], vec![], vec![]];
+ // for h in 0..24 {
+ // ui.row(height, |mut ui| {
+ // ui.col(|ui| {
+ // ui.heading(&format!("{h:02}:00"));
+ // });
+ // for d in 0..7 {
+ // let _col = &mut cols[d];
+ // let time = start_dt + Duration::days(d as i64) + Duration::hours(h);
+ // let time_end = time + Duration::hours(1) - Duration::seconds(1);
+ // let instances_here =
+ // instances.iter().filter(|(_, r)| r.overlaps(time..time_end));
+
+ // ui.col(|ui| {
+ // for (id, _) in instances_here {
+ // let task = g.tasks.get(id).unwrap();
+ // let (rect, response) =
+ // ui.allocate_at_least(Vec2::new(10.0, 50.0), Sense::hover());
+ // ui.painter().rect(
+ // rect,
+ // 0.0,
+ // Color32::KHAKI,
+ // Stroke::new(0.0, Color32::WHITE),
+ // );
+ // response.on_hover_ui_at_pointer(|ui| {
+ // ui.heading(&task.name);
+ // if let Some(d) = &task.description {
+ // ui.label(d);
+ // }
+ // });
+ // }
+ // });
+ // }
+ // })
+ // }
+ // })
}
}