mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-04-08 17:05:59 +02:00
Add frozen
This commit is contained in:
parent
a78edc88c0
commit
95318bb3e4
36
src/app.rs
36
src/app.rs
@ -151,11 +151,6 @@ pub struct AppState {
|
||||
pub app_config_fields: AppConfigFields,
|
||||
|
||||
// --- NEW STUFF ---
|
||||
pub selected_widget: NodeId,
|
||||
pub widget_lookup_map: FxHashMap<NodeId, BottomWidget>,
|
||||
pub layout_tree: Arena<LayoutNode>,
|
||||
pub layout_tree_root: NodeId,
|
||||
|
||||
frozen_state: FrozenState,
|
||||
current_screen: CurrentScreen,
|
||||
painter: Painter,
|
||||
@ -180,10 +175,6 @@ impl AppState {
|
||||
app_config_fields,
|
||||
filters,
|
||||
used_widgets,
|
||||
selected_widget,
|
||||
widget_lookup_map,
|
||||
layout_tree,
|
||||
layout_tree_root,
|
||||
painter,
|
||||
|
||||
// Use defaults.
|
||||
@ -226,8 +217,14 @@ impl Application for AppState {
|
||||
self.set_current_screen(CurrentScreen::Help);
|
||||
true
|
||||
}
|
||||
AppMessages::ConfirmKillProcess { to_kill } => true,
|
||||
AppMessages::KillProcess { to_kill, signal } => true,
|
||||
AppMessages::ConfirmKillProcess { to_kill } => {
|
||||
// FIXME: Handle confirmation
|
||||
true
|
||||
}
|
||||
AppMessages::KillProcess { to_kill, signal } => {
|
||||
// FIXME: Handle process termination
|
||||
true
|
||||
}
|
||||
AppMessages::ToggleFreeze => {
|
||||
self.frozen_state.toggle(&self.data_collection);
|
||||
true
|
||||
@ -302,27 +299,26 @@ impl Application for AppState {
|
||||
}
|
||||
|
||||
fn global_event_handler(
|
||||
&mut self, event: crate::tuine::Event, messages: &mut Vec<Self::Message>,
|
||||
&mut self, event: crate::tuine::Event, messages: &mut Vec<AppMessages>,
|
||||
) -> Status {
|
||||
use crate::tuine::Event;
|
||||
use crossterm::event::{KeyCode, KeyModifiers};
|
||||
|
||||
fn on_quit(messages: &mut Vec<AppMessages>) -> Status {
|
||||
messages.push(AppMessages::Quit);
|
||||
Status::Captured
|
||||
}
|
||||
|
||||
match event {
|
||||
Event::Keyboard(event) => {
|
||||
if event.modifiers.is_empty() {
|
||||
match event.code {
|
||||
KeyCode::Char('q') | KeyCode::Char('Q') => {
|
||||
messages.push(AppMessages::Quit);
|
||||
Status::Captured
|
||||
}
|
||||
KeyCode::Char('q') | KeyCode::Char('Q') => on_quit(messages),
|
||||
_ => Status::Ignored,
|
||||
}
|
||||
} else if let KeyModifiers::CONTROL = event.modifiers {
|
||||
match event.code {
|
||||
KeyCode::Char('c') | KeyCode::Char('C') => {
|
||||
messages.push(AppMessages::Quit);
|
||||
Status::Captured
|
||||
}
|
||||
KeyCode::Char('c') | KeyCode::Char('C') => on_quit(messages),
|
||||
KeyCode::Char('r') | KeyCode::Char('R') => {
|
||||
messages.push(AppMessages::Reset);
|
||||
Status::Captured
|
||||
|
@ -175,7 +175,7 @@ impl Default for DataCollection {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Just rip this out, store only stringified data...?
|
||||
// TODO: Just rip this out, store only stringified data...? Hm.
|
||||
impl DataCollection {
|
||||
pub fn reset(&mut self) {
|
||||
self.timed_data_vec = Default::default();
|
||||
|
120
src/canvas.rs
120
src/canvas.rs
@ -118,124 +118,4 @@ impl Painter {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw_frozen_indicator<B: Backend>(&self, f: &mut Frame<'_, B>, draw_loc: Rect) {
|
||||
f.render_widget(
|
||||
Paragraph::new(Span::styled(
|
||||
"Frozen, press 'f' to unfreeze",
|
||||
self.colours.currently_selected_text_style,
|
||||
)),
|
||||
Layout::default()
|
||||
.horizontal_margin(1)
|
||||
.constraints([Constraint::Length(1)])
|
||||
.split(draw_loc)[0],
|
||||
)
|
||||
}
|
||||
|
||||
pub fn draw_data<B: Backend>(
|
||||
&mut self, terminal: &mut Terminal<B>, app_state: &mut app::AppState,
|
||||
) -> error::Result<()> {
|
||||
terminal.draw(|mut f| {
|
||||
let (draw_area, frozen_draw_loc) = if false {
|
||||
let split_loc = Layout::default()
|
||||
.constraints([Constraint::Min(0), Constraint::Length(1)])
|
||||
.split(f.size());
|
||||
(split_loc[0], Some(split_loc[1]))
|
||||
} else {
|
||||
(f.size(), None)
|
||||
};
|
||||
let terminal_height = draw_area.height;
|
||||
let terminal_width = draw_area.width;
|
||||
|
||||
if false {
|
||||
if let Some(frozen_draw_loc) = frozen_draw_loc {
|
||||
self.draw_frozen_indicator(&mut f, frozen_draw_loc);
|
||||
}
|
||||
|
||||
if let Some(current_widget) = app_state
|
||||
.widget_lookup_map
|
||||
.get_mut(&app_state.selected_widget)
|
||||
{
|
||||
current_widget.set_bounds(draw_area);
|
||||
current_widget.draw(self, f, draw_area, true, true);
|
||||
}
|
||||
} else {
|
||||
/// A simple traversal through the `arena`, drawing all leaf elements.
|
||||
fn traverse_and_draw_tree<B: Backend>(
|
||||
node: NodeId, arena: &Arena<LayoutNode>, f: &mut Frame<'_, B>,
|
||||
lookup_map: &mut FxHashMap<NodeId, BottomWidget>, painter: &Painter,
|
||||
selected_id: NodeId, offset_x: u16, offset_y: u16,
|
||||
) {
|
||||
if let Some(layout_node) = arena.get(node).map(|n| n.get()) {
|
||||
match layout_node {
|
||||
LayoutNode::Row(RowLayout { bound, .. })
|
||||
| LayoutNode::Col(ColLayout { bound, .. }) => {
|
||||
for child in node.children(arena) {
|
||||
traverse_and_draw_tree(
|
||||
child,
|
||||
arena,
|
||||
f,
|
||||
lookup_map,
|
||||
painter,
|
||||
selected_id,
|
||||
offset_x + bound.x,
|
||||
offset_y + bound.y,
|
||||
);
|
||||
}
|
||||
}
|
||||
LayoutNode::Widget(widget_layout) => {
|
||||
let bound = widget_layout.bound;
|
||||
let area = Rect::new(
|
||||
bound.x + offset_x,
|
||||
bound.y + offset_y,
|
||||
bound.width,
|
||||
bound.height,
|
||||
);
|
||||
|
||||
if let Some(widget) = lookup_map.get_mut(&node) {
|
||||
if let BottomWidget::Carousel(carousel) = widget {
|
||||
let remaining_area: Rect =
|
||||
carousel.draw_carousel(painter, f, area);
|
||||
if let Some(to_draw_node) =
|
||||
carousel.get_currently_selected()
|
||||
{
|
||||
if let Some(child_widget) =
|
||||
lookup_map.get_mut(&to_draw_node)
|
||||
{
|
||||
child_widget.set_bounds(remaining_area);
|
||||
child_widget.draw(
|
||||
painter,
|
||||
f,
|
||||
remaining_area,
|
||||
selected_id == node,
|
||||
false,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
widget.set_bounds(area);
|
||||
widget.draw(painter, f, area, selected_id == node, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(frozen_draw_loc) = frozen_draw_loc {
|
||||
self.draw_frozen_indicator(&mut f, frozen_draw_loc);
|
||||
}
|
||||
|
||||
let root = &app_state.layout_tree_root;
|
||||
let arena = &mut app_state.layout_tree;
|
||||
let selected_id = app_state.selected_widget;
|
||||
|
||||
generate_layout(*root, arena, draw_area, &app_state.widget_lookup_map);
|
||||
|
||||
let lookup_map = &mut app_state.widget_lookup_map;
|
||||
traverse_and_draw_tree(*root, arena, f, lookup_map, self, selected_id, 0, 0);
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
32
src/tuine/component/banner/frozen_banner.rs
Normal file
32
src/tuine/component/banner/frozen_banner.rs
Normal file
@ -0,0 +1,32 @@
|
||||
use tui::{
|
||||
layout::{Constraint, Layout},
|
||||
style::Style,
|
||||
text::Span,
|
||||
widgets::Paragraph,
|
||||
};
|
||||
|
||||
use crate::tuine::TmpComponent;
|
||||
|
||||
/// A small banner to display that the app is "frozen" from data updates.
|
||||
pub struct FrozenBanner {
|
||||
style: Style,
|
||||
}
|
||||
|
||||
impl<Message> TmpComponent<Message> for FrozenBanner {
|
||||
fn draw<Backend>(
|
||||
&mut self, _state_ctx: &mut crate::tuine::StateContext<'_>,
|
||||
draw_ctx: &crate::tuine::DrawContext<'_>, frame: &mut tui::Frame<'_, Backend>,
|
||||
) where
|
||||
Backend: tui::backend::Backend,
|
||||
{
|
||||
let rect = draw_ctx.global_rect();
|
||||
|
||||
frame.render_widget(
|
||||
Paragraph::new(Span::styled("Frozen, press 'f' to unfreeze", self.style)),
|
||||
Layout::default()
|
||||
.horizontal_margin(1)
|
||||
.constraints([Constraint::Length(1)])
|
||||
.split(rect)[0],
|
||||
)
|
||||
}
|
||||
}
|
2
src/tuine/component/banner/mod.rs
Normal file
2
src/tuine/component/banner/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod frozen_banner;
|
||||
pub use frozen_banner::*;
|
@ -7,6 +7,9 @@ pub use widget::*;
|
||||
pub mod stateful;
|
||||
pub use stateful::*;
|
||||
|
||||
pub mod banner;
|
||||
pub use banner::*;
|
||||
|
||||
// pub mod stateless;
|
||||
// pub use stateless::*;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::tuine::{State, StateContext, ViewContext};
|
||||
use crate::tuine::{State, ViewContext};
|
||||
|
||||
use super::TmpComponent;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user