mirror of
https://github.com/kdheepak/taskwarrior-tui.git
synced 2025-08-25 08:47:18 +02:00
Make calendar scrollable
This commit is contained in:
parent
0d750f4b01
commit
32a8a79455
2 changed files with 54 additions and 25 deletions
15
src/app.rs
15
src/app.rs
|
@ -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,
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
|
|
|
@ -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());
|
||||||
|
@ -129,7 +149,7 @@ impl <'a> Widget for Calendar<'a> {
|
||||||
y += 1;
|
y += 1;
|
||||||
let mut x = area.x + startx;
|
let mut x = area.x + startx;
|
||||||
for c in startm..endm {
|
for c in startm..endm {
|
||||||
buf.set_string(x as u16, y, " Su Mo Tu We Th Fr Sa", Style::default());
|
buf.set_string(x as u16, y, "Su Mo Tu We Th Fr Sa", Style::default());
|
||||||
x += 21 + 1;
|
x += 21 + 1;
|
||||||
}
|
}
|
||||||
y += 1;
|
y += 1;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue