parent
acb627b1d7
commit
ae1a48e5e8
27
src/app.rs
27
src/app.rs
@ -8,6 +8,7 @@ use crate::{
|
||||
clock::{self, Clock, ClockArgs, Style},
|
||||
countdown::{Countdown, CountdownWidget},
|
||||
footer::Footer,
|
||||
header::Header,
|
||||
pomodoro::{Mode as PomodoroMode, Pomodoro, PomodoroArgs, PomodoroWidget},
|
||||
timer::{Timer, TimerWidget},
|
||||
},
|
||||
@ -173,14 +174,22 @@ impl App {
|
||||
}
|
||||
}
|
||||
|
||||
fn clock_is_running(&mut self) -> bool {
|
||||
fn clock_is_running(&self) -> bool {
|
||||
match self.content {
|
||||
Content::Countdown => self.countdown.get_clock().clone().is_running(),
|
||||
Content::Timer => self.timer.get_clock().clone().is_running(),
|
||||
Content::Countdown => self.countdown.get_clock().is_running(),
|
||||
Content::Timer => self.timer.get_clock().is_running(),
|
||||
Content::Pomodoro => self.pomodoro.get_clock().is_running(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_percentage_done(&self) -> Option<u16> {
|
||||
match self.content {
|
||||
Content::Countdown => Some(self.countdown.get_clock().get_percentage_done()),
|
||||
Content::Timer => None,
|
||||
Content::Pomodoro => Some(self.pomodoro.get_clock().get_percentage_done()),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_key_event(&mut self, key: KeyEvent) {
|
||||
debug!("Received key {:?}", key.code);
|
||||
match key.code {
|
||||
@ -249,14 +258,20 @@ impl AppWidget {
|
||||
impl StatefulWidget for AppWidget {
|
||||
type State = App;
|
||||
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
||||
let [v0, v1] = Layout::vertical([
|
||||
let [v0, v1, v2] = Layout::vertical([
|
||||
Constraint::Length(1),
|
||||
Constraint::Percentage(100),
|
||||
Constraint::Length(if state.show_menu { 4 } else { 1 }),
|
||||
])
|
||||
.areas(area);
|
||||
|
||||
// header
|
||||
Header {
|
||||
percentage: state.get_percentage_done(),
|
||||
}
|
||||
.render(v0, buf);
|
||||
// content
|
||||
self.render_content(v0, buf, state);
|
||||
self.render_content(v1, buf, state);
|
||||
// footer
|
||||
Footer {
|
||||
show_menu: state.show_menu,
|
||||
@ -264,6 +279,6 @@ impl StatefulWidget for AppWidget {
|
||||
selected_content: state.content,
|
||||
edit_mode: state.is_edit_mode(),
|
||||
}
|
||||
.render(v1, buf);
|
||||
.render(v2, buf);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
pub mod clock;
|
||||
pub mod countdown;
|
||||
pub mod footer;
|
||||
pub mod header;
|
||||
pub mod pomodoro;
|
||||
pub mod progressbar;
|
||||
pub mod timer;
|
||||
|
||||
@ -393,12 +393,22 @@ impl Clock<Countdown> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_done(&mut self) {
|
||||
fn set_done(&mut self) {
|
||||
if self.current_value.is_zero() {
|
||||
self.mode = Mode::Done;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_percentage_done(&self) -> u16 {
|
||||
let initial = self.initial_value.as_millis();
|
||||
let elapsed = self
|
||||
.initial_value
|
||||
.saturating_sub(self.current_value)
|
||||
.as_millis();
|
||||
|
||||
(elapsed * 100 / initial) as u16
|
||||
}
|
||||
|
||||
pub fn edit_next(&mut self) {
|
||||
self.edit_mode_next();
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ impl Widget for Footer {
|
||||
.title(
|
||||
format! {"[m]enu {:} ", if self.show_menu {scrollbar::VERTICAL.end} else {scrollbar::VERTICAL.begin}},
|
||||
)
|
||||
.border_set(border::DOUBLE)
|
||||
.border_set(border::PLAIN)
|
||||
.render(border_area, buf);
|
||||
// show menu
|
||||
if self.show_menu {
|
||||
|
||||
22
src/widgets/header.rs
Normal file
22
src/widgets/header.rs
Normal file
@ -0,0 +1,22 @@
|
||||
use ratatui::{
|
||||
buffer::Buffer,
|
||||
layout::Rect,
|
||||
widgets::{Block, Borders, Widget},
|
||||
};
|
||||
|
||||
use crate::widgets::progressbar::Progressbar;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Header {
|
||||
pub percentage: Option<u16>,
|
||||
}
|
||||
|
||||
impl Widget for Header {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
if let Some(percentage) = self.percentage {
|
||||
Progressbar::new(percentage).render(area, buf);
|
||||
} else {
|
||||
Block::new().borders(Borders::TOP).render(area, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
39
src/widgets/progressbar.rs
Normal file
39
src/widgets/progressbar.rs
Normal file
@ -0,0 +1,39 @@
|
||||
use ratatui::{
|
||||
buffer::Buffer,
|
||||
layout::{Constraint, Layout, Rect},
|
||||
symbols::line,
|
||||
text::Span,
|
||||
widgets::Widget,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Progressbar {
|
||||
pub percentage: u16,
|
||||
}
|
||||
|
||||
impl Progressbar {
|
||||
pub fn new(percentage: u16) -> Self {
|
||||
Self { percentage }
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for Progressbar {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
let label = Span::raw(format!(" {}% ", self.percentage));
|
||||
let [h0, area] = Layout::horizontal([
|
||||
Constraint::Length(label.width() as u16),
|
||||
Constraint::Percentage(100),
|
||||
])
|
||||
.areas(area);
|
||||
let [h1, h2] =
|
||||
Layout::horizontal([Constraint::Percentage(self.percentage), Constraint::Fill(0)])
|
||||
.areas(area);
|
||||
|
||||
// label
|
||||
label.render(h0, buf);
|
||||
// done
|
||||
Span::from(line::THICK_HORIZONTAL.repeat(h1.width as usize)).render(h1, buf);
|
||||
// rest
|
||||
Span::from(line::HORIZONTAL.repeat(h2.width as usize)).render(h2, buf);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user