added colours, select and delete ops, refac
This commit is contained in:
147
src/ui/mod.rs
147
src/ui/mod.rs
@@ -1,19 +1,21 @@
|
||||
#![allow(non_snake_case)]
|
||||
mod centeredRect;
|
||||
mod textHints;
|
||||
|
||||
use ratatui::{
|
||||
Frame,
|
||||
layout::{Constraint, Direction, Layout},
|
||||
style::{Color, Style},
|
||||
style::{Color, Modifier, Style},
|
||||
text::{Line, Span, Text},
|
||||
widgets::{Block, Borders, List, ListItem, Paragraph, Wrap},
|
||||
widgets::{Block, Borders, Cell, Paragraph, Row, Table, Wrap},
|
||||
};
|
||||
|
||||
use crate::app::status::CurrentScreen;
|
||||
use crate::app::{AppState, status::EditingField};
|
||||
use crate::ui::centeredRect::centered_rect;
|
||||
use crate::ui::textHints::hints;
|
||||
|
||||
pub fn ui(frame: &mut Frame, app: &AppState) {
|
||||
pub fn ui(frame: &mut Frame, app: &mut AppState) {
|
||||
// Split entire body into left title+body and right screen+keybinds chunks
|
||||
let screenChunks = Layout::default()
|
||||
.direction(ratatui::layout::Direction::Horizontal)
|
||||
@@ -47,32 +49,74 @@ pub fn ui(frame: &mut Frame, app: &AppState) {
|
||||
frame.render_widget(title, titleBodyChunks[0]);
|
||||
|
||||
// Create and add body
|
||||
let mut currentItems = Vec::<ListItem>::new();
|
||||
for (i, e) in app.entries.iter().enumerate() {
|
||||
currentItems.push(ListItem::new(Line::from(Span::styled(
|
||||
format!("{i}. {e}"),
|
||||
Style::default().fg(Color::Yellow),
|
||||
))));
|
||||
}
|
||||
let list = List::new(currentItems).block(Block::default().borders(Borders::all()));
|
||||
frame.render_widget(list, titleBodyChunks[1]);
|
||||
// let mut currentItems = Vec::<ListItem>::new();
|
||||
// for (i, e) in app.entries.iter().enumerate() {
|
||||
// currentItems.push(ListItem::new(Line::from(Span::styled(
|
||||
// format!("{i}. {e}"),
|
||||
// Style::default().fg(Color::Yellow),
|
||||
// ))));
|
||||
// }
|
||||
|
||||
// table drawing
|
||||
let headers = ["No.", "From IP", "From Port", "-->", "To IP", "To Port"]
|
||||
.into_iter()
|
||||
.map(Cell::from)
|
||||
.collect::<Row>()
|
||||
.style(Style::default().fg(Color::White).bg(Color::Black))
|
||||
.height(2);
|
||||
|
||||
let dataRows = app.entries.iter().enumerate().map(|(i, d)| {
|
||||
let item = d.array(i + 1);
|
||||
item.into_iter()
|
||||
.map(|content| Cell::from(Text::from(format!("\n{content}\n"))))
|
||||
.collect::<Row>()
|
||||
.style(Style::new().fg(Color::White).bg(Color::Black))
|
||||
.height(2)
|
||||
});
|
||||
let selectedColor = match app.screen {
|
||||
CurrentScreen::Delete => Color::Yellow,
|
||||
_ => Color::DarkGray,
|
||||
};
|
||||
let table = Table::new(
|
||||
dataRows,
|
||||
[
|
||||
Constraint::Percentage(4),
|
||||
Constraint::Percentage(28),
|
||||
Constraint::Percentage(18),
|
||||
Constraint::Percentage(4),
|
||||
Constraint::Percentage(28),
|
||||
Constraint::Percentage(18),
|
||||
],
|
||||
)
|
||||
.header(headers)
|
||||
.block(Block::default().borders(Borders::all()))
|
||||
.row_highlight_style(
|
||||
Style::default()
|
||||
.add_modifier(Modifier::REVERSED)
|
||||
.fg(selectedColor),
|
||||
);
|
||||
|
||||
// let list = List::new(currentItems).block(Block::default().borders(Borders::all()));
|
||||
frame.render_stateful_widget(table, titleBodyChunks[1], &mut app.tableState);
|
||||
|
||||
// Renter exit prompt
|
||||
if let CurrentScreen::Exit = app.screen {
|
||||
let exitPopup = Block::default()
|
||||
.title("Save and Exit?")
|
||||
.title("Exit Window")
|
||||
.borders(Borders::ALL)
|
||||
.style(Style::default().bg(Color::DarkGray));
|
||||
.style(Style::default().bg(Color::DarkGray))
|
||||
.border_style(Style::default().fg(Color::Red));
|
||||
|
||||
let exitText = Text::styled(
|
||||
"Save the current config and exit? (enter/esc)",
|
||||
Style::default().fg(Color::Red),
|
||||
);
|
||||
let exitText = Text::from(vec![
|
||||
Line::from("Exit the app?"),
|
||||
Line::from("ANY UNSAVED CHANGES WILL BE DISCARDED."),
|
||||
Line::from("Press (s) to save from the main screen."),
|
||||
]);
|
||||
let exitPara = Paragraph::new(exitText)
|
||||
.block(exitPopup)
|
||||
.wrap(Wrap { trim: false });
|
||||
|
||||
let area = centered_rect(60, 25, frame.area());
|
||||
let area = centered_rect(60, 25, titleBodyChunks[1]);
|
||||
frame.render_widget(exitPara, area);
|
||||
}
|
||||
|
||||
@@ -82,7 +126,7 @@ pub fn ui(frame: &mut Frame, app: &AppState) {
|
||||
.title("Add an entry")
|
||||
.borders(Borders::NONE)
|
||||
.style(Style::default().bg(Color::DarkGray));
|
||||
let area = centered_rect(60, 25, titleBodyChunks[1]);
|
||||
let area = centered_rect(75, 20, titleBodyChunks[1]);
|
||||
frame.render_widget(popup, area);
|
||||
|
||||
let fields = Layout::default()
|
||||
@@ -123,14 +167,30 @@ pub fn ui(frame: &mut Frame, app: &AppState) {
|
||||
|
||||
// --------------------------------
|
||||
// Current page title and status
|
||||
let mut borderColor = Color::White;
|
||||
let _ = borderColor; // to suppress warning, remove later
|
||||
let screenHeader = vec![
|
||||
match app.screen {
|
||||
CurrentScreen::Main => Span::styled("Main Screen", Style::default().fg(Color::Green)),
|
||||
CurrentScreen::Add => Span::styled("Add entry", Style::default().fg(Color::Yellow)),
|
||||
CurrentScreen::Exit => {
|
||||
Span::styled("Exit Screen", Style::default().fg(Color::LightRed))
|
||||
CurrentScreen::Main => {
|
||||
borderColor = Color::LightBlue;
|
||||
Span::styled("Main Screen", Style::default().fg(Color::LightBlue))
|
||||
}
|
||||
CurrentScreen::Add => {
|
||||
borderColor = Color::LightGreen;
|
||||
Span::styled("Add entry", Style::default().fg(Color::Green))
|
||||
}
|
||||
CurrentScreen::Exit => {
|
||||
borderColor = Color::LightRed;
|
||||
Span::styled("Exit Screen", Style::default().fg(Color::Red))
|
||||
}
|
||||
CurrentScreen::Settings => {
|
||||
borderColor = Color::LightBlue;
|
||||
Span::styled("Settings", Style::default().fg(Color::Blue))
|
||||
}
|
||||
CurrentScreen::Delete => {
|
||||
borderColor = Color::LightMagenta;
|
||||
Span::styled("Delete Selection", Style::default().fg(Color::Magenta))
|
||||
}
|
||||
CurrentScreen::Settings => Span::styled("Settings", Style::default().fg(Color::Blue)),
|
||||
}
|
||||
.to_owned(),
|
||||
Span::styled(" | ", Style::default().fg(Color::White)),
|
||||
@@ -152,35 +212,28 @@ pub fn ui(frame: &mut Frame, app: &AppState) {
|
||||
},
|
||||
];
|
||||
|
||||
let screenHeaderPara = Paragraph::new(Line::from(screenHeader))
|
||||
.block(Block::default().borders(Borders::TOP | Borders::LEFT | Borders::RIGHT));
|
||||
let screenHeaderPara = Paragraph::new(Line::from(screenHeader)).block(
|
||||
Block::default()
|
||||
.borders(Borders::TOP | Borders::LEFT | Borders::RIGHT)
|
||||
.style(Style::default().fg(borderColor)),
|
||||
);
|
||||
|
||||
// Keybinds Entry
|
||||
let keybinds = {
|
||||
match app.screen {
|
||||
CurrentScreen::Main => Text::from(vec![
|
||||
Line::from("(a) add entry").style(Style::default().fg(Color::Green)),
|
||||
Line::from("(q) save and quit").style(Style::default().fg(Color::Green)),
|
||||
]),
|
||||
CurrentScreen::Add => Text::from(vec![
|
||||
Line::from("(l) localhost"),
|
||||
Line::from("(enter) next field"),
|
||||
Line::from("(c) clear"),
|
||||
Line::from("(C) clear all"),
|
||||
Line::from("(esc) main menu"),
|
||||
]),
|
||||
CurrentScreen::Settings => {
|
||||
Text::from(Line::from("").style(Style::default().fg(Color::Red)))
|
||||
}
|
||||
CurrentScreen::Exit => Text::from(vec![
|
||||
Line::from("(enter) save and exit").style(Style::default().fg(Color::Red)),
|
||||
Line::from("(esc) main menu").style(Style::default().fg(Color::Red)),
|
||||
]),
|
||||
CurrentScreen::Main => hints::mainHints(),
|
||||
CurrentScreen::Add => hints::addHints(),
|
||||
CurrentScreen::Settings => hints::settingsHints(),
|
||||
CurrentScreen::Delete => hints::delHints(),
|
||||
CurrentScreen::Exit => hints::exitHints(),
|
||||
}
|
||||
};
|
||||
|
||||
let keyBindFooter = Paragraph::new(keybinds)
|
||||
.block(Block::default().borders(Borders::BOTTOM | Borders::LEFT | Borders::RIGHT));
|
||||
let keyBindFooter = Paragraph::new(keybinds).block(
|
||||
Block::default()
|
||||
.borders(Borders::BOTTOM | Borders::LEFT | Borders::RIGHT)
|
||||
.style(Style::default().fg(borderColor)),
|
||||
);
|
||||
|
||||
frame.render_widget(screenHeaderPara, headerKeybindChunks[0]);
|
||||
frame.render_widget(keyBindFooter, headerKeybindChunks[1]);
|
||||
|
||||
Reference in New Issue
Block a user