use crate::{
app::App,
canvas::{
drawing_utils::{get_column_widths, get_search_start_position, get_start_position},
Painter,
},
constants::*,
};
use tui::{
backend::Backend,
layout::{Alignment, Constraint, Direction, Layout, Rect},
terminal::Frame,
text::{Span, Spans},
widgets::{Block, Borders, Paragraph, Row, Table},
};
use std::borrow::Cow;
use unicode_segmentation::{GraphemeIndices, UnicodeSegmentation};
use unicode_width::UnicodeWidthStr;
use once_cell::sync::Lazy;
static PROCESS_HEADERS_HARD_WIDTH_NO_GROUP: Lazy<Vec<Option<u16>>> = Lazy::new(|| {
vec![
Some(7),
None,
Some(8),
Some(8),
Some(8),
Some(8),
Some(7),
Some(8),
]
});
static PROCESS_HEADERS_HARD_WIDTH_GROUPED: Lazy<Vec<Option<u16>>> = Lazy::new(|| {
vec![
Some(7),
None,
Some(8),
Some(8),
Some(8),
Some(8),
Some(7),
Some(8),
None,
]
});
static PROCESS_HEADERS_SOFT_WIDTH_MAX_GROUPED_COMMAND: Lazy<Vec<Option<f64>>> =
Lazy::new(|| vec![None, Some(0.7), None, None, None, None, None, None]);
static PROCESS_HEADERS_SOFT_WIDTH_MAX_GROUPED_TREE: Lazy<Vec<Option<f64>>> =
Lazy::new(|| vec![None, Some(0.5), None, None, None, None, None, None]);
static PROCESS_HEADERS_SOFT_WIDTH_MAX_GROUPED_ELSE: Lazy<Vec<Option<f64>>> =
Lazy::new(|| vec![None, Some(0.4), None, None, None, None, None, None]);
static PROCESS_HEADERS_SOFT_WIDTH_MAX_NO_GROUP_COMMAND: Lazy<Vec<Option<f64>>> = Lazy::new(|| {
vec![
None,
Some(0.7),
None,
None,
None,
None,
None,
None,
Some(0.2),
]
});
static PROCESS_HEADERS_SOFT_WIDTH_MAX_NO_GROUP_TREE: Lazy<Vec<Option<f64>>> = Lazy::new(|| {
vec![
None,
Some(0.5),
None,
None,
None,
None,
None,
None,
Some(0.2),
]
});
static PROCESS_HEADERS_SOFT_WIDTH_MAX_NO_GROUP_ELSE: Lazy<Vec<Option<f64>>> = Lazy::new(|| {
vec![
None,
Some(0.3),
None,
None,
None,
None,
None,
None,
Some(0.2),
]
});
pub trait ProcessTableWidget {
/// Draws and handles all process-related drawing. Use this.
/// - `widget_id` here represents the widget ID of the process widget itself!
fn draw_process_features<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect, draw_border: bool,
widget_id: u64,
);
/// Draws the process sort box.
/// - `widget_id` represents the widget ID of the process widget itself.
///
/// This should not be directly called.
fn draw_processes_table<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect, draw_border: bool,
widget_id: u64,
);
/// Draws the process search field.
/// - `widget_id` represents the widget ID of the search box itself --- NOT the process widget
/// state that is stored.
///
/// This should not be directly called.
fn draw_search_field<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect, draw_border: bool,
widget_id: u64,
);
/// Draws the process sort box.
/// - `widget_id` represents the widget ID of the sort box itself --- NOT the process widget
/// state that is stored.
///
/// This should not be directly called.
fn draw_process_sort<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect, draw_border: bool,
widget_id: u64,
);
}
impl ProcessTableWidget for Painter {
fn draw_process_features<B: Backend>(
&self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect, draw_border: bool,
widget_id: u64,
) {
if let Some(process_widget_state) = app_state.proc_state.widget_states.get(&widget_id) {
let search_height = if draw_border { 5 } else { 3 };
let is_sort_open = process_widget_state.is_sort_open;
let header_len = process_widget_state.columns.longest_header_len;
let mut proc_draw_loc = draw_loc;
if process_widget_state.is_search_enabled() {
let processes_chunk = Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Min(0), Constraint::Length(search_height)])
.split(draw_loc);
proc_draw_loc = processes_chunk[0];
self.draw_search_field(
f,
app_state,
processes_chunk