diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/app.rs | 29 | ||||
-rw-r--r-- | src/views.rs | 85 |
2 files changed, 82 insertions, 32 deletions
@@ -111,7 +111,7 @@ impl App { | |||
111 | fn status(&self) -> StatusLine { | 111 | fn status(&self) -> StatusLine { |
112 | let today = chrono::Local::now().naive_utc().date(); | 112 | let today = chrono::Local::now().naive_utc().date(); |
113 | let remaining = self.habits.iter().map(|h| h.remaining(today)).sum::<u32>(); | 113 | let remaining = self.habits.iter().map(|h| h.remaining(today)).sum::<u32>(); |
114 | let total = self.habits.iter().map(|h| h.total()).sum::<u32>(); | 114 | let total = self.habits.iter().map(|h| h.goal()).sum::<u32>(); |
115 | let completed = total - remaining; | 115 | let completed = total - remaining; |
116 | 116 | ||
117 | let timestamp = if self.view_month_offset == 0 { | 117 | let timestamp = if self.view_month_offset == 0 { |
@@ -124,7 +124,7 @@ impl App { | |||
124 | let months = self.view_month_offset; | 124 | let months = self.view_month_offset; |
125 | format!( | 125 | format!( |
126 | "{:>width$}", | 126 | "{:>width$}", |
127 | format!("{} months ago", self.view_month_offset), | 127 | format!("{} months ago", months), |
128 | width = CONFIGURATION.view_width * CONFIGURATION.grid_width | 128 | width = CONFIGURATION.view_width * CONFIGURATION.grid_width |
129 | ) | 129 | ) |
130 | }; | 130 | }; |
@@ -226,7 +226,7 @@ impl View for App { | |||
226 | let view_height = CONFIGURATION.view_height; | 226 | let view_height = CONFIGURATION.view_height; |
227 | let width = { | 227 | let width = { |
228 | if self.habits.len() > 0 { | 228 | if self.habits.len() > 0 { |
229 | grid_width * view_width | 229 | grid_width * (view_width + 2) |
230 | } else { | 230 | } else { |
231 | 0 | 231 | 0 |
232 | } | 232 | } |
@@ -283,6 +283,29 @@ impl View for App { | |||
283 | self.save_state(); | 283 | self.save_state(); |
284 | return EventResult::with_cb(|s| s.quit()); | 284 | return EventResult::with_cb(|s| s.quit()); |
285 | } | 285 | } |
286 | Event::Char('v') => { | ||
287 | if self.habits.is_empty() { | ||
288 | return EventResult::Consumed(None); | ||
289 | } | ||
290 | if self.habits[self.focus].view_mode() == ViewMode::Month { | ||
291 | self.set_mode(ViewMode::Day) | ||
292 | } else { | ||
293 | self.set_mode(ViewMode::Month) | ||
294 | } | ||
295 | return EventResult::Consumed(None); | ||
296 | } | ||
297 | Event::Char('V') => { | ||
298 | for habit in self.habits.iter_mut() { | ||
299 | habit.set_view_mode(ViewMode::Month); | ||
300 | } | ||
301 | return EventResult::Consumed(None); | ||
302 | } | ||
303 | Event::Key(Key::Esc) => { | ||
304 | for habit in self.habits.iter_mut() { | ||
305 | habit.set_view_mode(ViewMode::Day); | ||
306 | } | ||
307 | return EventResult::Consumed(None); | ||
308 | } | ||
286 | 309 | ||
287 | /* We want sifting to be an app level function, | 310 | /* We want sifting to be an app level function, |
288 | * that later trickles down into each habit | 311 | * that later trickles down into each habit |
diff --git a/src/views.rs b/src/views.rs index 3e623a9..f5ba01b 100644 --- a/src/views.rs +++ b/src/views.rs | |||
@@ -7,7 +7,7 @@ use cursive::{Printer, Vec2}; | |||
7 | use chrono::prelude::*; | 7 | use chrono::prelude::*; |
8 | use chrono::{Duration, Local, NaiveDate}; | 8 | use chrono::{Duration, Local, NaiveDate}; |
9 | 9 | ||
10 | use crate::habit::{Bit, Count, Habit, TrackEvent}; | 10 | use crate::habit::{Bit, Count, Habit, TrackEvent, ViewMode}; |
11 | 11 | ||
12 | use crate::CONFIGURATION; | 12 | use crate::CONFIGURATION; |
13 | 13 | ||
@@ -63,37 +63,64 @@ where | |||
63 | }, | 63 | }, |
64 | ); | 64 | ); |
65 | 65 | ||
66 | // fn draw_day(&self, p: &Printer) { }; | 66 | let draw_month = |printer: &Printer| { |
67 | // fn draw_month(&self, p: &Printer) {}; | 67 | let days = (1..31) |
68 | 68 | .map(|i| NaiveDate::from_ymd_opt(year, month, i)) | |
69 | // match self.view_mode() { | 69 | .flatten() // dates 28-31 may not exist, ignore them if they don't |
70 | // ViewMode::Day => draw_day(self, p), | 70 | .collect::<Vec<_>>(); |
71 | // ViewMode::Month => | 71 | for (week, line_nr) in days.chunks(7).zip(2..) { |
72 | // } | 72 | let weekly_goal = self.goal() * week.len() as u32; |
73 | 73 | let is_this_week = week.contains(&Local::now().naive_utc().date()); | |
74 | //let draw_day = |printer: &Printer| { | 74 | let remaining = week.iter().map(|&i| self.remaining(i)).sum::<u32>(); |
75 | let mut i = 1; | 75 | let completions = weekly_goal - remaining; |
76 | while let Some(d) = NaiveDate::from_ymd_opt(year, month, i) { | 76 | let full = CONFIGURATION.view_width - 8; |
77 | let day_style; | 77 | let bars_to_fill = (completions * full as u32) / weekly_goal; |
78 | if self.reached_goal(d) { | 78 | let percentage = (completions as f64 * 100f64) / weekly_goal as f64; |
79 | day_style = goal_reached_style; | ||
80 | } else { | ||
81 | day_style = todo_style; | ||
82 | } | ||
83 | let coords: Vec2 = ((i % 7) * 3, i / 7 + 2).into(); | ||
84 | if let Some(c) = self.get_by_date(d) { | ||
85 | printer.with_style(day_style, |p| { | ||
86 | p.print(coords, &format!("{:^3}", c)); | ||
87 | }); | ||
88 | } else { | ||
89 | printer.with_style(future_style, |p| { | 79 | printer.with_style(future_style, |p| { |
90 | p.print(coords, &format!("{:^3}", CONFIGURATION.future_chr)); | 80 | p.print((4, line_nr), &"―".repeat(full)); |
81 | }); | ||
82 | printer.with_style(goal_reached_style, |p| { | ||
83 | p.print((4, line_nr), &"―".repeat(bars_to_fill as usize)); | ||
91 | }); | 84 | }); |
85 | printer.with_style( | ||
86 | if is_this_week { | ||
87 | Style::none() | ||
88 | } else { | ||
89 | future_style | ||
90 | }, | ||
91 | |p| { | ||
92 | p.print((0, line_nr), &format!("{:3.0}% ", percentage)); | ||
93 | }, | ||
94 | ); | ||
92 | } | 95 | } |
93 | i += 1; | 96 | }; |
94 | } | 97 | let draw_day = |printer: &Printer| { |
95 | //}; | 98 | let mut i = 1; |
96 | //draw_day(printer); | 99 | while let Some(d) = NaiveDate::from_ymd_opt(year, month, i) { |
100 | let day_style; | ||
101 | if self.reached_goal(d) { | ||
102 | day_style = goal_reached_style; | ||
103 | } else { | ||
104 | day_style = todo_style; | ||
105 | } | ||
106 | let coords: Vec2 = ((i % 7) * 3, i / 7 + 2).into(); | ||
107 | if let Some(c) = self.get_by_date(d) { | ||
108 | printer.with_style(day_style, |p| { | ||
109 | p.print(coords, &format!("{:^3}", c)); | ||
110 | }); | ||
111 | } else { | ||
112 | printer.with_style(future_style, |p| { | ||
113 | p.print(coords, &format!("{:^3}", CONFIGURATION.future_chr)); | ||
114 | }); | ||
115 | } | ||
116 | i += 1; | ||
117 | } | ||
118 | }; | ||
119 | match self.view_mode() { | ||
120 | ViewMode::Day => draw_day(printer), | ||
121 | ViewMode::Month => draw_month(printer), | ||
122 | _ => draw_day(printer), | ||
123 | }; | ||
97 | } | 124 | } |
98 | 125 | ||
99 | fn required_size(&mut self, _: Vec2) -> Vec2 { | 126 | fn required_size(&mut self, _: Vec2) -> Vec2 { |