database done + popup start
This commit is contained in:
commit
234b17a8b0
12 changed files with 1134 additions and 0 deletions
178
src/app.rs
Normal file
178
src/app.rs
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
use std::io;
|
||||
|
||||
use chrono::{Datelike, Local};
|
||||
use crossterm::event::{self, Event, KeyEvent, KeyEventKind};
|
||||
use ratatui::{
|
||||
DefaultTerminal, Frame,
|
||||
layout::{Constraint, Direction, Layout, Rect},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
database::DB, days::Days, events::AppEvent, focused::Focused, month::Month, popup::Popup,
|
||||
year::Year,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum FocusedComponent {
|
||||
Year,
|
||||
Month,
|
||||
Days,
|
||||
DayPopup,
|
||||
}
|
||||
|
||||
pub struct App {
|
||||
year: Year,
|
||||
month: Month,
|
||||
days: Days,
|
||||
day_popup: Popup,
|
||||
|
||||
focused: FocusedComponent,
|
||||
exit: bool,
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub fn new() -> Self {
|
||||
let mut app = App {
|
||||
year: Year::default(),
|
||||
month: Month::default(),
|
||||
days: Days::default(),
|
||||
day_popup: Popup::default(),
|
||||
|
||||
focused: FocusedComponent::DayPopup,
|
||||
exit: false,
|
||||
};
|
||||
|
||||
app.days
|
||||
.reload(app.month.month, app.year.year, Local::now().day() as i32);
|
||||
|
||||
app.get_focused_mut().take_focus();
|
||||
app
|
||||
}
|
||||
|
||||
fn get_focused_mut(&mut self) -> &mut dyn Focused {
|
||||
match self.focused {
|
||||
FocusedComponent::Year => &mut self.year,
|
||||
FocusedComponent::Month => &mut self.month,
|
||||
FocusedComponent::Days => &mut self.days,
|
||||
FocusedComponent::DayPopup => &mut self.day_popup,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn switch_focus(&mut self, new_focus: FocusedComponent) {
|
||||
if self.focused != new_focus {
|
||||
self.get_focused_mut().lose_focus();
|
||||
self.focused = new_focus;
|
||||
self.get_focused_mut().take_focus();
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_input(&mut self, key_event: KeyEvent, db: &mut DB) -> Option<Vec<AppEvent>> {
|
||||
let focused = self.get_focused_mut();
|
||||
focused.handle_input(key_event, db)
|
||||
}
|
||||
|
||||
pub fn run(&mut self, terminal: &mut DefaultTerminal) -> io::Result<()> {
|
||||
let mut db = DB::new().unwrap();
|
||||
|
||||
while !self.exit {
|
||||
terminal.draw(|frame| self.draw(frame))?;
|
||||
self.handle_events(&mut db)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw(&mut self, frame: &mut Frame) {
|
||||
let main_area = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints(vec![
|
||||
Constraint::Length(8),
|
||||
Constraint::Length(4),
|
||||
Constraint::Fill(1),
|
||||
])
|
||||
.split(frame.area());
|
||||
|
||||
let popup_area = Self::popup_rect(50, 50, frame.area());
|
||||
|
||||
if frame.area().width < 10 || frame.area().height < 30 {
|
||||
self.exit();
|
||||
return;
|
||||
}
|
||||
|
||||
self.year.ready_to_render(main_area[0]);
|
||||
self.month.ready_to_render(main_area[1]);
|
||||
self.days.ready_to_render(main_area[2]);
|
||||
self.day_popup.ready_to_render(popup_area);
|
||||
|
||||
frame.render_widget(&self.year, main_area[0]);
|
||||
frame.render_widget(&self.month, main_area[1]);
|
||||
frame.render_widget(&self.days, main_area[2]);
|
||||
|
||||
frame.render_widget(&self.day_popup, popup_area);
|
||||
}
|
||||
|
||||
fn popup_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect {
|
||||
let popup_layout = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([
|
||||
Constraint::Percentage((100 - percent_y) / 2),
|
||||
Constraint::Percentage(percent_y),
|
||||
Constraint::Percentage((100 - percent_y) / 2),
|
||||
])
|
||||
.split(r);
|
||||
|
||||
Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints([
|
||||
Constraint::Percentage((100 - percent_x) / 2),
|
||||
Constraint::Percentage(percent_x),
|
||||
Constraint::Percentage((100 - percent_x) / 2),
|
||||
])
|
||||
.split(popup_layout[1])[1]
|
||||
}
|
||||
|
||||
fn exit(&mut self) {
|
||||
self.exit = true;
|
||||
}
|
||||
|
||||
fn handle_events(&mut self, db: &mut DB) -> io::Result<()> {
|
||||
match event::read()? {
|
||||
Event::Key(key_event) if key_event.kind == KeyEventKind::Press => {
|
||||
let app_event_option = self.handle_input(key_event, db);
|
||||
|
||||
if let Some(app_event_vec) = app_event_option {
|
||||
for app_event in app_event_vec {
|
||||
match app_event {
|
||||
AppEvent::SwitchFocus(new_focus) => self.switch_focus(new_focus),
|
||||
AppEvent::Exit => self.exit(),
|
||||
AppEvent::YearScrolled(dir) => match dir {
|
||||
crate::events::Direction::Up => {
|
||||
self.year.plus_year();
|
||||
}
|
||||
crate::events::Direction::Down => {
|
||||
self.year.minus_year();
|
||||
}
|
||||
},
|
||||
AppEvent::MonthScrolled(dir) => match dir {
|
||||
crate::events::Direction::Up => {
|
||||
self.month.plus_month();
|
||||
}
|
||||
crate::events::Direction::Down => {
|
||||
self.month.minus_month();
|
||||
}
|
||||
},
|
||||
AppEvent::MonthSet(month) => {
|
||||
self.days.reload(month, self.year.year, 1);
|
||||
}
|
||||
AppEvent::YearSet(year) => {
|
||||
self.days.reload(self.month.month, year, 1);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue