menu: appearance + controls (#22)
This commit is contained in:
parent
c9b444e91a
commit
98ee2bc16b
36
src/app.rs
36
src/app.rs
@ -7,7 +7,7 @@ use crate::{
|
|||||||
widgets::{
|
widgets::{
|
||||||
clock::{self, Clock, ClockArgs, Style},
|
clock::{self, Clock, ClockArgs, Style},
|
||||||
countdown::{Countdown, CountdownWidget},
|
countdown::{Countdown, CountdownWidget},
|
||||||
footer::Footer,
|
footer::{Footer, FooterArgs},
|
||||||
header::Header,
|
header::Header,
|
||||||
pomodoro::{Mode as PomodoroMode, Pomodoro, PomodoroArgs, PomodoroWidget},
|
pomodoro::{Mode as PomodoroMode, Pomodoro, PomodoroArgs, PomodoroWidget},
|
||||||
timer::{Timer, TimerWidget},
|
timer::{Timer, TimerWidget},
|
||||||
@ -59,6 +59,7 @@ pub struct App {
|
|||||||
pub struct AppArgs {
|
pub struct AppArgs {
|
||||||
pub style: Style,
|
pub style: Style,
|
||||||
pub with_decis: bool,
|
pub with_decis: bool,
|
||||||
|
pub show_menu: bool,
|
||||||
pub content: Content,
|
pub content: Content,
|
||||||
pub pomodoro_mode: PomodoroMode,
|
pub pomodoro_mode: PomodoroMode,
|
||||||
pub initial_value_work: Duration,
|
pub initial_value_work: Duration,
|
||||||
@ -76,6 +77,7 @@ impl From<(Args, AppStorage)> for AppArgs {
|
|||||||
fn from((args, stg): (Args, AppStorage)) -> Self {
|
fn from((args, stg): (Args, AppStorage)) -> Self {
|
||||||
AppArgs {
|
AppArgs {
|
||||||
with_decis: args.decis || stg.with_decis,
|
with_decis: args.decis || stg.with_decis,
|
||||||
|
show_menu: stg.show_menu,
|
||||||
content: args.mode.unwrap_or(stg.content),
|
content: args.mode.unwrap_or(stg.content),
|
||||||
style: args.style.unwrap_or(stg.style),
|
style: args.style.unwrap_or(stg.style),
|
||||||
pomodoro_mode: stg.pomodoro_mode,
|
pomodoro_mode: stg.pomodoro_mode,
|
||||||
@ -94,6 +96,7 @@ impl App {
|
|||||||
pub fn new(args: AppArgs) -> Self {
|
pub fn new(args: AppArgs) -> Self {
|
||||||
let AppArgs {
|
let AppArgs {
|
||||||
style,
|
style,
|
||||||
|
show_menu,
|
||||||
initial_value_work,
|
initial_value_work,
|
||||||
initial_value_pause,
|
initial_value_pause,
|
||||||
initial_value_countdown,
|
initial_value_countdown,
|
||||||
@ -108,7 +111,7 @@ impl App {
|
|||||||
Self {
|
Self {
|
||||||
mode: Mode::Running,
|
mode: Mode::Running,
|
||||||
content,
|
content,
|
||||||
show_menu: false,
|
show_menu,
|
||||||
style,
|
style,
|
||||||
with_decis,
|
with_decis,
|
||||||
countdown: Countdown::new(Clock::<clock::Countdown>::new(ClockArgs {
|
countdown: Countdown::new(Clock::<clock::Countdown>::new(ClockArgs {
|
||||||
@ -163,6 +166,22 @@ impl App {
|
|||||||
self.mode != Mode::Quit
|
self.mode != Mode::Quit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_edit_mode(&mut self) -> bool {
|
||||||
|
match self.content {
|
||||||
|
Content::Countdown => self.countdown.get_clock().clone().is_edit_mode(),
|
||||||
|
Content::Timer => self.timer.get_clock().clone().is_edit_mode(),
|
||||||
|
Content::Pomodoro => self.pomodoro.get_clock().is_edit_mode(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clock_is_running(&mut self) -> bool {
|
||||||
|
match self.content {
|
||||||
|
Content::Countdown => self.countdown.get_clock().clone().is_running(),
|
||||||
|
Content::Timer => self.timer.get_clock().clone().is_running(),
|
||||||
|
Content::Pomodoro => self.pomodoro.get_clock().is_running(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_key_event(&mut self, key: KeyEvent) {
|
fn handle_key_event(&mut self, key: KeyEvent) {
|
||||||
debug!("Received key {:?}", key.code);
|
debug!("Received key {:?}", key.code);
|
||||||
match key.code {
|
match key.code {
|
||||||
@ -234,12 +253,21 @@ impl StatefulWidget for AppWidget {
|
|||||||
let vertical = Layout::vertical([
|
let vertical = Layout::vertical([
|
||||||
Constraint::Length(1),
|
Constraint::Length(1),
|
||||||
Constraint::Percentage(100),
|
Constraint::Percentage(100),
|
||||||
Constraint::Length(if state.show_menu { 2 } else { 1 }),
|
Constraint::Length(if state.show_menu { 5 } else { 1 }),
|
||||||
]);
|
]);
|
||||||
let [v0, v1, v2] = vertical.areas(area);
|
let [v0, v1, v2] = vertical.areas(area);
|
||||||
|
|
||||||
|
// header
|
||||||
Header::new(true).render(v0, buf);
|
Header::new(true).render(v0, buf);
|
||||||
|
// content
|
||||||
self.render_content(v1, buf, state);
|
self.render_content(v1, buf, state);
|
||||||
Footer::new(state.show_menu, state.content).render(v2, buf);
|
// footer
|
||||||
|
Footer::new(FooterArgs {
|
||||||
|
show_menu: state.show_menu,
|
||||||
|
running_clock: state.clock_is_running(),
|
||||||
|
selected_content: state.content,
|
||||||
|
edit_mode: state.is_edit_mode(),
|
||||||
|
})
|
||||||
|
.render(v2, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -211,6 +211,10 @@ impl<T> Clock<T> {
|
|||||||
&self.mode
|
&self.mode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_running(&self) -> bool {
|
||||||
|
self.mode == Mode::Tick
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_edit_mode(&mut self) -> bool {
|
pub fn is_edit_mode(&mut self) -> bool {
|
||||||
matches!(self.mode, Mode::Editable(_, _))
|
matches!(self.mode, Mode::Editable(_, _))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,21 +7,38 @@ use ratatui::{
|
|||||||
style::{Modifier, Style},
|
style::{Modifier, Style},
|
||||||
symbols,
|
symbols,
|
||||||
text::{Line, Span},
|
text::{Line, Span},
|
||||||
widgets::{Block, Borders, Widget},
|
widgets::{Block, Borders, Cell, Row, Table, Widget},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Footer {
|
pub struct Footer {
|
||||||
show_menu: bool,
|
show_menu: bool,
|
||||||
|
running_clock: bool,
|
||||||
selected_content: Content,
|
selected_content: Content,
|
||||||
content_labels: BTreeMap<Content, String>,
|
content_labels: BTreeMap<Content, String>,
|
||||||
|
edit_mode: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FooterArgs {
|
||||||
|
pub show_menu: bool,
|
||||||
|
pub running_clock: bool,
|
||||||
|
pub selected_content: Content,
|
||||||
|
pub edit_mode: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Footer {
|
impl Footer {
|
||||||
pub fn new(show_menu: bool, selected_content: Content) -> Self {
|
pub fn new(args: FooterArgs) -> Self {
|
||||||
|
let FooterArgs {
|
||||||
|
show_menu,
|
||||||
|
running_clock,
|
||||||
|
selected_content,
|
||||||
|
edit_mode,
|
||||||
|
} = args;
|
||||||
Self {
|
Self {
|
||||||
show_menu,
|
show_menu,
|
||||||
|
running_clock,
|
||||||
selected_content,
|
selected_content,
|
||||||
|
edit_mode,
|
||||||
content_labels: BTreeMap::from([
|
content_labels: BTreeMap::from([
|
||||||
(Content::Countdown, "[c]ountdown".into()),
|
(Content::Countdown, "[c]ountdown".into()),
|
||||||
(Content::Timer, "[t]imer".into()),
|
(Content::Timer, "[t]imer".into()),
|
||||||
@ -34,7 +51,7 @@ impl Footer {
|
|||||||
impl Widget for Footer {
|
impl Widget for Footer {
|
||||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||||
let [border_area, menu_area] =
|
let [border_area, menu_area] =
|
||||||
Layout::vertical([Constraint::Length(1), Constraint::Fill(0)]).areas(area);
|
Layout::vertical([Constraint::Length(2), Constraint::Percentage(100)]).areas(area);
|
||||||
Block::new()
|
Block::new()
|
||||||
.borders(Borders::TOP)
|
.borders(Borders::TOP)
|
||||||
.title(format! {"[m]enu {:} ", if self.show_menu {"↓"} else {"↑"}})
|
.title(format! {"[m]enu {:} ", if self.show_menu {"↓"} else {"↑"}})
|
||||||
@ -42,12 +59,7 @@ impl Widget for Footer {
|
|||||||
.render(border_area, buf);
|
.render(border_area, buf);
|
||||||
// show menu
|
// show menu
|
||||||
if self.show_menu {
|
if self.show_menu {
|
||||||
let [title_area, labels_area] =
|
let content_labels: Vec<Span> = self
|
||||||
Layout::horizontal([Constraint::Length(12), Constraint::Fill(0)]).areas(menu_area);
|
|
||||||
|
|
||||||
Span::styled("screens", Style::default().add_modifier(Modifier::BOLD))
|
|
||||||
.render(title_area, buf);
|
|
||||||
let spans: Vec<Span> = self
|
|
||||||
.content_labels
|
.content_labels
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
@ -65,7 +77,74 @@ impl Widget for Footer {
|
|||||||
Span::styled(label, style)
|
Span::styled(label, style)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
Line::from(spans).render(labels_area, buf);
|
|
||||||
|
const SPACE: &str = " ";
|
||||||
|
let widths = [Constraint::Length(12), Constraint::Percentage(100)];
|
||||||
|
Table::new(
|
||||||
|
[
|
||||||
|
// content
|
||||||
|
Row::new(vec![
|
||||||
|
Cell::from(Span::styled(
|
||||||
|
"screens",
|
||||||
|
Style::default().add_modifier(Modifier::BOLD),
|
||||||
|
)),
|
||||||
|
Cell::from(Line::from(content_labels)),
|
||||||
|
]),
|
||||||
|
// format
|
||||||
|
Row::new(vec![
|
||||||
|
Cell::from(Span::styled(
|
||||||
|
"appearance",
|
||||||
|
Style::default().add_modifier(Modifier::BOLD),
|
||||||
|
)),
|
||||||
|
Cell::from(Line::from(vec![
|
||||||
|
Span::from("[,]change style"),
|
||||||
|
Span::from(SPACE),
|
||||||
|
Span::from("[.]toggle deciseconds"),
|
||||||
|
])),
|
||||||
|
]),
|
||||||
|
// edit
|
||||||
|
Row::new(vec![
|
||||||
|
Cell::from(Span::styled(
|
||||||
|
"controls",
|
||||||
|
Style::default().add_modifier(Modifier::BOLD),
|
||||||
|
)),
|
||||||
|
Cell::from(Line::from({
|
||||||
|
if self.edit_mode {
|
||||||
|
vec![
|
||||||
|
Span::from("[e]dit done"),
|
||||||
|
Span::from(SPACE),
|
||||||
|
Span::from("[← →]edit selection"),
|
||||||
|
Span::from(SPACE),
|
||||||
|
Span::from("[↑]edit up"),
|
||||||
|
Span::from(SPACE),
|
||||||
|
Span::from("[↓]edit down"),
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
let mut spans = vec![
|
||||||
|
Span::from(if self.running_clock {
|
||||||
|
"[s]top"
|
||||||
|
} else {
|
||||||
|
"[s]tart"
|
||||||
|
}),
|
||||||
|
Span::from(SPACE),
|
||||||
|
Span::from("[r]eset"),
|
||||||
|
Span::from(SPACE),
|
||||||
|
Span::from("[e]dit"),
|
||||||
|
];
|
||||||
|
if self.selected_content == Content::Pomodoro {
|
||||||
|
spans.extend_from_slice(&[
|
||||||
|
Span::from(SPACE),
|
||||||
|
Span::from("[← →]switch work/pause"),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
spans
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
widths,
|
||||||
|
)
|
||||||
|
.render(menu_area, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user