mirror of
https://github.com/kdheepak/taskwarrior-tui.git
synced 2025-08-26 03:07:18 +02:00
feat: Implement scrollbar
This commit is contained in:
parent
94bab20adc
commit
f4a48fad90
5 changed files with 103 additions and 6 deletions
|
@ -26,6 +26,9 @@ uda.taskwarrior-tui.task-report.prompt-on-done=false
|
||||||
uda.taskwarrior-tui.style.report.selection=
|
uda.taskwarrior-tui.style.report.selection=
|
||||||
uda.taskwarrior-tui.style.context.active=black on rgb444
|
uda.taskwarrior-tui.style.context.active=black on rgb444
|
||||||
uda.taskwarrior-tui.style.calendar.title=black on rgb444
|
uda.taskwarrior-tui.style.calendar.title=black on rgb444
|
||||||
|
uda.taskwarrior-tui.style.report.scrollbar=black
|
||||||
|
uda.taskwarrior-tui.style.report.scrollbar=black
|
||||||
|
uda.taskwarrior-tui.scrollbar.indicator=█
|
||||||
uda.taskwarrior-tui.task-report.next.filter=$(task show report.next.filter)
|
uda.taskwarrior-tui.task-report.next.filter=$(task show report.next.filter)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
12
src/app.rs
12
src/app.rs
|
@ -6,6 +6,7 @@ use crate::event::Key;
|
||||||
use crate::event::{Event, Events};
|
use crate::event::{Event, Events};
|
||||||
use crate::help::Help;
|
use crate::help::Help;
|
||||||
use crate::keyconfig::KeyConfig;
|
use crate::keyconfig::KeyConfig;
|
||||||
|
use crate::scrollbar::Scrollbar;
|
||||||
use crate::table::{Row, Table, TableMode, TableState};
|
use crate::table::{Row, Table, TableMode, TableState};
|
||||||
use crate::task_report::TaskReportTable;
|
use crate::task_report::TaskReportTable;
|
||||||
|
|
||||||
|
@ -25,6 +26,7 @@ use task_hookrs::date::Date;
|
||||||
use task_hookrs::import::import;
|
use task_hookrs::import::import;
|
||||||
use task_hookrs::status::TaskStatus;
|
use task_hookrs::status::TaskStatus;
|
||||||
use task_hookrs::task::Task;
|
use task_hookrs::task::Task;
|
||||||
|
use tui::symbols::bar::FULL;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use unicode_segmentation::Graphemes;
|
use unicode_segmentation::Graphemes;
|
||||||
|
@ -1158,10 +1160,12 @@ impl TaskwarriorTui {
|
||||||
let header = headers.iter();
|
let header = headers.iter();
|
||||||
let mut rows = vec![];
|
let mut rows = vec![];
|
||||||
let mut highlight_style = Style::default();
|
let mut highlight_style = Style::default();
|
||||||
|
let mut pos = 0;
|
||||||
for (i, task) in tasks.iter().enumerate() {
|
for (i, task) in tasks.iter().enumerate() {
|
||||||
let style = self.style_for_task(&self.tasks[i]);
|
let style = self.style_for_task(&self.tasks[i]);
|
||||||
if i == selected {
|
if i == selected {
|
||||||
highlight_style = style.patch(self.config.uda_report_style_selection);
|
pos = i;
|
||||||
|
highlight_style = style.patch(self.config.uda_style_report_selection);
|
||||||
if self.config.uda_selection_bold {
|
if self.config.uda_selection_bold {
|
||||||
highlight_style = highlight_style.add_modifier(Modifier::BOLD);
|
highlight_style = highlight_style.add_modifier(Modifier::BOLD);
|
||||||
}
|
}
|
||||||
|
@ -1216,6 +1220,12 @@ impl TaskwarriorTui {
|
||||||
.widths(&constraints);
|
.widths(&constraints);
|
||||||
|
|
||||||
f.render_stateful_widget(t, rect, &mut self.task_table_state);
|
f.render_stateful_widget(t, rect, &mut self.task_table_state);
|
||||||
|
if tasks.iter().len() as u16 > rect.height.saturating_sub(4) {
|
||||||
|
let mut widget = Scrollbar::new(pos, tasks.iter().len());
|
||||||
|
widget.pos_style = self.config.uda_style_report_scrollbar;
|
||||||
|
widget.pos_symbol = self.config.uda_scrollbar_indicator.clone();
|
||||||
|
f.render_widget(widget, rect);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_all_contexts(&self) -> (Vec<Vec<String>>, Vec<String>) {
|
pub fn get_all_contexts(&self) -> (Vec<Vec<String>>, Vec<String>) {
|
||||||
|
|
|
@ -3,7 +3,10 @@ use anyhow::{Context, Result};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::str;
|
use std::str;
|
||||||
use tui::style::{Color, Modifier, Style};
|
use tui::{
|
||||||
|
style::{Color, Modifier, Style},
|
||||||
|
symbols::bar::FULL,
|
||||||
|
};
|
||||||
|
|
||||||
trait TaskWarriorBool {
|
trait TaskWarriorBool {
|
||||||
fn get_bool(&self) -> Option<bool>;
|
fn get_bool(&self) -> Option<bool>;
|
||||||
|
@ -53,6 +56,8 @@ pub struct Config {
|
||||||
pub uda_selection_indicator: String,
|
pub uda_selection_indicator: String,
|
||||||
pub uda_mark_indicator: String,
|
pub uda_mark_indicator: String,
|
||||||
pub uda_unmark_indicator: String,
|
pub uda_unmark_indicator: String,
|
||||||
|
pub uda_scrollbar_indicator: String,
|
||||||
|
pub uda_style_report_scrollbar: Style,
|
||||||
pub uda_selection_bold: bool,
|
pub uda_selection_bold: bool,
|
||||||
pub uda_selection_italic: bool,
|
pub uda_selection_italic: bool,
|
||||||
pub uda_selection_dim: bool,
|
pub uda_selection_dim: bool,
|
||||||
|
@ -60,7 +65,7 @@ pub struct Config {
|
||||||
pub uda_selection_reverse: bool,
|
pub uda_selection_reverse: bool,
|
||||||
pub uda_calendar_months_per_row: usize,
|
pub uda_calendar_months_per_row: usize,
|
||||||
pub uda_style_context_active: Style,
|
pub uda_style_context_active: Style,
|
||||||
pub uda_report_style_selection: Style,
|
pub uda_style_report_selection: Style,
|
||||||
pub uda_style_calendar_title: Style,
|
pub uda_style_calendar_title: Style,
|
||||||
pub uda_style_calendar_today: Style,
|
pub uda_style_calendar_today: Style,
|
||||||
pub uda_style_report_completion_pane: Style,
|
pub uda_style_report_completion_pane: Style,
|
||||||
|
@ -96,13 +101,15 @@ impl Config {
|
||||||
let uda_selection_indicator = Self::get_uda_selection_indicator(data);
|
let uda_selection_indicator = Self::get_uda_selection_indicator(data);
|
||||||
let uda_mark_indicator = Self::get_uda_mark_indicator(data);
|
let uda_mark_indicator = Self::get_uda_mark_indicator(data);
|
||||||
let uda_unmark_indicator = Self::get_uda_unmark_indicator(data);
|
let uda_unmark_indicator = Self::get_uda_unmark_indicator(data);
|
||||||
|
let uda_scrollbar_indicator = Self::get_uda_scrollbar_indicator(data);
|
||||||
let uda_selection_bold = Self::get_uda_selection_bold(data);
|
let uda_selection_bold = Self::get_uda_selection_bold(data);
|
||||||
let uda_selection_italic = Self::get_uda_selection_italic(data);
|
let uda_selection_italic = Self::get_uda_selection_italic(data);
|
||||||
let uda_selection_dim = Self::get_uda_selection_dim(data);
|
let uda_selection_dim = Self::get_uda_selection_dim(data);
|
||||||
let uda_selection_blink = Self::get_uda_selection_blink(data);
|
let uda_selection_blink = Self::get_uda_selection_blink(data);
|
||||||
let uda_selection_reverse = Self::get_uda_selection_reverse(data);
|
let uda_selection_reverse = Self::get_uda_selection_reverse(data);
|
||||||
let uda_calendar_months_per_row = Self::get_uda_months_per_row(data);
|
let uda_calendar_months_per_row = Self::get_uda_months_per_row(data);
|
||||||
let uda_report_style_selection = Self::get_uda_style("report.selection", data);
|
let uda_style_report_selection = Self::get_uda_style("report.selection", data);
|
||||||
|
let uda_style_report_scrollbar = Self::get_uda_style("report.scrollbar", data);
|
||||||
let uda_style_calendar_title = Self::get_uda_style("calendar.title", data);
|
let uda_style_calendar_title = Self::get_uda_style("calendar.title", data);
|
||||||
let uda_style_calendar_today = Self::get_uda_style("calendar.today", data);
|
let uda_style_calendar_today = Self::get_uda_style("calendar.today", data);
|
||||||
let uda_style_context_active = Self::get_uda_style("context.active", data);
|
let uda_style_context_active = Self::get_uda_style("context.active", data);
|
||||||
|
@ -110,7 +117,9 @@ impl Config {
|
||||||
let uda_shortcuts = Self::get_uda_shortcuts(data);
|
let uda_shortcuts = Self::get_uda_shortcuts(data);
|
||||||
let uda_background_process = Self::get_uda_background_process(data);
|
let uda_background_process = Self::get_uda_background_process(data);
|
||||||
let uda_background_process_period = Self::get_uda_background_process_period(data);
|
let uda_background_process_period = Self::get_uda_background_process_period(data);
|
||||||
let uda_report_style_selection = uda_report_style_selection.unwrap_or_default();
|
let uda_style_report_selection = uda_style_report_selection.unwrap_or_default();
|
||||||
|
let uda_style_report_scrollbar =
|
||||||
|
uda_style_report_scrollbar.unwrap_or_else(|| Style::default().fg(Color::Black));
|
||||||
let uda_style_calendar_title = uda_style_calendar_title.unwrap_or_default();
|
let uda_style_calendar_title = uda_style_calendar_title.unwrap_or_default();
|
||||||
let uda_style_calendar_today =
|
let uda_style_calendar_today =
|
||||||
uda_style_calendar_today.unwrap_or_else(|| Style::default().add_modifier(Modifier::BOLD));
|
uda_style_calendar_today.unwrap_or_else(|| Style::default().add_modifier(Modifier::BOLD));
|
||||||
|
@ -140,17 +149,19 @@ impl Config {
|
||||||
uda_selection_indicator,
|
uda_selection_indicator,
|
||||||
uda_mark_indicator,
|
uda_mark_indicator,
|
||||||
uda_unmark_indicator,
|
uda_unmark_indicator,
|
||||||
|
uda_scrollbar_indicator,
|
||||||
uda_selection_bold,
|
uda_selection_bold,
|
||||||
uda_selection_italic,
|
uda_selection_italic,
|
||||||
uda_selection_dim,
|
uda_selection_dim,
|
||||||
uda_selection_blink,
|
uda_selection_blink,
|
||||||
uda_selection_reverse,
|
uda_selection_reverse,
|
||||||
uda_calendar_months_per_row,
|
uda_calendar_months_per_row,
|
||||||
uda_report_style_selection,
|
uda_style_report_selection,
|
||||||
uda_style_context_active,
|
uda_style_context_active,
|
||||||
uda_style_calendar_title,
|
uda_style_calendar_title,
|
||||||
uda_style_calendar_today,
|
uda_style_calendar_today,
|
||||||
uda_style_report_completion_pane,
|
uda_style_report_completion_pane,
|
||||||
|
uda_style_report_scrollbar,
|
||||||
uda_shortcuts,
|
uda_shortcuts,
|
||||||
uda_background_process,
|
uda_background_process,
|
||||||
uda_background_process_period,
|
uda_background_process_period,
|
||||||
|
@ -504,6 +515,19 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_uda_scrollbar_indicator(data: &str) -> String {
|
||||||
|
let indicator = Self::get_config("uda.taskwarrior-tui.scrollbar.indicator", data);
|
||||||
|
match indicator {
|
||||||
|
None => FULL.to_string(),
|
||||||
|
Some(indicator) => format!(
|
||||||
|
"{}",
|
||||||
|
indicator
|
||||||
|
.chars()
|
||||||
|
.next()
|
||||||
|
.unwrap_or_else(|| FULL.to_string().chars().next().unwrap())
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
fn get_uda_mark_highlight_indicator(data: &str) -> String {
|
fn get_uda_mark_highlight_indicator(data: &str) -> String {
|
||||||
let indicator = Self::get_config("uda.taskwarrior-tui.mark-selection.indicator", data);
|
let indicator = Self::get_config("uda.taskwarrior-tui.mark-selection.indicator", data);
|
||||||
match indicator {
|
match indicator {
|
||||||
|
|
|
@ -13,6 +13,7 @@ mod help;
|
||||||
mod history;
|
mod history;
|
||||||
mod keyconfig;
|
mod keyconfig;
|
||||||
mod pane;
|
mod pane;
|
||||||
|
mod scrollbar;
|
||||||
mod table;
|
mod table;
|
||||||
mod task_report;
|
mod task_report;
|
||||||
|
|
||||||
|
|
59
src/scrollbar.rs
Normal file
59
src/scrollbar.rs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
use tui::{
|
||||||
|
backend::Backend,
|
||||||
|
buffer::Buffer,
|
||||||
|
layout::{Margin, Rect},
|
||||||
|
style::{Color, Style},
|
||||||
|
symbols::{block::FULL, line::DOUBLE_VERTICAL},
|
||||||
|
widgets::Widget,
|
||||||
|
Frame,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Scrollbar {
|
||||||
|
pub pos: u16,
|
||||||
|
pub len: u16,
|
||||||
|
pub pos_style: Style,
|
||||||
|
pub pos_symbol: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Scrollbar {
|
||||||
|
pub fn new(pos: usize, len: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
pos: pos as u16,
|
||||||
|
len: len as u16,
|
||||||
|
pos_style: Style::default(),
|
||||||
|
pos_symbol: FULL.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for Scrollbar {
|
||||||
|
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||||
|
if area.height <= 2 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.len == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let right = area.right().saturating_sub(1);
|
||||||
|
|
||||||
|
if right <= area.left() {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let (top, height) = { (area.top() + 3, area.height.saturating_sub(4)) };
|
||||||
|
|
||||||
|
for y in top..(top + height) {
|
||||||
|
buf.set_string(right, y, DOUBLE_VERTICAL, Style::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
let progress = self.pos as f64 / self.len as f64;
|
||||||
|
let progress = if progress > 1.0 { 1.0 } else { progress };
|
||||||
|
let pos = height as f64 * progress;
|
||||||
|
|
||||||
|
let pos = pos as i64 as u16;
|
||||||
|
|
||||||
|
buf.set_string(right, top + pos, self.pos_symbol, self.pos_style);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue