mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-04-08 17:05:59 +02:00
feature: add basic page up/down scrolling (#646)
Adds page up/down scrolling support to respectively scroll up/down by a full page. Note that this is mostly just to get the feature out for those interested, and is admittedly a bit rushed - I will be rewriting all logic involving event handling as part of state refactor anyways, so this will also get changed in the work done there, and therefore, I kinda just sped through this.
This commit is contained in:
parent
c92cfc644d
commit
9eabb061aa
@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [0.6.7]/[0.7.0] - Unreleased
|
||||
|
||||
## Feature
|
||||
|
||||
- [#646](https://github.com/ClementTsang/bottom/pull/646): Add `PgUp`/`PgDown` keybind support to scroll up and down a page in a table.
|
||||
|
||||
## [0.6.6] - 2021-12-22
|
||||
|
||||
## Bug Fixes
|
||||
|
@ -55,6 +55,7 @@ Note that key bindings are generally case-sensitive.
|
||||
| ++right++ <br/> ++l++ <br/> ++alt+l++ | Move right within a widget |
|
||||
| ++g+g++ , ++home++ | Jump to the first entry |
|
||||
| ++G++ , ++end++ | Jump to the last entry |
|
||||
| ++page-up++ , ++page-down++ | Scroll up/down a table by a page |
|
||||
|
||||
## Mouse bindings
|
||||
|
||||
|
113
src/app.rs
113
src/app.rs
@ -1114,6 +1114,20 @@ impl App {
|
||||
0 => KillSignal::Cancel,
|
||||
sig => KillSignal::Kill(sig),
|
||||
};
|
||||
} else if self.current_widget.widget_type.is_widget_table() {
|
||||
if let (Some((_tlc_x, tlc_y)), Some((_brc_x, brc_y))) = (
|
||||
&self.current_widget.top_left_corner,
|
||||
&self.current_widget.bottom_right_corner,
|
||||
) {
|
||||
let border_offset = if self.is_drawing_border() { 1 } else { 0 };
|
||||
let header_gap_offset = 1 + if self.is_drawing_gap(&self.current_widget) {
|
||||
self.app_config_fields.table_gap
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let height = brc_y - tlc_y - 2 * border_offset - header_gap_offset;
|
||||
self.change_position_count(-(height as i64));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1127,6 +1141,20 @@ impl App {
|
||||
new_signal += 2;
|
||||
}
|
||||
self.delete_dialog_state.selected_signal = KillSignal::Kill(new_signal);
|
||||
} else if self.current_widget.widget_type.is_widget_table() {
|
||||
if let (Some((_tlc_x, tlc_y)), Some((_brc_x, brc_y))) = (
|
||||
&self.current_widget.top_left_corner,
|
||||
&self.current_widget.bottom_right_corner,
|
||||
) {
|
||||
let border_offset = if self.is_drawing_border() { 1 } else { 0 };
|
||||
let header_gap_offset = 1 + if self.is_drawing_gap(&self.current_widget) {
|
||||
self.app_config_fields.table_gap
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let height = brc_y - tlc_y - 2 * border_offset - header_gap_offset;
|
||||
self.change_position_count(height as i64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1443,8 +1471,6 @@ impl App {
|
||||
'0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' => {
|
||||
self.on_number(caught_char)
|
||||
}
|
||||
'u' => self.on_page_up(),
|
||||
'd' => self.on_page_down(),
|
||||
'g' => {
|
||||
let mut is_first_g = true;
|
||||
if let Some(second_char) = self.second_char {
|
||||
@ -2330,36 +2356,29 @@ impl App {
|
||||
}
|
||||
|
||||
pub fn decrement_position_count(&mut self) {
|
||||
if !self.ignore_normal_keybinds() {
|
||||
match self.current_widget.widget_type {
|
||||
BottomWidgetType::Proc => {
|
||||
self.increment_process_position(-1);
|
||||
}
|
||||
BottomWidgetType::ProcSort => self.increment_process_sort_position(-1),
|
||||
BottomWidgetType::Temp => self.increment_temp_position(-1),
|
||||
BottomWidgetType::Disk => self.increment_disk_position(-1),
|
||||
BottomWidgetType::CpuLegend => self.increment_cpu_legend_position(-1),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
self.change_position_count(-1);
|
||||
}
|
||||
|
||||
pub fn increment_position_count(&mut self) {
|
||||
self.change_position_count(1);
|
||||
}
|
||||
|
||||
fn change_position_count(&mut self, amount: i64) {
|
||||
if !self.ignore_normal_keybinds() {
|
||||
match self.current_widget.widget_type {
|
||||
BottomWidgetType::Proc => {
|
||||
self.increment_process_position(1);
|
||||
self.change_process_position(amount);
|
||||
}
|
||||
BottomWidgetType::ProcSort => self.increment_process_sort_position(1),
|
||||
BottomWidgetType::Temp => self.increment_temp_position(1),
|
||||
BottomWidgetType::Disk => self.increment_disk_position(1),
|
||||
BottomWidgetType::CpuLegend => self.increment_cpu_legend_position(1),
|
||||
BottomWidgetType::ProcSort => self.change_process_sort_position(amount),
|
||||
BottomWidgetType::Temp => self.change_temp_position(amount),
|
||||
BottomWidgetType::Disk => self.increment_disk_position(amount),
|
||||
BottomWidgetType::CpuLegend => self.change_cpu_legend_position(amount),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn increment_process_sort_position(&mut self, num_to_change_by: i64) {
|
||||
fn change_process_sort_position(&mut self, num_to_change_by: i64) {
|
||||
if let Some(proc_widget_state) = self
|
||||
.proc_state
|
||||
.get_mut_widget_state(self.current_widget.widget_id - 2)
|
||||
@ -2367,9 +2386,11 @@ impl App {
|
||||
let current_posn = proc_widget_state.columns.current_scroll_position;
|
||||
let num_columns = proc_widget_state.columns.get_enabled_columns_len();
|
||||
|
||||
if current_posn as i64 + num_to_change_by >= 0
|
||||
&& current_posn as i64 + num_to_change_by < num_columns as i64
|
||||
{
|
||||
if current_posn as i64 + num_to_change_by < 0 {
|
||||
proc_widget_state.columns.current_scroll_position = 0;
|
||||
} else if current_posn as i64 + num_to_change_by >= num_columns as i64 {
|
||||
proc_widget_state.columns.current_scroll_position = num_columns.saturating_sub(1);
|
||||
} else {
|
||||
proc_widget_state.columns.current_scroll_position =
|
||||
(current_posn as i64 + num_to_change_by) as usize;
|
||||
}
|
||||
@ -2382,7 +2403,7 @@ impl App {
|
||||
}
|
||||
}
|
||||
|
||||
fn increment_cpu_legend_position(&mut self, num_to_change_by: i64) {
|
||||
fn change_cpu_legend_position(&mut self, num_to_change_by: i64) {
|
||||
if let Some(cpu_widget_state) = self
|
||||
.cpu_state
|
||||
.widget_states
|
||||
@ -2391,9 +2412,11 @@ impl App {
|
||||
let current_posn = cpu_widget_state.scroll_state.current_scroll_position;
|
||||
|
||||
let cap = self.canvas_data.cpu_data.len();
|
||||
if current_posn as i64 + num_to_change_by >= 0
|
||||
&& current_posn as i64 + num_to_change_by < cap as i64
|
||||
{
|
||||
if current_posn as i64 + num_to_change_by < 0 {
|
||||
cpu_widget_state.scroll_state.current_scroll_position = 0;
|
||||
} else if current_posn as i64 + num_to_change_by >= cap as i64 {
|
||||
cpu_widget_state.scroll_state.current_scroll_position = cap.saturating_sub(1);
|
||||
} else {
|
||||
cpu_widget_state.scroll_state.current_scroll_position =
|
||||
(current_posn as i64 + num_to_change_by) as usize;
|
||||
}
|
||||
@ -2407,7 +2430,7 @@ impl App {
|
||||
}
|
||||
|
||||
/// Returns the new position.
|
||||
fn increment_process_position(&mut self, num_to_change_by: i64) -> Option<usize> {
|
||||
fn change_process_position(&mut self, num_to_change_by: i64) -> Option<usize> {
|
||||
if let Some(proc_widget_state) = self
|
||||
.proc_state
|
||||
.get_mut_widget_state(self.current_widget.widget_id)
|
||||
@ -2418,13 +2441,16 @@ impl App {
|
||||
.finalized_process_data_map
|
||||
.get(&self.current_widget.widget_id)
|
||||
{
|
||||
if current_posn as i64 + num_to_change_by >= 0
|
||||
&& current_posn as i64 + num_to_change_by < finalized_process_data.len() as i64
|
||||
if current_posn as i64 + num_to_change_by < 0 {
|
||||
proc_widget_state.scroll_state.current_scroll_position = 0;
|
||||
} else if current_posn as i64 + num_to_change_by
|
||||
>= finalized_process_data.len() as i64
|
||||
{
|
||||
proc_widget_state.scroll_state.current_scroll_position =
|
||||
(current_posn as i64 + num_to_change_by) as usize;
|
||||
finalized_process_data.len().saturating_sub(1);
|
||||
} else {
|
||||
return None;
|
||||
proc_widget_state.scroll_state.current_scroll_position =
|
||||
(current_posn as i64 + num_to_change_by) as usize;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2440,7 +2466,7 @@ impl App {
|
||||
None
|
||||
}
|
||||
|
||||
fn increment_temp_position(&mut self, num_to_change_by: i64) {
|
||||
fn change_temp_position(&mut self, num_to_change_by: i64) {
|
||||
if let Some(temp_widget_state) = self
|
||||
.temp_state
|
||||
.widget_states
|
||||
@ -2448,10 +2474,14 @@ impl App {
|
||||
{
|
||||
let current_posn = temp_widget_state.scroll_state.current_scroll_position;
|
||||
|
||||
if current_posn as i64 + num_to_change_by >= 0
|
||||
&& current_posn as i64 + num_to_change_by
|
||||
< self.canvas_data.temp_sensor_data.len() as i64
|
||||
if current_posn as i64 + num_to_change_by < 0 {
|
||||
temp_widget_state.scroll_state.current_scroll_position = 0;
|
||||
} else if current_posn as i64 + num_to_change_by
|
||||
>= self.canvas_data.temp_sensor_data.len() as i64
|
||||
{
|
||||
temp_widget_state.scroll_state.current_scroll_position =
|
||||
self.canvas_data.temp_sensor_data.len().saturating_sub(1);
|
||||
} else {
|
||||
temp_widget_state.scroll_state.current_scroll_position =
|
||||
(current_posn as i64 + num_to_change_by) as usize;
|
||||
}
|
||||
@ -2901,9 +2931,6 @@ impl App {
|
||||
}
|
||||
|
||||
let mut failed_to_get = true;
|
||||
// TODO: [MOUSE] We could use a better data structure for this? Currently it's a blind
|
||||
// traversal through a hashmap, using a 2d binary tree of sorts would be better.
|
||||
// See: https://docs.rs/kdtree/0.6.0/kdtree/
|
||||
for (new_widget_id, widget) in &self.widget_map {
|
||||
if let (Some((tlc_x, tlc_y)), Some((brc_x, brc_y))) =
|
||||
(widget.top_left_corner, widget.bottom_right_corner)
|
||||
@ -2985,7 +3012,7 @@ impl App {
|
||||
.current_scroll_position;
|
||||
let is_tree_mode = proc_widget_state.is_tree_mode;
|
||||
|
||||
let new_position = self.increment_process_position(
|
||||
let new_position = self.change_process_position(
|
||||
offset_clicked_entry as i64 - visual_index as i64,
|
||||
);
|
||||
|
||||
@ -3008,7 +3035,7 @@ impl App {
|
||||
if let Some(visual_index) =
|
||||
proc_widget_state.columns.column_state.selected()
|
||||
{
|
||||
self.increment_process_sort_position(
|
||||
self.change_process_sort_position(
|
||||
offset_clicked_entry as i64 - visual_index as i64,
|
||||
);
|
||||
}
|
||||
@ -3022,7 +3049,7 @@ impl App {
|
||||
if let Some(visual_index) =
|
||||
cpu_widget_state.scroll_state.table_state.selected()
|
||||
{
|
||||
self.increment_cpu_legend_position(
|
||||
self.change_cpu_legend_position(
|
||||
offset_clicked_entry as i64 - visual_index as i64,
|
||||
);
|
||||
}
|
||||
@ -3036,7 +3063,7 @@ impl App {
|
||||
if let Some(visual_index) =
|
||||
temp_widget_state.scroll_state.table_state.selected()
|
||||
{
|
||||
self.increment_temp_position(
|
||||
self.change_temp_position(
|
||||
offset_clicked_entry as i64 - visual_index as i64,
|
||||
);
|
||||
}
|
||||
|
@ -695,6 +695,13 @@ impl Painter {
|
||||
}
|
||||
})?;
|
||||
|
||||
if let Some(updated_current_widget) = app_state
|
||||
.widget_map
|
||||
.get(&app_state.current_widget.widget_id)
|
||||
{
|
||||
app_state.current_widget = updated_current_widget.clone();
|
||||
}
|
||||
|
||||
app_state.is_force_redraw = false;
|
||||
app_state.is_determining_widget_boundary = false;
|
||||
|
||||
|
@ -231,7 +231,7 @@ pub const HELP_CONTENTS_TEXT: [&str; 8] = [
|
||||
|
||||
// TODO [Help]: Search in help?
|
||||
// TODO [Help]: Move to using tables for easier formatting?
|
||||
pub const GENERAL_HELP_TEXT: [&str; 30] = [
|
||||
pub const GENERAL_HELP_TEXT: [&str; 31] = [
|
||||
"1 - General",
|
||||
"q, Ctrl-c Quit",
|
||||
"Esc Close dialog windows, search, widgets, or exit expanded mode",
|
||||
@ -260,6 +260,7 @@ pub const GENERAL_HELP_TEXT: [&str; 30] = [
|
||||
"+ Zoom in on chart (decrease time range)",
|
||||
"- Zoom out on chart (increase time range)",
|
||||
"= Reset zoom",
|
||||
"PgUp, PgDown Scroll up/down a table by a page",
|
||||
"Mouse scroll Scroll through the tables or zoom in/out of charts by scrolling up/down",
|
||||
"Mouse click Selects the clicked widget, table entry, dialog option, or tab",
|
||||
];
|
||||
|
@ -125,6 +125,8 @@ pub fn handle_key_event_or_break(
|
||||
KeyCode::F(5) => app.toggle_tree_mode(),
|
||||
KeyCode::F(6) => app.toggle_sort(),
|
||||
KeyCode::F(9) => app.start_killing_process(),
|
||||
KeyCode::PageDown => app.on_page_down(),
|
||||
KeyCode::PageUp => app.on_page_up(),
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user