Support a list with Schwimmflügel
This commit is contained in:
parent
af64fcb7f5
commit
6177f37f36
|
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue