Make calendar scrollable

This commit is contained in:
Dheepak Krishnamurthy 2020-10-22 00:40:55 -06:00
parent 0d750f4b01
commit 32a8a79455
2 changed files with 54 additions and 25 deletions

View file

@ -1,4 +1,6 @@
use crate::config::TConfig; use crate::config::TConfig;
use crate::calendar::Calendar;
use crate::table::{Row, Table, TableState};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::convert::TryInto; use std::convert::TryInto;
@ -14,7 +16,6 @@ use uuid::Uuid;
use chrono::{Datelike, Local, NaiveDateTime, TimeZone}; use chrono::{Datelike, Local, NaiveDateTime, TimeZone};
use crate::calendar::Calendar;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::{sync::mpsc, thread, time::Duration}; use std::{sync::mpsc, thread, time::Duration};
use tui::{ use tui::{
@ -26,8 +27,6 @@ use tui::{
widgets::{Block, Borders, Clear, Paragraph}, widgets::{Block, Borders, Clear, Paragraph},
}; };
use crate::table::{Row, Table, TableState};
use rustyline::error::ReadlineError; use rustyline::error::ReadlineError;
use rustyline::line_buffer::LineBuffer; use rustyline::line_buffer::LineBuffer;
use rustyline::At; use rustyline::At;
@ -359,6 +358,7 @@ pub struct TTApp {
pub error: String, pub error: String,
pub tasks: Arc<Mutex<Vec<Task>>>, pub tasks: Arc<Mutex<Vec<Task>>>,
pub task_report_table: TaskReportTable, pub task_report_table: TaskReportTable,
pub calendar_year: i32,
pub mode: AppMode, pub mode: AppMode,
pub config: TConfig, pub config: TConfig,
} }
@ -378,6 +378,7 @@ impl TTApp {
mode: AppMode::TaskReport, mode: AppMode::TaskReport,
config: TConfig::default(), config: TConfig::default(),
task_report_table: TaskReportTable::new(), task_report_table: TaskReportTable::new(),
calendar_year: Local::today().year(),
}; };
for c in "status:pending ".chars() { for c in "status:pending ".chars() {
app.filter.insert(c, 1); app.filter.insert(c, 1);
@ -439,10 +440,8 @@ impl TTApp {
.split(f.size()); .split(f.size());
let today = Local::today(); let today = Local::today();
let c = Calendar::default() let c = Calendar::default()
.block(Block::default().title("Calendar").borders(Borders::ALL)); .block(Block::default().title("Calendar").borders(Borders::ALL))
// let p = Paragraph::new(Text::from()) .year(self.calendar_year);
// .alignment(Alignment::Left)
// .block(Block::default().borders(Borders::ALL).title("Calendar"));
f.render_widget(c, rects[0]); f.render_widget(c, rects[0]);
} }
@ -1501,6 +1500,8 @@ impl TTApp {
Key::Char('[') => { Key::Char('[') => {
self.mode = AppMode::TaskReport; self.mode = AppMode::TaskReport;
} }
Key::Up | Key::Char('k') => self.calendar_year -= 1,
Key::Down | Key::Char('j') => self.calendar_year += 1,
Key::Ctrl('c') | Key::Char('q') => self.should_quit = true, Key::Ctrl('c') | Key::Char('q') => self.should_quit = true,
_ => {} _ => {}
}, },

View file

@ -22,24 +22,21 @@ use unicode_width::UnicodeWidthStr;
pub struct Calendar<'a> { pub struct Calendar<'a> {
pub block: Option<Block<'a>>, pub block: Option<Block<'a>>,
pub year: i32, pub year: i32,
pub days: Vec<(NaiveDate, NaiveDate)>, pub month: u32,
pub style: Style, pub style: Style,
pub months_per_row: usize, pub months_per_row: usize,
} }
impl<'a> Default for Calendar<'a> { impl<'a> Default for Calendar<'a> {
fn default() -> Calendar<'a> { fn default() -> Calendar<'a> {
let year = Local::today().year().into(); let year = Local::today().year();
let days: Vec<_> = (0..12).into_iter().map(|i| { let month = Local::today().month();
let first = NaiveDate::from_ymd(year, i+1, 1);
(first, first - Duration::days(first.weekday().num_days_from_sunday() as i64))
}).collect();
Calendar { Calendar {
block: None, block: None,
style: Default::default(), style: Default::default(),
months_per_row: 0, months_per_row: 0,
year, year,
days, month,
} }
} }
} }
@ -57,11 +54,11 @@ impl<'a> Calendar<'a> {
pub fn year(mut self, year: i32) -> Self { pub fn year(mut self, year: i32) -> Self {
self.year = year; self.year = year;
let days: Vec<_> = (0..12).into_iter().map(|i| { self
let first = NaiveDate::from_ymd(year, i+1, 1); }
(first, first - Duration::days(first.weekday().num_days_from_sunday() as i64))
}).collect(); pub fn month(mut self, month: u32) -> Self {
self.days = days; self.month = month;
self self
} }
} }
@ -101,18 +98,41 @@ impl <'a> Widget for Calendar<'a> {
let today = Local::today(); let today = Local::today();
let year = self.year; let year = self.year;
let month = self.month;
let months: Vec<_> = (0..12).collect(); let months: Vec<_> = (0..12).collect();
let mut startm = 0;
let mut days: Vec<_> = months.iter().map(|i| {
let first = NaiveDate::from_ymd(year, i+1, 1);
(first, first - Duration::days(first.weekday().num_days_from_sunday() as i64))
}).collect();
days.append(&mut months.iter().map(|i| {
let first = NaiveDate::from_ymd(year + 1, i+1, 1);
(first, first - Duration::days(first.weekday().num_days_from_sunday() as i64))
}).collect::<Vec<_>>()
);
days.append(&mut months.iter().map(|i| {
let first = NaiveDate::from_ymd(year + 2, i+1, 1);
(first, first - Duration::days(first.weekday().num_days_from_sunday() as i64))
}).collect::<Vec<_>>()
);
let mut startm = 0 as usize;
if self.months_per_row > area.width as usize / 8 / 3 || self.months_per_row <= 0 { if self.months_per_row > area.width as usize / 8 / 3 || self.months_per_row <= 0 {
self.months_per_row = area.width as usize / 8 / 3; self.months_per_row = area.width as usize / 8 / 3;
} }
let mut y = area.y; let mut y = area.y;
y += 1; y += 1;
let x = area.x; let x = area.x;
let s = format!("{year:^width$}", year = year, width = area.width as usize - 4); let s = format!("{year:^width$}", year = year, width = area.width as usize - 4);
buf.set_string(x, y, &s, Style::default().add_modifier(Modifier::BOLD)); buf.set_string(x, y, &s, Style::default().add_modifier(Modifier::BOLD));
let startx = (area.width - 3 * 7 * self.months_per_row as u16 - self.months_per_row as u16) / 2; let startx = (area.width - 3 * 7 * self.months_per_row as u16 - self.months_per_row as u16) / 2;
y += 2; y += 2;
let mut year = 0;
loop { loop {
let endm = std::cmp::min(startm + self.months_per_row, 12); let endm = std::cmp::min(startm + self.months_per_row, 12);
let mut x = area.x + startx; let mut x = area.x + startx;
@ -120,7 +140,7 @@ impl <'a> Widget for Calendar<'a> {
if c > startm { if c > startm {
x += 1; x += 1;
} }
let d = &mut self.days[c]; let d = &mut days[c];
let m = d.0.month() as usize; let m = d.0.month() as usize;
let s = format!("{:^21}", month_names[m - 1]); let s = format!("{:^21}", month_names[m - 1]);
buf.set_string(x, y, &s, Style::default()); buf.set_string(x, y, &s, Style::default());
@ -140,7 +160,7 @@ impl <'a> Widget for Calendar<'a> {
if c > startm { if c > startm {
x += 1; x += 1;
} }
let d = &mut self.days[c]; let d = &mut days[c + year * 12];
for _ in 0..7 { for _ in 0..7 {
let s = if d.0.month() == d.1.month() { let s = if d.0.month() == d.1.month() {
format!("{:>2}", d.1.day()) format!("{:>2}", d.1.day())
@ -163,8 +183,16 @@ impl <'a> Widget for Calendar<'a> {
} }
} }
startm += self.months_per_row; startm += self.months_per_row;
if startm >= 12 { y += 1;
return; if y + 8 > area.height {
break
} else if startm >= 12 {
startm = 0;
year += 1;
let x = area.x;
let s = format!("{year:^width$}", year = self.year as usize + year, width = area.width as usize - 4);
buf.set_string(x, y, &s, Style::default().add_modifier(Modifier::BOLD));
y += 1;
} }
y += 1; y += 1;
} }