diff --git a/src/Tools/psxreadmap/src/lib.rs b/src/Tools/psxreadmap/src/lib.rs index c4f1737e..2887dadb 100644 --- a/src/Tools/psxreadmap/src/lib.rs +++ b/src/Tools/psxreadmap/src/lib.rs @@ -96,22 +96,23 @@ impl Default for ListSelection { } pub struct ConsoleUI { + data: ConsoleUIData, rx: EventReceiver, terminal: Terminal, - cur_size: Rect, - main_chunks: Vec, - stats_chunks: Vec, + console_size: 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, content_selection: ListSelection::default()} + ConsoleUI{data: ConsoleUIData::default(), rx, terminal, console_size: Rect::default(), menu_selection: MenuSelection::Stats, content_selection: ListSelection::default()} } - pub fn update(&mut self, data: &ConsoleUIData) -> Result { - if data.list.len() > 0 { + pub fn update_data(&mut self, memory_map: &MemoryMap) -> Result<(), Error> { + self.data.update(memory_map)?; + + if self.data.list.len() > 0 { if !self.content_selection.is_active() { self.content_selection.activate(); } @@ -120,7 +121,10 @@ impl ConsoleUI { else { self.content_selection.deactivate(); } + Ok(()) + } + pub fn update(&mut self) -> Result { match self.rx.recv()? { Event::Input(event) => { match event.code { @@ -129,17 +133,17 @@ impl ConsoleUI { self.menu_selection = MenuSelection::Stats; Ok(UIState::Render) }, - KeyCode::Left => { + KeyCode::Left => { self.menu_selection = self.menu_selection.prev(); Ok(UIState::Render) }, - KeyCode::Right => { + KeyCode::Right => { 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()); + self.content_selection.increment(self.data.list.len()); Ok(UIState::Render) } @@ -147,9 +151,9 @@ impl ConsoleUI { Ok(UIState::Alive) } }, - KeyCode::Up => { + KeyCode::Up => { if matches!(self.menu_selection, MenuSelection::Stats) { - self.content_selection.decrement(data.list.len()); + self.content_selection.decrement(self.data.list.len()); Ok(UIState::Render) } @@ -157,7 +161,7 @@ impl ConsoleUI { Ok(UIState::Alive) } }, - KeyCode::Enter => { + KeyCode::Enter => { if matches!(self.menu_selection, MenuSelection::Quit) { Ok(UIState::Terminated) } @@ -168,8 +172,10 @@ impl ConsoleUI { _ => Ok(UIState::Alive) } }, - Event::Tick => { - if self.terminal.size().expect("Getting size of terminal") != self.cur_size { + Event::Tick => { + let terminal_size = self.terminal.size().expect("Getting size of terminal"); + if terminal_size != self.console_size { + self.console_size = terminal_size; Ok(UIState::Render) } @@ -181,18 +187,59 @@ impl ConsoleUI { } } - pub fn render(&mut self, data: &mut ConsoleUIData) -> Result<(), Error> { + pub fn render(&mut self) -> Result<(), Error> { self.terminal.draw(|frame| { - Self::update_sub_frames(&mut self.main_chunks, &mut self.stats_chunks, &mut self.cur_size, frame.size()); + // Create layout elements + let main_layout = Layout::default().direction(Direction::Vertical).constraints([ + Constraint::Length(3), + Constraint::Length(3), + Constraint::Min(3) + ]).split(frame.size()).to_vec(); + let stats_layout = Layout::default().direction(Direction::Vertical).constraints([ + Constraint::Min(3), + Constraint::Length(3) + ]).split(main_layout[2]).to_vec(); - frame.render_widget(Self::create_titel(), self.main_chunks[0]); - frame.render_widget(Self::create_menu(&self.menu_selection), self.main_chunks[1]); + // Elements + let titel_bar = { + Paragraph::new("psxreadmap") + .style(Style::default().fg(Color::White)) + .alignment(Alignment::Center) + .block(Block::default() + .borders(Borders::ALL) + .style(Style::default().fg(Color::White)) + .border_type(BorderType::Plain) + ) + }; + let menu_bar = { + const MENU_TITLES: &'static [&'static str] = &["Stats", "Quit"]; + + let menu = MENU_TITLES.iter().map(|t| { + let (first, rest) = t.split_at(1); + Line::from(vec![ + Span::styled(first, Style::default().fg(Color::Yellow).add_modifier(Modifier::UNDERLINED),), + Span::styled(rest, Style::default().fg(Color::White)), + ]) + }).collect(); + + Tabs::new(menu).select(self.menu_selection.get_id()).block( + Block::default() + .title("Menu").borders(Borders::ALL)) + .style(Style::default().fg(Color::White)) + .highlight_style(Style::default().bg(Color::LightYellow)) + .divider(Span::raw("|") + ) + }; + + // Render screen + frame.render_widget(titel_bar, main_layout[0]); + frame.render_widget(menu_bar, main_layout[1]); match self.menu_selection { MenuSelection::Stats => { - Self::render_stats(frame, &self.stats_chunks, &self.content_selection, data); + Self::render_stats(frame, &stats_layout, &self.content_selection, &mut self.data); }, MenuSelection::Quit => { - frame.render_widget(Self::create_exit_message(), self.main_chunks[2]); + frame.render_widget(Self::create_exit_message(), main_layout[2]); } } })?; @@ -207,54 +254,6 @@ impl ConsoleUI { Ok(()) } - fn update_sub_frames(sub_frames: &mut Vec, stats_frames: &mut Vec, frame: &mut Rect, new_frame: Rect) { - if new_frame != *frame { - *sub_frames = Layout::default().direction(Direction::Vertical).constraints([ - Constraint::Length(3), - Constraint::Length(3), - Constraint::Min(3) - ]).split(new_frame).to_vec(); - - *stats_frames = Layout::default().direction(Direction::Vertical).constraints([ - Constraint::Min(3), - Constraint::Length(3) - ]).split(sub_frames[2]).to_vec(); - - *frame = new_frame; - } - } - - fn create_titel<'a>() -> Paragraph<'a> { - Paragraph::new("psxreadmap") - .style(Style::default().fg(Color::White)) - .alignment(Alignment::Center) - .block(Block::default() - .borders(Borders::ALL) - .style(Style::default().fg(Color::White)) - .border_type(BorderType::Plain) - ) - } - - fn create_menu<'a>(menu_selection: &MenuSelection) -> Tabs<'a> { - const MENU_TITLES: &'static [&'static str] = &["Stats", "Quit"]; - - let menu = MENU_TITLES.iter().map(|t| { - let (first, rest) = t.split_at(1); - Line::from(vec![ - Span::styled(first, Style::default().fg(Color::Yellow).add_modifier(Modifier::UNDERLINED),), - Span::styled(rest, Style::default().fg(Color::White)), - ]) - }).collect(); - - Tabs::new(menu).select(menu_selection.get_id()).block( - Block::default() - .title("Menu").borders(Borders::ALL)) - .style(Style::default().fg(Color::White)) - .highlight_style(Style::default().bg(Color::LightYellow)) - .divider(Span::raw("|") - ) - } - fn render_stats(frame: &mut ConsoleFrame, frames: &Vec, content_selection: &ListSelection, data: &mut ConsoleUIData) { let content_list = List::new({ let mut vec = Vec::new(); @@ -270,7 +269,7 @@ impl ConsoleUI { .border_type(BorderType::Plain) ) .highlight_style(Style::default().bg(Color::Yellow)); - let mem_gauge = Self::create_overall_mem_gauge(data.highest_adr); + let mem_gauge = Self::create_mem_gauge("Overall memory usage", data.highest_adr, Color::Cyan); let mut list_state = ListState::default(); list_state.select(content_selection.selection); @@ -279,16 +278,16 @@ impl ConsoleUI { frame.render_widget(mem_gauge, frames[1]); } - fn create_overall_mem_gauge<'a>(highest_adr: u64) -> Gauge<'a> { + fn create_mem_gauge<'a>(name: &str, adr: u64, color: Color) -> Gauge<'a> { const RAM_TOP:u64 = ConsoleUIData::HIGHEST_RAM_ADDRESS & !ConsoleUIData::RAM_BASE_ADDRESS; - let highest_adr_masked = highest_adr & !ConsoleUIData::RAM_BASE_ADDRESS; - let adr_ratio = (highest_adr_masked as f64)/RAM_TOP as f64; + let adr_masked = adr & !ConsoleUIData::RAM_BASE_ADDRESS; + let adr_ratio = (adr_masked as f64)/RAM_TOP as f64; Gauge::default().block(Block::default().borders(Borders::ALL) - .title(format!("Memory Usage: {}% [0x{:x}/0x{:x}]", adr_ratio*100.0f64, highest_adr, ConsoleUIData::HIGHEST_RAM_ADDRESS))) - .gauge_style(Style::default().fg(Color::Cyan).bg(Color::Black).add_modifier(Modifier::BOLD)) - .ratio(adr_ratio) + .title(format!("{} [0x{:x}/0x{:x}]", name, adr, ConsoleUIData::HIGHEST_RAM_ADDRESS))) + .gauge_style(Style::default().fg(color).bg(Color::Black).add_modifier(Modifier::BOLD)) + .ratio(adr_ratio).label(format!("{}%", adr_ratio*100.0f64)) } fn create_exit_message<'a>() -> Paragraph<'a> { @@ -304,7 +303,7 @@ impl ConsoleUI { } #[derive(Default)] -pub struct ConsoleUIData { +struct ConsoleUIData { highest_adr: u64, list: Vec } @@ -313,7 +312,7 @@ impl ConsoleUIData { pub const RAM_BASE_ADDRESS:u64 = 0x80000000; pub const HIGHEST_RAM_ADDRESS:u64 = Self::RAM_BASE_ADDRESS + (2*1024*1024); - pub fn new(memory_map: &MemoryMap) -> Result { + fn _new(memory_map: &MemoryMap) -> Result { let mut ui_data = ConsoleUIData::default(); ui_data.update(memory_map)?; diff --git a/src/Tools/psxreadmap/src/main.rs b/src/Tools/psxreadmap/src/main.rs index 069dd6d6..d75e7d3e 100644 --- a/src/Tools/psxreadmap/src/main.rs +++ b/src/Tools/psxreadmap/src/main.rs @@ -1,6 +1,6 @@ use clap::Parser; use crossterm::{event::{self, Event as CEvent, KeyboardEnhancementFlags, KeyEventKind, PushKeyboardEnhancementFlags}, execute, terminal}; -use psxreadmap::{ConsoleUI, ConsoleUIData, Event, EventReceiver, Terminal, load_memory_map, UIState}; +use psxreadmap::{ConsoleUI, Event, EventReceiver, Terminal, load_memory_map, UIState}; use std::{io, path::PathBuf, sync::mpsc, thread, time::{Duration, Instant}}; use tool_helper::{Error, exit_with_error}; use ratatui::backend::CrosstermBackend; @@ -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 mut ui_data = ConsoleUIData::new(&memory_map)?; let mut console_ui = ConsoleUI::new(rx, terminal); + console_ui.update_data(&memory_map)?; loop { - match console_ui.update(&ui_data)? { + match console_ui.update()? { UIState::Alive => (), - UIState::Render => {console_ui.render(&mut ui_data)?;} + UIState::Render => {console_ui.render()?;} UIState::Terminated => break } }