parent
acb627b1d7
commit
ae1a48e5e8
27
src/app.rs
27
src/app.rs
@ -8,6 +8,7 @@ use crate::{
|
|||||||
clock::{self, Clock, ClockArgs, Style},
|
clock::{self, Clock, ClockArgs, Style},
|
||||||
countdown::{Countdown, CountdownWidget},
|
countdown::{Countdown, CountdownWidget},
|
||||||
footer::Footer,
|
footer::Footer,
|
||||||
|
header::Header,
|
||||||
pomodoro::{Mode as PomodoroMode, Pomodoro, PomodoroArgs, PomodoroWidget},
|
pomodoro::{Mode as PomodoroMode, Pomodoro, PomodoroArgs, PomodoroWidget},
|
||||||
timer::{Timer, TimerWidget},
|
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 {
|
match self.content {
|
||||||
Content::Countdown => self.countdown.get_clock().clone().is_running(),
|
Content::Countdown => self.countdown.get_clock().is_running(),
|
||||||
Content::Timer => self.timer.get_clock().clone().is_running(),
|
Content::Timer => self.timer.get_clock().is_running(),
|
||||||
Content::Pomodoro => self.pomodoro.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) {
|
fn handle_key_event(&mut self, key: KeyEvent) {
|
||||||
debug!("Received key {:?}", key.code);
|
debug!("Received key {:?}", key.code);
|
||||||
match key.code {
|
match key.code {
|
||||||
@ -249,14 +258,20 @@ impl AppWidget {
|
|||||||
impl StatefulWidget for AppWidget {
|
impl StatefulWidget for AppWidget {
|
||||||
type State = App;
|
type State = App;
|
||||||
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
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::Percentage(100),
|
||||||
Constraint::Length(if state.show_menu { 4 } else { 1 }),
|
Constraint::Length(if state.show_menu { 4 } else { 1 }),
|
||||||
])
|
])
|
||||||
.areas(area);
|
.areas(area);
|
||||||
|
|
||||||
|
// header
|
||||||
|
Header {
|
||||||
|
percentage: state.get_percentage_done(),
|
||||||
|
}
|
||||||
|
.render(v0, buf);
|
||||||
// content
|
// content
|
||||||
self.render_content(v0, buf, state);
|
self.render_content(v1, buf, state);
|
||||||
// footer
|
// footer
|
||||||
Footer {
|
Footer {
|
||||||
show_menu: state.show_menu,
|
show_menu: state.show_menu,
|
||||||
@ -264,6 +279,6 @@ impl StatefulWidget for AppWidget {
|
|||||||
selected_content: state.content,
|
selected_content: state.content,
|
||||||
edit_mode: state.is_edit_mode(),
|
edit_mode: state.is_edit_mode(),
|
||||||
}
|
}
|
||||||
.render(v1, buf);
|
.render(v2, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
pub mod clock;
|
pub mod clock;
|
||||||
pub mod countdown;
|
pub mod countdown;
|
||||||
pub mod footer;
|
pub mod footer;
|
||||||
|
pub mod header;
|
||||||
pub mod pomodoro;
|
pub mod pomodoro;
|
||||||
|
pub mod progressbar;
|
||||||
pub mod timer;
|
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() {
|
if self.current_value.is_zero() {
|
||||||
self.mode = Mode::Done;
|
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) {
|
pub fn edit_next(&mut self) {
|
||||||
self.edit_mode_next();
|
self.edit_mode_next();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,7 +36,7 @@ impl Widget for Footer {
|
|||||||
.title(
|
.title(
|
||||||
format! {"[m]enu {:} ", if self.show_menu {scrollbar::VERTICAL.end} else {scrollbar::VERTICAL.begin}},
|
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);
|
.render(border_area, buf);
|
||||||
// show menu
|
// show menu
|
||||||
if self.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