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}, layout::{Alignment, Constraint, Direction, Layout, Rect},
style::{Color, Modifier, Style}, style::{Color, Modifier, Style},
text::{Line, Span}, 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>>; pub type EventReceiver = std::sync::mpsc::Receiver<Event<crossterm::event::KeyEvent>>;
@ -51,21 +51,76 @@ 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 { pub struct ConsoleUI {
rx: EventReceiver, rx: EventReceiver,
terminal: Terminal, terminal: Terminal,
cur_size: Rect, cur_size: Rect,
main_chunks: Vec<Rect>, main_chunks: Vec<Rect>,
stats_chunks: Vec<Rect>, stats_chunks: Vec<Rect>,
menu_selection: MenuSelection, menu_selection: MenuSelection,
content_selection: ListSelection,
} }
impl ConsoleUI { impl ConsoleUI {
pub fn new(rx: EventReceiver, terminal: Terminal) -> 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) -> Result<UIState, Error> { 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();
}
match self.rx.recv()? { match self.rx.recv()? {
Event::Input(event) => { Event::Input(event) => {
match event.code { match event.code {
@ -82,6 +137,26 @@ impl ConsoleUI {
self.menu_selection = self.menu_selection.next(); self.menu_selection = self.menu_selection.next();
Ok(UIState::Render) 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 => { KeyCode::Enter => {
if matches!(self.menu_selection, MenuSelection::Quit) { if matches!(self.menu_selection, MenuSelection::Quit) {
Ok(UIState::Terminated) 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.terminal.draw(|frame| {
Self::update_sub_frames(&mut self.main_chunks, &mut self.stats_chunks, &mut self.cur_size, frame.size()); 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]); frame.render_widget(Self::create_menu(&self.menu_selection), self.main_chunks[1]);
match self.menu_selection { match self.menu_selection {
MenuSelection::Stats => { MenuSelection::Stats => {
Self::render_stats(frame, &self.stats_chunks, data); Self::render_stats(frame, &self.stats_chunks, &self.content_selection, data);
}, },
MenuSelection::Quit => { MenuSelection::Quit => {
frame.render_widget(Self::create_exit_message(), self.main_chunks[2]); 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) { fn render_stats(frame: &mut ConsoleFrame, frames: &Vec<Rect>, content_selection: &ListSelection, data: &mut ConsoleUIData) {
let content_text = Paragraph::new("<EMPTY>") let content_list = List::new({
.style(Style::default().fg(Color::White)) let mut vec = Vec::new();
.alignment(Alignment::Center)
.block(Block::default()
.borders(Borders::ALL)
.style(Style::default().fg(Color::White))
.border_type(BorderType::Plain)
);
let mem_gauge = Self::create_overall_mem_gauge(data.highest_adr);
frame.render_widget(content_text, frames[0]); 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();
list_state.select(content_selection.selection);
frame.render_stateful_widget(content_list, frames[0], &mut list_state);
frame.render_widget(mem_gauge, frames[1]); frame.render_widget(mem_gauge, frames[1]);
} }
@ -221,7 +305,8 @@ impl ConsoleUI {
#[derive(Default)] #[derive(Default)]
pub struct ConsoleUIData { pub struct ConsoleUIData {
highest_adr: u64 highest_adr: u64,
list: Vec<String>
} }
impl ConsoleUIData { impl ConsoleUIData {
@ -245,6 +330,16 @@ impl ConsoleUIData {
} }
self.highest_adr = get_last_section_end_adr(memory_map); 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(()) 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 memory_map = load_memory_map(cmd.use_wsl, cmd.input)?; dump_memory_map(cmd.output, &memory_map)?;
let rx = start_event_loop(); let rx = start_event_loop();
let terminal = setup_console()?; 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); let mut console_ui = ConsoleUI::new(rx, terminal);
loop { loop {
match console_ui.update()? { match console_ui.update(&ui_data)? {
UIState::Alive => (), UIState::Alive => (),
UIState::Render => {console_ui.render(&ui_data)?;} UIState::Render => {console_ui.render(&mut ui_data)?;}
UIState::Terminated => break UIState::Terminated => break
} }
} }