aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs137
1 files changed, 111 insertions, 26 deletions
diff --git a/src/main.rs b/src/main.rs
index a9ea9b1..3d819d2 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -5,8 +5,8 @@ use std::f64;
5 5
6use cursive::direction::Direction; 6use cursive::direction::Direction;
7use cursive::event::{Event, EventResult, Key}; 7use cursive::event::{Event, EventResult, Key};
8use cursive::view::View; 8use cursive::view::{View, ViewWrapper};
9use cursive::views::{Dialog, EditView, LinearLayout, ListView, SelectView}; 9//use cursive::views::{Dialog, EditView, LinearLayout, ListView, SelectView};
10use cursive::Cursive; 10use cursive::Cursive;
11use cursive::{Printer, Vec2}; 11use cursive::{Printer, Vec2};
12 12
@@ -27,9 +27,9 @@ enum ViewMode {
27 27
28struct App { 28struct App {
29 habits: Vec<HabitView>, 29 habits: Vec<HabitView>,
30 status: String,
31 view_mode: ViewMode, 30 view_mode: ViewMode,
32 focus: usize, 31 focus: usize,
32 grid_width: usize,
33 33
34 padding: usize, 34 padding: usize,
35} 35}
@@ -38,27 +38,55 @@ impl App {
38 fn new() -> Self { 38 fn new() -> Self {
39 return App { 39 return App {
40 habits: vec![], 40 habits: vec![],
41 status: "".to_string(),
42 view_mode: ViewMode::Day, 41 view_mode: ViewMode::Day,
43 focus: 0, 42 focus: 0,
44 padding: 2, 43 grid_width: 3,
44 padding: 12,
45 }; 45 };
46 } 46 }
47 fn add_habit(&mut self, h: HabitView) -> &mut Self { 47 fn add_habit(mut self, h: HabitView) -> Self {
48 self.habits.push(h); 48 self.habits.push(h);
49 return self; 49 return self;
50 } 50 }
51 fn set_mode(&mut self, set_mode: ViewMode) -> &mut Self { 51 fn set_mode(mut self, set_mode: ViewMode) -> Self {
52 if set_mode != self.view_mode { 52 if set_mode != self.view_mode {
53 self.view_mode = set_mode 53 self.view_mode = set_mode
54 } 54 }
55 return self; 55 return self;
56 } 56 }
57} 57 fn focus_right(&mut self) {
58 58 if self.focus != self.habits.len() - 1 {
59impl View for App { 59 self.focus += 1;
60 fn draw(&self, printer: &Printer) { 60 }
61 let grid_width = 3; 61 }
62 fn focus_left(&mut self) {
63 if self.focus != 0 {
64 self.focus -= 1;
65 }
66 }
67 fn focus_down(&mut self) {
68 if self.focus + self.grid_width < self.habits.len() - 1 {
69 self.focus += self.grid_width;
70 } else {
71 self.focus = self.habits.len() - 1;
72 }
73 }
74 fn focus_up(&mut self) {
75 if self.focus as isize - self.grid_width as isize >= 0 {
76 self.focus -= self.grid_width;
77 } else {
78 self.focus = 0;
79 }
80 }
81 fn status(&self) -> String {
82 return format!(
83 "{} total, {} remaining",
84 self.habits.iter().map(|h| h.total()).sum::<u32>(),
85 self.habits.iter().map(|h| h.remaining()).sum::<u32>()
86 );
87 }
88 fn max_size(&self) -> Vec2 {
89 let grid_width = self.grid_width;
62 let width = { 90 let width = {
63 if self.habits.len() > 0 { 91 if self.habits.len() > 0 {
64 grid_width * self.habits[0].get_size().x 92 grid_width * self.habits[0].get_size().x
@@ -68,27 +96,77 @@ impl View for App {
68 }; 96 };
69 let height = { 97 let height = {
70 if self.habits.len() > 0 { 98 if self.habits.len() > 0 {
71 (self.habits[0].get_size().y as f64 / grid_width as f64).ceil() as usize 99 (self.habits[0].get_size().y as f64
100 * (self.habits.len() as f64 / grid_width as f64).ceil())
101 as usize
72 } else { 102 } else {
73 0 103 0
74 } 104 }
75 }; 105 };
76 let mut offset = Vec2::new(width + self.padding, height + self.padding); 106 Vec2::new(width, height)
107 }
108}
109
110impl cursive::view::View for App {
111 fn draw(&self, printer: &Printer) {
112 let grid_width = self.grid_width;
113 let mut offset = Vec2::zero();
77 for (idx, i) in self.habits.iter().enumerate() { 114 for (idx, i) in self.habits.iter().enumerate() {
115 if idx >= grid_width && idx % grid_width == 0 {
116 offset = offset.map_y(|y| y + i.get_size().y).map_x(|_| 0);
117 }
78 i.draw(&printer.offset(offset).focused(self.focus == idx)); 118 i.draw(&printer.offset(offset).focused(self.focus == idx));
79 offset = offset.saturating_add(i.get_size()); 119 offset = offset.map_x(|x| x + i.get_size().x);
80 } 120 }
121 offset = offset.map_x(|_| 0).map_y(|_| self.max_size().y - 2);
122 printer.print(offset, &self.status());
81 } 123 }
124
82 fn required_size(&mut self, _: Vec2) -> Vec2 { 125 fn required_size(&mut self, _: Vec2) -> Vec2 {
83 todo!() 126 let grid_width = self.grid_width;
127 let width = {
128 if self.habits.len() > 0 {
129 grid_width * self.habits[0].get_size().x
130 } else {
131 0
132 }
133 };
134 let height = {
135 if self.habits.len() > 0 {
136 (self.habits[0].get_size().y as f64
137 * (self.habits.len() as f64 / grid_width as f64).ceil())
138 as usize
139 } else {
140 0
141 }
142 };
143 Vec2::new(width, height)
84 } 144 }
85 145
86 fn take_focus(&mut self, _: Direction) -> bool { 146 fn take_focus(&mut self, _: Direction) -> bool {
87 todo!() 147 false
88 } 148 }
89 149
90 fn on_event(&mut self, e: Event) -> EventResult { 150 fn on_event(&mut self, e: Event) -> EventResult {
91 todo!() 151 match e {
152 Event::Key(Key::Right) | Event::Key(Key::Tab) | Event::Char('l') => {
153 self.focus_right();
154 return EventResult::Consumed(None);
155 }
156 Event::Key(Key::Left) | Event::Shift(Key::Tab) | Event::Char('h') => {
157 self.focus_left();
158 return EventResult::Consumed(None);
159 }
160 Event::Key(Key::Up) | Event::Char('k') => {
161 self.focus_up();
162 return EventResult::Consumed(None);
163 }
164 Event::Key(Key::Down) | Event::Char('j') => {
165 self.focus_down();
166 return EventResult::Consumed(None);
167 }
168 _ => self.habits[self.focus].on_event(e),
169 }
92 } 170 }
93} 171}
94 172
@@ -109,18 +187,25 @@ fn main() {
109 reading.insert_entry(NaiveDate::from_ymd(2020, 2, 14), HabitType::Bit(false)); 187 reading.insert_entry(NaiveDate::from_ymd(2020, 2, 14), HabitType::Bit(false));
110 reading.insert_entry(NaiveDate::from_ymd(2020, 2, 15), HabitType::Bit(true)); 188 reading.insert_entry(NaiveDate::from_ymd(2020, 2, 15), HabitType::Bit(true));
111 189
112 let gym_title = gymming.get_name(); 190 let mut walking = Habit::new("walk", HabitType::Bit(true));
113 let gym_view = HabitView::new(gymming); 191 walking.insert_entry(NaiveDate::from_ymd(2020, 2, 11), HabitType::Bit(true));
192 walking.insert_entry(NaiveDate::from_ymd(2020, 2, 12), HabitType::Bit(false));
193 walking.insert_entry(NaiveDate::from_ymd(2020, 2, 13), HabitType::Bit(true));
194 walking.insert_entry(NaiveDate::from_ymd(2020, 2, 14), HabitType::Bit(false));
195 walking.insert_entry(NaiveDate::from_ymd(2020, 2, 15), HabitType::Bit(true));
114 196
115 let read_title = reading.get_name(); 197 let gym_view = HabitView::new(gymming);
116 let read_view = HabitView::new(reading); 198 let read_view = HabitView::new(reading);
199 let walk_view = HabitView::new(walking);
117 200
118 s.add_global_callback('q', |a| a.quit()); 201 s.add_global_callback('q', |a| a.quit());
119 s.add_layer( 202 let app = App::new()
120 LinearLayout::horizontal() 203 .add_habit(gym_view)
121 .child(Dialog::around(gym_view).title(gym_title)) 204 .add_habit(read_view)
122 .child(Dialog::around(read_view).title(read_title)), 205 .add_habit(walk_view)
123 ); 206 .set_mode(ViewMode::Month);
207
208 s.add_layer(app);
124 209
125 s.set_theme(theme::theme_gen()); 210 s.set_theme(theme::theme_gen());
126 s.run(); 211 s.run();