diff --git a/src/tui.rs b/src/tui.rs index b2cb439..191deb9 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -6,6 +6,7 @@ use crossterm::terminal::{ }; use ratatui::backend::CrosstermBackend; use ratatui::layout::{Constraint, Direction, Layout, Rect}; +use ratatui::style::{Color, Style}; use ratatui::widgets::{Block, Borders, Paragraph, Wrap}; use ratatui::{Frame, Terminal}; use std::io::{stdout, Stdout}; @@ -605,11 +606,18 @@ fn render( log: &HistoryLog, typewriter: Option<&Typewriter>, ) { - let area = frame.size(); + // Outer layout: two-column area on top, 1-row status bar across the + // full width below. + let outer = Layout::default() + .direction(Direction::Vertical) + .constraints([Constraint::Min(0), Constraint::Length(1)].as_ref()) + .split(frame.size()); + let (top, status) = (outer[0], outer[1]); + let chunks = Layout::default() .direction(Direction::Horizontal) .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref()) - .split(area); + .split(top); let (left, right) = (chunks[0], chunks[1]); match screen { @@ -632,6 +640,35 @@ fn render( } else { render_editor_inactive(frame, right); } + + render_status_bar(frame, status, screen, focus); +} + +fn render_status_bar(frame: &mut Frame, area: Rect, screen: &Screen, focus: Focus) { + let style = Style::default().fg(Color::White).bg(Color::DarkGray); + let p = Paragraph::new(status_text(screen, focus)).style(style); + frame.render_widget(p, area); +} + +fn status_text(screen: &Screen, focus: Focus) -> String { + match (screen, focus) { + (Screen::Welcome, _) => { + " [Enter] begin · [↑/↓] scroll · [PgUp/PgDn] page · [q] quit".into() + } + (Screen::TierSelect { .. }, _) => { + " [↑/↓] choose · [Enter] confirm · [PgUp/PgDn] scroll · [q] quit".into() + } + (Screen::Game, Focus::Editor) => { + " [Ctrl-S] grade · [Tab] focus log · [Esc] focus log · [Ctrl-Q] quit".into() + } + (Screen::Game, Focus::Game) => { + " [Ctrl-S] grade · [Tab] focus editor · [↑/↓] scroll · [r] reset · [q] quit".into() + } + (Screen::ResetConfirm, _) => " [y] confirm wipe · any other key cancels".into(), + (Screen::Completed, _) => { + " [↑/↓] scroll · [PgUp/PgDn] page · [r] reset · [q] quit".into() + } + } } fn screen_widget<'a>(title: String, body: String) -> Paragraph<'a> { @@ -642,8 +679,7 @@ fn screen_widget<'a>(title: String, body: String) -> Paragraph<'a> { fn welcome_prompt_lines() -> Vec { vec![ - "🏰 You stand at the entrance.".to_string(), - " [Enter] begin · [q] flee · [PgUp/PgDn] scroll the log".to_string(), + "🏰 You stand at the entrance, brave explorer. Press [Enter] to enter the dungeon.".to_string(), ] } @@ -775,11 +811,6 @@ fn entry_lines(entry: &LogEntry) -> Vec { for line in description.lines() { v.push(line.to_string()); } - v.push(String::new()); - v.push( - " ⌨ [Ctrl-S] grade · [Tab] swap · [↑/↓] scroll · [r] reset · [q] quit" - .to_string(), - ); v } LogEntry::ResultPass {