From 0bb24a38380cb1cb47533ac62889f6450a01e92b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Orhun=20Parmaks=C4=B1z?= Date: Wed, 12 Jan 2022 00:03:44 +0300 Subject: [PATCH] feat(tui): show the selected parameter index --- systeroid-tui/src/ui.rs | 114 +++++++++++++++++++++++++++++++++++----- 1 file changed, 100 insertions(+), 14 deletions(-) diff --git a/systeroid-tui/src/ui.rs b/systeroid-tui/src/ui.rs index 6206423..da56ae7 100644 --- a/systeroid-tui/src/ui.rs +++ b/systeroid-tui/src/ui.rs @@ -1,27 +1,44 @@ use crate::app::App; use tui::backend::Backend; -use tui::layout::{Constraint, Direction, Layout, Rect}; +use tui::layout::{Alignment, Constraint, Direction, Layout, Rect}; use tui::style::{Color, Style}; -use tui::widgets::{Block, BorderType, Borders, Cell, Paragraph, Row, Table}; +use tui::text::{Span, Text}; +use tui::widgets::{Block, BorderType, Borders, Cell, Clear, Paragraph, Row, Table}; use tui::Frame; use unicode_width::UnicodeWidthStr; /// Renders the user interface. pub fn render(frame: &mut Frame<'_, B>, app: &mut App) { + let documentation = app + .parameter_list + .selected() + .and_then(|parameter| parameter.get_documentation()); let rect = frame.size(); let chunks = Layout::default() .direction(Direction::Horizontal) - .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref()) + .constraints(if documentation.is_some() { + [Constraint::Percentage(50), Constraint::Percentage(50)] + } else { + [Constraint::Percentage(100), Constraint::Min(0)] + }) .split(rect); { let chunks = Layout::default() .direction(Direction::Vertical) - .constraints([Constraint::Min(rect.height - 3), Constraint::Min(3)].as_ref()) + .constraints(if app.input.is_some() { + [Constraint::Min(rect.height - 3), Constraint::Min(3)] + } else { + [Constraint::Percentage(100), Constraint::Min(0)] + }) .split(chunks[0]); render_parameter_list(frame, chunks[0], app); - render_input_prompt(frame, chunks[1], rect.height - 2, app); + if app.input.is_some() { + render_input_prompt(frame, chunks[1], rect.height - 2, app); + } + } + if let Some(documentation) = documentation { + render_parameter_documentation(frame, chunks[1], documentation); } - render_parameter_documentation(frame, chunks[1], app); } /// Renders the list that contains the sysctl parameters. @@ -51,6 +68,11 @@ fn render_parameter_list(frame: &mut Frame<'_, B>, rect: Rect, app: Table::new(rows) .block( Block::default() + .title(Span::styled( + "Parameters", + Style::default().fg(Color::White), + )) + .title_alignment(Alignment::Left) .borders(Borders::all()) .border_style(Style::default().fg(Color::White)) .border_type(BorderType::Rounded) @@ -65,19 +87,83 @@ fn render_parameter_list(frame: &mut Frame<'_, B>, rect: Rect, app: rect, &mut app.parameter_list.state, ); + render_selection_text( + frame, + rect, + format!( + "{}/{}", + app.parameter_list + .state + .selected() + .map(|v| v + 1) + .unwrap_or(0), + app.parameter_list.items.len() + ), + ); +} + +/// Renders the text for displaying the selected index. +fn render_selection_text(frame: &mut Frame<'_, B>, rect: Rect, selection_text: String) { + let selection_text_width = u16::try_from(selection_text.width()).unwrap_or_default(); + if let Some(horizontal_area_width) = rect.width.checked_sub(selection_text_width + 2) { + let vertical_area = Layout::default() + .direction(Direction::Vertical) + .constraints( + [ + Constraint::Min(rect.height.checked_sub(2).unwrap_or(rect.height)), + Constraint::Min(1), + Constraint::Min(1), + ] + .as_ref(), + ) + .split(rect); + let horizontal_area = Layout::default() + .direction(Direction::Horizontal) + .constraints( + [ + Constraint::Min(horizontal_area_width), + Constraint::Min(selection_text_width), + Constraint::Min(1), + Constraint::Min(1), + ] + .as_ref(), + ) + .split(vertical_area[1]); + frame.render_widget(Clear, horizontal_area[1]); + frame.render_widget( + Paragraph::new(selection_text).block( + Block::default() + .borders(Borders::NONE) + .style(Style::default().bg(Color::Black)), + ), + horizontal_area[1], + ); + frame.render_widget(Clear, horizontal_area[2]); + frame.render_widget( + Paragraph::new(Text::default()).block( + Block::default() + .borders(Borders::NONE) + .style(Style::default().bg(Color::Black)), + ), + horizontal_area[2], + ); + } } /// Renders the documentation of the selected sysctl parameter. -fn render_parameter_documentation(frame: &mut Frame<'_, B>, rect: Rect, app: &mut App) { +fn render_parameter_documentation( + frame: &mut Frame<'_, B>, + rect: Rect, + documentation: String, +) { frame.render_widget( - Paragraph::new( - app.parameter_list - .selected() - .and_then(|parameter| parameter.get_documentation()) - .unwrap_or_else(|| String::from("No documentation available")), - ) - .block( + Paragraph::new(documentation).block( Block::default() + .title(Span::styled( + "Documentation", + Style::default().fg(Color::White), + )) + .title_alignment(Alignment::Center) .borders(Borders::all()) .border_style(Style::default().fg(Color::White)) .border_type(BorderType::Rounded)