Support a list with Schwimmflügel

This commit is contained in:
Jaby Blubb 2023-08-06 10:46:12 +02:00
parent af64fcb7f5
commit 6177f37f36
2 changed files with 121 additions and 26 deletions

View File

@ -7,7 +7,7 @@ use ratatui::{
layout::{Alignment, Constraint, Direction, Layout, Rect},
style::{Color, Modifier, Style},
text::{Line, Span},
widgets::{Block, Borders, BorderType, Gauge, Paragraph, Tabs}
widgets::{Block, Borders, BorderType, Gauge, List, ListItem, ListState, Paragraph, Tabs}
};
pub type EventReceiver = std::sync::mpsc::Receiver<Event<crossterm::event::KeyEvent>>;
@ -51,6 +51,50 @@ impl MenuSelection {
}
}
pub struct ListSelection {
pub selection: Option<usize>
}
impl ListSelection {
fn change_value(&mut self, max: usize, f: fn(usize)->usize) {
if let Some(cur_selection) = self.selection {
self.selection = Some(f(cur_selection)%max);
}
}
pub fn increment(&mut self, max: usize) {
fn add_one(value: usize) -> usize {
value + 1
}
self.change_value(max, add_one)
}
pub fn decrement(&mut self, max: usize) {
fn sub_one(value: usize) -> usize {
value - 1
}
self.change_value(max, sub_one)
}
pub fn activate(&mut self) {
self.selection = Some(0);
}
pub fn deactivate(&mut self) {
self.selection = None;
}
pub fn is_active(&self) -> bool {
self.selection.is_some()
}
}
impl Default for ListSelection {
fn default() -> Self {
Self{selection: None}
}
}
pub struct ConsoleUI {
rx: EventReceiver,
terminal: Terminal,
@ -58,14 +102,25 @@ pub struct ConsoleUI {
main_chunks: Vec<Rect>,
stats_chunks: Vec<Rect>,
menu_selection: MenuSelection,
content_selection: ListSelection,
}
impl ConsoleUI {
pub fn new(rx: EventReceiver, terminal: Terminal) -> ConsoleUI {
ConsoleUI{rx, terminal, cur_size: Rect::default(), main_chunks: Vec::default(), stats_chunks: Vec::default(), menu_selection: MenuSelection::Stats}
ConsoleUI{rx, terminal, cur_size: Rect::default(), main_chunks: Vec::default(), stats_chunks: Vec::default(), menu_selection: MenuSelection::Stats, content_selection: ListSelection::default()}
}
pub fn update(&mut self, data: &ConsoleUIData) -> Result<UIState, Error> {
if data.list.len() > 0 {
if !self.content_selection.is_active() {
self.content_selection.activate();
}
}
else {
self.content_selection.deactivate();
}
pub fn update(&mut self) -> Result<UIState, Error> {
match self.rx.recv()? {
Event::Input(event) => {
match event.code {
@ -82,6 +137,26 @@ impl ConsoleUI {
self.menu_selection = self.menu_selection.next();
Ok(UIState::Render)
},
KeyCode::Down => {
if matches!(self.menu_selection, MenuSelection::Stats) {
self.content_selection.increment(data.list.len());
Ok(UIState::Render)
}
else {
Ok(UIState::Alive)
}
},
KeyCode::Up => {
if matches!(self.menu_selection, MenuSelection::Stats) {
self.content_selection.decrement(data.list.len());
Ok(UIState::Render)
}
else {
Ok(UIState::Alive)
}
},
KeyCode::Enter => {
if matches!(self.menu_selection, MenuSelection::Quit) {
Ok(UIState::Terminated)
@ -106,7 +181,7 @@ impl ConsoleUI {
}
}
pub fn render(&mut self, data: &ConsoleUIData) -> Result<(), Error> {
pub fn render(&mut self, data: &mut ConsoleUIData) -> Result<(), Error> {
self.terminal.draw(|frame| {
Self::update_sub_frames(&mut self.main_chunks, &mut self.stats_chunks, &mut self.cur_size, frame.size());
@ -114,7 +189,7 @@ impl ConsoleUI {
frame.render_widget(Self::create_menu(&self.menu_selection), self.main_chunks[1]);
match self.menu_selection {
MenuSelection::Stats => {
Self::render_stats(frame, &self.stats_chunks, data);
Self::render_stats(frame, &self.stats_chunks, &self.content_selection, data);
},
MenuSelection::Quit => {
frame.render_widget(Self::create_exit_message(), self.main_chunks[2]);
@ -180,18 +255,27 @@ impl ConsoleUI {
)
}
fn render_stats(frame: &mut ConsoleFrame, frames: &Vec<Rect>, data: &ConsoleUIData) {
let content_text = Paragraph::new("<EMPTY>")
.style(Style::default().fg(Color::White))
.alignment(Alignment::Center)
fn render_stats(frame: &mut ConsoleFrame, frames: &Vec<Rect>, content_selection: &ListSelection, data: &mut ConsoleUIData) {
let content_list = List::new({
let mut vec = Vec::new();
for item in &data.list {
vec.push(ListItem::new(item.as_str()))
}
vec
}).style(Style::default().fg(Color::White))
.block(Block::default()
.borders(Borders::ALL)
.style(Style::default().fg(Color::White))
.border_type(BorderType::Plain)
);
)
.highlight_style(Style::default().bg(Color::Yellow));
let mem_gauge = Self::create_overall_mem_gauge(data.highest_adr);
let mut list_state = ListState::default();
frame.render_widget(content_text, frames[0]);
list_state.select(content_selection.selection);
frame.render_stateful_widget(content_list, frames[0], &mut list_state);
frame.render_widget(mem_gauge, frames[1]);
}
@ -221,7 +305,8 @@ impl ConsoleUI {
#[derive(Default)]
pub struct ConsoleUIData {
highest_adr: u64
highest_adr: u64,
list: Vec<String>
}
impl ConsoleUIData {
@ -245,6 +330,16 @@ impl ConsoleUIData {
}
self.highest_adr = get_last_section_end_adr(memory_map);
self.list = vec![
String::from("Schwimmflugel 0"),
String::from("Schwimmflugel 1"),
String::from("Schwimmflugel 2"),
String::from("Schwimmflugel 3"),
String::from("Schwimmflugel 4"),
String::from("Schwimmflugel 5"),
String::from("Schwimmflugel 6"),
String::from("Schwimmflugel 7"),
];
Ok(())
}
}

View File

@ -34,13 +34,13 @@ fn run_main(cmd: CommandLine) -> Result<(), Error> {
let memory_map = load_memory_map(cmd.use_wsl, cmd.input)?; dump_memory_map(cmd.output, &memory_map)?;
let rx = start_event_loop();
let terminal = setup_console()?;
let ui_data = ConsoleUIData::new(&memory_map)?;
let mut ui_data = ConsoleUIData::new(&memory_map)?;
let mut console_ui = ConsoleUI::new(rx, terminal);
loop {
match console_ui.update()? {
match console_ui.update(&ui_data)? {
UIState::Alive => (),
UIState::Render => {console_ui.render(&ui_data)?;}
UIState::Render => {console_ui.render(&mut ui_data)?;}
UIState::Terminated => break
}
}