diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/app.rs | 169 | ||||
-rw-r--r-- | src/main.rs | 159 |
2 files changed, 171 insertions, 157 deletions
diff --git a/src/app.rs b/src/app.rs new file mode 100644 index 0000000..c43a43e --- /dev/null +++ b/src/app.rs | |||
@@ -0,0 +1,169 @@ | |||
1 | use std::f64; | ||
2 | |||
3 | use cursive::direction::{Absolute, Direction}; | ||
4 | use cursive::event::{Event, EventResult, Key}; | ||
5 | use cursive::view::View; | ||
6 | use cursive::{Printer, Vec2}; | ||
7 | |||
8 | use crate::views::habitview::HabitView; | ||
9 | |||
10 | #[derive(PartialEq)] | ||
11 | pub enum ViewMode { | ||
12 | Day, | ||
13 | Month, | ||
14 | Year, | ||
15 | } | ||
16 | |||
17 | pub struct App { | ||
18 | habits: Vec<HabitView>, | ||
19 | view_mode: ViewMode, | ||
20 | focus: usize, | ||
21 | grid_width: usize, | ||
22 | |||
23 | padding: usize, | ||
24 | } | ||
25 | |||
26 | impl App { | ||
27 | pub fn new() -> Self { | ||
28 | return App { | ||
29 | habits: vec![], | ||
30 | view_mode: ViewMode::Day, | ||
31 | focus: 0, | ||
32 | grid_width: 3, | ||
33 | padding: 12, | ||
34 | }; | ||
35 | } | ||
36 | |||
37 | pub fn add_habit(mut self, h: HabitView) -> Self { | ||
38 | self.habits.push(h); | ||
39 | return self; | ||
40 | } | ||
41 | |||
42 | pub fn set_mode(mut self, set_mode: ViewMode) -> Self { | ||
43 | if set_mode != self.view_mode { | ||
44 | self.view_mode = set_mode | ||
45 | } | ||
46 | return self; | ||
47 | } | ||
48 | |||
49 | fn set_focus(&mut self, d: Absolute) { | ||
50 | match d { | ||
51 | Absolute::Right => { | ||
52 | if self.focus != self.habits.len() - 1 { | ||
53 | self.focus += 1; | ||
54 | } | ||
55 | } | ||
56 | Absolute::Left => { | ||
57 | if self.focus != 0 { | ||
58 | self.focus -= 1; | ||
59 | } | ||
60 | } | ||
61 | Absolute::Down => { | ||
62 | if self.focus + self.grid_width < self.habits.len() - 1 { | ||
63 | self.focus += self.grid_width; | ||
64 | } else { | ||
65 | self.focus = self.habits.len() - 1; | ||
66 | } | ||
67 | } | ||
68 | Absolute::Up => { | ||
69 | if self.focus as isize - self.grid_width as isize >= 0 { | ||
70 | self.focus -= self.grid_width; | ||
71 | } else { | ||
72 | self.focus = 0; | ||
73 | } | ||
74 | } | ||
75 | Absolute::None => {} | ||
76 | } | ||
77 | } | ||
78 | |||
79 | fn status(&self) -> String { | ||
80 | let remaining = self.habits.iter().map(|h| h.remaining()).sum::<u32>(); | ||
81 | let total = self.habits.iter().map(|h| h.total()).sum::<u32>(); | ||
82 | let completed = total - remaining; | ||
83 | |||
84 | return format!("{}/{} ", completed, total); | ||
85 | } | ||
86 | fn max_size(&self) -> Vec2 { | ||
87 | let grid_width = self.grid_width; | ||
88 | let width = { | ||
89 | if self.habits.len() > 0 { | ||
90 | grid_width * self.habits[0].get_size().x | ||
91 | } else { | ||
92 | 0 | ||
93 | } | ||
94 | }; | ||
95 | let height = { | ||
96 | if self.habits.len() > 0 { | ||
97 | (self.habits[0].get_size().y as f64 | ||
98 | * (self.habits.len() as f64 / grid_width as f64).ceil()) | ||
99 | as usize | ||
100 | } else { | ||
101 | 0 | ||
102 | } | ||
103 | }; | ||
104 | Vec2::new(width, height) | ||
105 | } | ||
106 | } | ||
107 | |||
108 | impl View for App { | ||
109 | fn draw(&self, printer: &Printer) { | ||
110 | let grid_width = self.grid_width; | ||
111 | let mut offset = Vec2::zero(); | ||
112 | for (idx, i) in self.habits.iter().enumerate() { | ||
113 | if idx >= grid_width && idx % grid_width == 0 { | ||
114 | offset = offset.map_y(|y| y + i.get_size().y).map_x(|_| 0); | ||
115 | } | ||
116 | i.draw(&printer.offset(offset).focused(self.focus == idx)); | ||
117 | offset = offset.map_x(|x| x + i.get_size().x); | ||
118 | } | ||
119 | offset = offset.map_x(|_| 0).map_y(|_| self.max_size().y - 2); | ||
120 | printer.print(offset, &self.status()); | ||
121 | } | ||
122 | |||
123 | fn required_size(&mut self, _: Vec2) -> Vec2 { | ||
124 | let grid_width = self.grid_width; | ||
125 | let width = { | ||
126 | if self.habits.len() > 0 { | ||
127 | grid_width * self.habits[0].get_size().x | ||
128 | } else { | ||
129 | 0 | ||
130 | } | ||
131 | }; | ||
132 | let height = { | ||
133 | if self.habits.len() > 0 { | ||
134 | (self.habits[0].get_size().y as f64 | ||
135 | * (self.habits.len() as f64 / grid_width as f64).ceil()) | ||
136 | as usize | ||
137 | } else { | ||
138 | 0 | ||
139 | } | ||
140 | }; | ||
141 | Vec2::new(width, height) | ||
142 | } | ||
143 | |||
144 | fn take_focus(&mut self, _: Direction) -> bool { | ||
145 | false | ||
146 | } | ||
147 | |||
148 | fn on_event(&mut self, e: Event) -> EventResult { | ||
149 | match e { | ||
150 | Event::Key(Key::Right) | Event::Key(Key::Tab) | Event::Char('l') => { | ||
151 | self.set_focus(Absolute::Right); | ||
152 | return EventResult::Consumed(None); | ||
153 | } | ||
154 | Event::Key(Key::Left) | Event::Shift(Key::Tab) | Event::Char('h') => { | ||
155 | self.set_focus(Absolute::Left); | ||
156 | return EventResult::Consumed(None); | ||
157 | } | ||
158 | Event::Key(Key::Up) | Event::Char('k') => { | ||
159 | self.set_focus(Absolute::Up); | ||
160 | return EventResult::Consumed(None); | ||
161 | } | ||
162 | Event::Key(Key::Down) | Event::Char('j') => { | ||
163 | self.set_focus(Absolute::Down); | ||
164 | return EventResult::Consumed(None); | ||
165 | } | ||
166 | _ => self.habits[self.focus].on_event(e), | ||
167 | } | ||
168 | } | ||
169 | } | ||
diff --git a/src/main.rs b/src/main.rs index 3d819d2..5115aab 100644 --- a/src/main.rs +++ b/src/main.rs | |||
@@ -1,14 +1,9 @@ | |||
1 | #![allow(unused_must_use)] | 1 | #![allow(unused_must_use)] |
2 | 2 | ||
3 | use chrono::NaiveDate; | 3 | use chrono::NaiveDate; |
4 | use std::f64; | ||
5 | 4 | ||
6 | use cursive::direction::Direction; | ||
7 | use cursive::event::{Event, EventResult, Key}; | ||
8 | use cursive::view::{View, ViewWrapper}; | ||
9 | //use cursive::views::{Dialog, EditView, LinearLayout, ListView, SelectView}; | 5 | //use cursive::views::{Dialog, EditView, LinearLayout, ListView, SelectView}; |
10 | use cursive::Cursive; | 6 | use cursive::Cursive; |
11 | use cursive::{Printer, Vec2}; | ||
12 | 7 | ||
13 | mod habit; | 8 | mod habit; |
14 | use crate::habit::{Habit, HabitTrait, HabitType}; | 9 | use crate::habit::{Habit, HabitTrait, HabitType}; |
@@ -16,159 +11,9 @@ use crate::habit::{Habit, HabitTrait, HabitType}; | |||
16 | mod views; | 11 | mod views; |
17 | use crate::views::habitview::HabitView; | 12 | use crate::views::habitview::HabitView; |
18 | 13 | ||
14 | mod app; | ||
19 | mod theme; | 15 | mod theme; |
20 | 16 | use crate::app::{App, ViewMode}; | |
21 | #[derive(PartialEq)] | ||
22 | enum ViewMode { | ||
23 | Day, | ||
24 | Month, | ||
25 | Year, | ||
26 | } | ||
27 | |||
28 | struct App { | ||
29 | habits: Vec<HabitView>, | ||
30 | view_mode: ViewMode, | ||
31 | focus: usize, | ||
32 | grid_width: usize, | ||
33 | |||
34 | padding: usize, | ||
35 | } | ||
36 | |||
37 | impl App { | ||
38 | fn new() -> Self { | ||
39 | return App { | ||
40 | habits: vec![], | ||
41 | view_mode: ViewMode::Day, | ||
42 | focus: 0, | ||
43 | grid_width: 3, | ||
44 | padding: 12, | ||
45 | }; | ||
46 | } | ||
47 | fn add_habit(mut self, h: HabitView) -> Self { | ||
48 | self.habits.push(h); | ||
49 | return self; | ||
50 | } | ||
51 | fn set_mode(mut self, set_mode: ViewMode) -> Self { | ||
52 | if set_mode != self.view_mode { | ||
53 | self.view_mode = set_mode | ||
54 | } | ||
55 | return self; | ||
56 | } | ||
57 | fn focus_right(&mut self) { | ||
58 | if self.focus != self.habits.len() - 1 { | ||
59 | self.focus += 1; | ||
60 | } | ||
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; | ||
90 | let width = { | ||
91 | if self.habits.len() > 0 { | ||
92 | grid_width * self.habits[0].get_size().x | ||
93 | } else { | ||
94 | 0 | ||
95 | } | ||
96 | }; | ||
97 | let height = { | ||
98 | if self.habits.len() > 0 { | ||
99 | (self.habits[0].get_size().y as f64 | ||
100 | * (self.habits.len() as f64 / grid_width as f64).ceil()) | ||
101 | as usize | ||
102 | } else { | ||
103 | 0 | ||
104 | } | ||
105 | }; | ||
106 | Vec2::new(width, height) | ||
107 | } | ||
108 | } | ||
109 | |||
110 | impl cursive::view::View for App { | ||
111 | fn draw(&self, printer: &Printer) { | ||
112 | let grid_width = self.grid_width; | ||
113 | let mut offset = Vec2::zero(); | ||
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 | } | ||
118 | i.draw(&printer.offset(offset).focused(self.focus == idx)); | ||
119 | offset = offset.map_x(|x| x + i.get_size().x); | ||
120 | } | ||
121 | offset = offset.map_x(|_| 0).map_y(|_| self.max_size().y - 2); | ||
122 | printer.print(offset, &self.status()); | ||
123 | } | ||
124 | |||
125 | fn required_size(&mut self, _: Vec2) -> Vec2 { | ||
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) | ||
144 | } | ||
145 | |||
146 | fn take_focus(&mut self, _: Direction) -> bool { | ||
147 | false | ||
148 | } | ||
149 | |||
150 | fn on_event(&mut self, e: Event) -> EventResult { | ||
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 | } | ||
170 | } | ||
171 | } | ||
172 | 17 | ||
173 | fn main() { | 18 | fn main() { |
174 | let mut s = Cursive::default(); | 19 | let mut s = Cursive::default(); |