diff --git a/crates/wayfarer/src/tui/state.rs b/crates/wayfarer/src/tui/state.rs index 9e304df..cffada5 100644 --- a/crates/wayfarer/src/tui/state.rs +++ b/crates/wayfarer/src/tui/state.rs @@ -9,7 +9,9 @@ use ratatui::widgets::TableState; use tracing::debug; use tui_input::Input; -use super::view::info::{GLYPHS_TABLE_RANGE, MURALS_TABLE_RANGE, STATS_TABLE_RANGE}; +use super::view::info::glyphs::TABLE_RANGE as GLYPHS_TABLE_RANGE; +use super::view::info::murals::TABLE_RANGE as MURALS_TABLE_RANGE; +use super::view::info::stats::TABLE_RANGE as STATS_TABLE_RANGE; use super::Direction; #[cfg(feature = "watch")] use crate::watcher::FileWatcher; diff --git a/crates/wayfarer/src/tui/view.rs b/crates/wayfarer/src/tui/view.rs index 6276c2d..f9e5e8a 100644 --- a/crates/wayfarer/src/tui/view.rs +++ b/crates/wayfarer/src/tui/view.rs @@ -13,7 +13,7 @@ use super::State; type Frame<'a> = ratatui::Frame<'a, CrosstermBackend>; -pub fn render(state: &mut State, frame: &mut Frame) { +pub(super) fn render(state: &mut State, frame: &mut Frame) { let rows = Layout::default() .direction(Direction::Vertical) .constraints([Constraint::Min(40), Constraint::Length(2)]) diff --git a/crates/wayfarer/src/tui/view/info.rs b/crates/wayfarer/src/tui/view/info.rs index 8f1ab7c..3f0f58d 100644 --- a/crates/wayfarer/src/tui/view/info.rs +++ b/crates/wayfarer/src/tui/view/info.rs @@ -1,19 +1,17 @@ -use jrny_save::LEVEL_NAMES; -use ratatui::layout::{Alignment, Constraint, Direction, Layout, Rect}; -use ratatui::style::{Color, Style}; -use ratatui::widgets::{Block, Borders, Cell, Padding, Paragraph, Row, Table}; +pub mod companions; +pub mod glyphs; +pub mod murals; +pub mod stats; + + +use ratatui::layout::{Constraint, Direction, Layout, Rect}; +use ratatui::widgets::{Block, Borders, Padding, Paragraph}; -use crate::tui::state::{Mode, Section}; use crate::tui::view::Frame; use crate::tui::State; -pub const STATS_TABLE_RANGE: (usize, usize) = (0, 9); -pub const GLYPHS_TABLE_RANGE: (usize, usize) = (0, 5); -pub const MURALS_TABLE_RANGE: (usize, usize) = (0, 6); - - -pub fn render(state: &mut State, frame: &mut Frame, area: Rect) { +pub(super) fn render(state: &mut State, frame: &mut Frame, area: Rect) { if state.is_savefile_loaded() { render_info(state, frame, area); } else { @@ -54,243 +52,8 @@ fn render_info(state: &mut State, mut frame: &mut Frame, area: Rect) { .constraints([Constraint::Ratio(10, 10)]) .split(columns[1]); - render_stats(state, &mut frame, left_column[0]); - render_glyphs(state, &mut frame, left_column[1]); - render_murals(state, &mut frame, left_column[2]); - render_companions(state, &mut frame, right_column[0]); -} - - -fn render_stats<'a>(state: &mut State, frame: &mut Frame, area: Rect) { - let Some(savefile) = state.savefile() else { - return - }; - - let is_selected = state.active_section == Section::General && state.mode == Mode::Edit; - - let border_style = if is_selected { - Style::default().fg(Color::Blue) - } else { - Style::default() - }; - - let stats_section_block = Block::default() - .padding(Padding::new(2, 2, 1, 1)) - .border_style(border_style) - .borders(Borders::ALL); - - let layout = Layout::default() - .direction(Direction::Horizontal) - .constraints([Constraint::Percentage(25), Constraint::Percentage(75)]) - .split(stats_section_block.inner(area)); - - let stats_block = Block::default().title("Stats"); - - let table_highlight = if is_selected { - Style::default().fg(Color::Blue) - } else { - Style::default() - }; - - let table = Table::new([ - Row::new([ - "Journeys Completed".to_string(), - savefile.journey_count.to_string(), - ]), - Row::new([ - "Total Companions Met".to_string(), - savefile.total_companions_met.to_string(), - ]), - Row::new([ - "Total Symbols Collected".to_string(), - savefile.total_collected_symbols.to_string(), - ]), - Row::new(["Current Level", savefile.current_level_name()]), - Row::new([ - "Companions Met".to_string(), - savefile.companions_met.to_string(), - ]), - Row::new([ - "Scarf Length".to_string(), - savefile.scarf_length.to_string(), - ]), - Row::new(["Symbol Number".to_string(), savefile.symbol.id.to_string()]), - Row::new(["Robe Color".to_string(), savefile.robe_color().to_string()]), - Row::new(["Robe Tier".to_string(), savefile.robe_tier().to_string()]), - Row::new(["Last Played".to_string(), savefile.last_played.to_string()]), - ]) - .highlight_style(table_highlight) - .widths(&[Constraint::Ratio(1, 3), Constraint::Ratio(2, 3)]) - .block(stats_block); - - let cur_symbol_block = Block::default(); - - let cur_symbol = Paragraph::new(savefile.symbol.to_string()).block(cur_symbol_block); - - frame.render_widget(stats_section_block, area); - frame.render_widget(cur_symbol, layout[0]); - frame.render_stateful_widget(table, layout[1], &mut state.stats_table); -} - - -fn render_companions<'a>(state: &State, frame: &mut Frame, area: Rect) { - let Some(savefile) = state.savefile() else { - return - }; - - let is_selected = state.active_section == Section::Companions && state.mode == Mode::Edit; - - let border_style = if is_selected { - Style::default().fg(ratatui::style::Color::Blue) - } else { - Style::default() - }; - - let companions_block = Block::default() - .title("Companions") - .padding(Padding::new(2, 2, 1, 1)) - .border_style(border_style) - .borders(Borders::ALL); - - let layout = Layout::default() - .direction(Direction::Vertical) - .constraints([Constraint::Ratio(1, 2), Constraint::Ratio(1, 2)]) - .split(companions_block.inner(area)); - - let current_companions_block = Block::default() - .title("Current") - .borders(Borders::TOP) - .title_alignment(Alignment::Center); - - let current_companions = Table::new( - savefile - .current_companions() - .map(|companion| Row::new([companion.name.clone(), companion.steam_url()])), - ) - .widths(&[Constraint::Ratio(1, 3), Constraint::Ratio(2, 3)]) - .block(current_companions_block); - - let past_companions_block = Block::default() - .title("Past") - .borders(Borders::TOP) - .title_alignment(Alignment::Center); - - let past_companions = Table::new( - savefile - .past_companions() - .map(|companion| Row::new([companion.name.clone(), companion.steam_url()])), - ) - .widths(&[Constraint::Ratio(1, 3), Constraint::Ratio(2, 3)]) - .block(past_companions_block); - - frame.render_widget(companions_block, area); - frame.render_widget(current_companions, layout[0]); - frame.render_widget(past_companions, layout[1]); -} - - -fn render_glyphs<'a>(state: &mut State, frame: &mut Frame, area: Rect) { - const FOUND_SIGN: &str = "◆"; - const NOT_FOUND_SIGN: &str = "◇"; - - let Some(savefile) = state.savefile() else { - return - }; - - let is_selected = state.active_section == Section::Glyphs && state.mode == Mode::Edit; - - - let border_style = if is_selected { - Style::default().fg(Color::Blue) - } else { - Style::default() - }; - - let block = Block::default() - .title("Glyphs") - .border_style(border_style) - .borders(Borders::ALL) - .padding(Padding::new(2, 2, 1, 1)); - - let table_highlight = if is_selected { - Style::default().fg(Color::Blue) - } else { - Style::default() - }; - - let table = Table::new(savefile.glyphs.all().map(|(level_number, status)| { - let status = status - .iter() - .map(|&val| Cell::from(if val { FOUND_SIGN } else { NOT_FOUND_SIGN })); - Row::new( - [Cell::from(LEVEL_NAMES[level_number])] - .into_iter() - .chain(status), - ) - })) - .widths(&[ - Constraint::Length(20), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - ]) - .column_spacing(1) - .highlight_style(table_highlight) - .block(block); - - frame.render_stateful_widget(table, area, &mut state.glyphs_table); -} - - -fn render_murals<'a>(state: &mut State, frame: &mut Frame, area: Rect) { - const FOUND_SIGN: &str = "▾"; - const NOT_FOUND_SIGN: &str = "▿"; - - let Some(savefile) = state.savefile() else { - return - }; - - let is_selected = state.active_section == Section::Murals && state.mode == Mode::Edit; - - let border_style = if is_selected { - Style::default().fg(Color::Blue) - } else { - Style::default() - }; - - let block = Block::default() - .title("Murals") - .border_style(border_style) - .borders(Borders::ALL) - .padding(Padding::new(2, 2, 1, 1)); - - let table_highlight = if is_selected { - Style::default().fg(Color::Blue) - } else { - Style::default() - }; - - let table = Table::new(savefile.murals.all().map(|(level_number, status)| { - let status = status - .iter() - .map(|&val| Cell::from(if val { FOUND_SIGN } else { NOT_FOUND_SIGN })); - Row::new( - [Cell::from(LEVEL_NAMES[level_number])] - .into_iter() - .chain(status), - ) - })) - .widths(&[ - Constraint::Length(20), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - Constraint::Length(3), - ]) - .column_spacing(1) - .highlight_style(table_highlight) - .block(block); - - frame.render_stateful_widget(table, area, &mut state.murals_table); + stats::render(state, &mut frame, left_column[0]); + glyphs::render(state, &mut frame, left_column[1]); + murals::render(state, &mut frame, left_column[2]); + companions::render(state, &mut frame, right_column[0]); } diff --git a/crates/wayfarer/src/tui/view/info/companions.rs b/crates/wayfarer/src/tui/view/info/companions.rs new file mode 100644 index 0000000..2bc2fa5 --- /dev/null +++ b/crates/wayfarer/src/tui/view/info/companions.rs @@ -0,0 +1,63 @@ +use ratatui::layout::{Alignment, Constraint, Direction, Layout, Rect}; +use ratatui::style::Style; +use ratatui::widgets::{Block, Borders, Padding, Row, Table}; + +use crate::tui::state::{Mode, Section}; +use crate::tui::view::Frame; +use crate::tui::State; + + +pub(super) fn render<'a>(state: &State, frame: &mut Frame, area: Rect) { + let Some(savefile) = state.savefile() else { + return + }; + + let is_selected = state.active_section == Section::Companions && state.mode == Mode::Edit; + + let border_style = if is_selected { + Style::default().fg(ratatui::style::Color::Blue) + } else { + Style::default() + }; + + let companions_block = Block::default() + .title("Companions") + .padding(Padding::new(2, 2, 1, 1)) + .border_style(border_style) + .borders(Borders::ALL); + + let layout = Layout::default() + .direction(Direction::Vertical) + .constraints([Constraint::Ratio(1, 2), Constraint::Ratio(1, 2)]) + .split(companions_block.inner(area)); + + let current_companions_block = Block::default() + .title("Current") + .borders(Borders::TOP) + .title_alignment(Alignment::Center); + + let current_companions = Table::new( + savefile + .current_companions() + .map(|companion| Row::new([companion.name.clone(), companion.steam_url()])), + ) + .widths(&[Constraint::Ratio(1, 3), Constraint::Ratio(2, 3)]) + .block(current_companions_block); + + let past_companions_block = Block::default() + .title("Past") + .borders(Borders::TOP) + .title_alignment(Alignment::Center); + + let past_companions = Table::new( + savefile + .past_companions() + .map(|companion| Row::new([companion.name.clone(), companion.steam_url()])), + ) + .widths(&[Constraint::Ratio(1, 3), Constraint::Ratio(2, 3)]) + .block(past_companions_block); + + frame.render_widget(companions_block, area); + frame.render_widget(current_companions, layout[0]); + frame.render_widget(past_companions, layout[1]); +} diff --git a/crates/wayfarer/src/tui/view/info/glyphs.rs b/crates/wayfarer/src/tui/view/info/glyphs.rs new file mode 100644 index 0000000..b13ff85 --- /dev/null +++ b/crates/wayfarer/src/tui/view/info/glyphs.rs @@ -0,0 +1,65 @@ +use jrny_save::LEVEL_NAMES; +use ratatui::layout::{Constraint, Rect}; +use ratatui::style::{Color, Style}; +use ratatui::widgets::{Block, Borders, Cell, Padding, Row, Table}; + +use crate::tui::state::{Mode, Section}; +use crate::tui::view::Frame; +use crate::tui::State; + + +pub const TABLE_RANGE: (usize, usize) = (0, 5); + + +pub(super) fn render<'a>(state: &mut State, frame: &mut Frame, area: Rect) { + const FOUND_SIGN: &str = "◆"; + const NOT_FOUND_SIGN: &str = "◇"; + + let Some(savefile) = state.savefile() else { + return + }; + + let is_selected = state.active_section == Section::Glyphs && state.mode == Mode::Edit; + + + let border_style = if is_selected { + Style::default().fg(Color::Blue) + } else { + Style::default() + }; + + let block = Block::default() + .title("Glyphs") + .border_style(border_style) + .borders(Borders::ALL) + .padding(Padding::new(2, 2, 1, 1)); + + let table_highlight = if is_selected { + Style::default().fg(Color::Blue) + } else { + Style::default() + }; + + let table = Table::new(savefile.glyphs.all().map(|(level_number, status)| { + let status = status + .iter() + .map(|&val| Cell::from(if val { FOUND_SIGN } else { NOT_FOUND_SIGN })); + Row::new( + [Cell::from(LEVEL_NAMES[level_number])] + .into_iter() + .chain(status), + ) + })) + .widths(&[ + Constraint::Length(20), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + ]) + .column_spacing(1) + .highlight_style(table_highlight) + .block(block); + + frame.render_stateful_widget(table, area, &mut state.glyphs_table); +} diff --git a/crates/wayfarer/src/tui/view/info/murals.rs b/crates/wayfarer/src/tui/view/info/murals.rs new file mode 100644 index 0000000..47731fa --- /dev/null +++ b/crates/wayfarer/src/tui/view/info/murals.rs @@ -0,0 +1,64 @@ +use jrny_save::LEVEL_NAMES; +use ratatui::layout::{Constraint, Rect}; +use ratatui::style::{Color, Style}; +use ratatui::widgets::{Block, Borders, Cell, Padding, Row, Table}; + +use crate::tui::state::{Mode, Section}; +use crate::tui::view::Frame; +use crate::tui::State; + + +pub const TABLE_RANGE: (usize, usize) = (0, 6); + + +pub(super) fn render<'a>(state: &mut State, frame: &mut Frame, area: Rect) { + const FOUND_SIGN: &str = "▾"; + const NOT_FOUND_SIGN: &str = "▿"; + + let Some(savefile) = state.savefile() else { + return + }; + + let is_selected = state.active_section == Section::Murals && state.mode == Mode::Edit; + + let border_style = if is_selected { + Style::default().fg(Color::Blue) + } else { + Style::default() + }; + + let block = Block::default() + .title("Murals") + .border_style(border_style) + .borders(Borders::ALL) + .padding(Padding::new(2, 2, 1, 1)); + + let table_highlight = if is_selected { + Style::default().fg(Color::Blue) + } else { + Style::default() + }; + + let table = Table::new(savefile.murals.all().map(|(level_number, status)| { + let status = status + .iter() + .map(|&val| Cell::from(if val { FOUND_SIGN } else { NOT_FOUND_SIGN })); + Row::new( + [Cell::from(LEVEL_NAMES[level_number])] + .into_iter() + .chain(status), + ) + })) + .widths(&[ + Constraint::Length(20), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + ]) + .column_spacing(1) + .highlight_style(table_highlight) + .block(block); + + frame.render_stateful_widget(table, area, &mut state.murals_table); +} diff --git a/crates/wayfarer/src/tui/view/info/stats.rs b/crates/wayfarer/src/tui/view/info/stats.rs new file mode 100644 index 0000000..9c94395 --- /dev/null +++ b/crates/wayfarer/src/tui/view/info/stats.rs @@ -0,0 +1,82 @@ +use ratatui::layout::{Constraint, Direction, Layout, Rect}; +use ratatui::style::{Color, Style}; +use ratatui::widgets::{Block, Borders, Padding, Paragraph, Row, Table}; + +use crate::tui::state::{Mode, Section}; +use crate::tui::view::Frame; +use crate::tui::State; + + +pub const TABLE_RANGE: (usize, usize) = (0, 9); + + +pub(super) fn render<'a>(state: &mut State, frame: &mut Frame, area: Rect) { + let Some(savefile) = state.savefile() else { + return + }; + + let is_selected = state.active_section == Section::General && state.mode == Mode::Edit; + + let border_style = if is_selected { + Style::default().fg(Color::Blue) + } else { + Style::default() + }; + + let stats_section_block = Block::default() + .padding(Padding::new(2, 2, 1, 1)) + .border_style(border_style) + .borders(Borders::ALL); + + let layout = Layout::default() + .direction(Direction::Horizontal) + .constraints([Constraint::Percentage(25), Constraint::Percentage(75)]) + .split(stats_section_block.inner(area)); + + let stats_block = Block::default().title("Stats"); + + let table_highlight = if is_selected { + Style::default().fg(Color::Blue) + } else { + Style::default() + }; + + let table = Table::new([ + Row::new([ + "Journeys Completed".to_string(), + savefile.journey_count.to_string(), + ]), + Row::new([ + "Total Companions Met".to_string(), + savefile.total_companions_met.to_string(), + ]), + Row::new([ + "Total Symbols Collected".to_string(), + savefile.total_collected_symbols.to_string(), + ]), + Row::new(["Current Level", savefile.current_level_name()]), + Row::new([ + "Companions Met".to_string(), + savefile.companions_met.to_string(), + ]), + Row::new([ + "Scarf Length".to_string(), + savefile.scarf_length.to_string(), + ]), + Row::new(["Symbol Number".to_string(), savefile.symbol.id.to_string()]), + Row::new(["Robe Color".to_string(), savefile.robe_color().to_string()]), + Row::new(["Robe Tier".to_string(), savefile.robe_tier().to_string()]), + Row::new(["Last Played".to_string(), savefile.last_played.to_string()]), + ]) + .highlight_style(table_highlight) + .widths(&[Constraint::Ratio(1, 3), Constraint::Ratio(2, 3)]) + .block(stats_block); + + let cur_symbol_block = Block::default(); + + let cur_symbol = Paragraph::new(savefile.symbol.to_string()).block(cur_symbol_block); + + frame.render_widget(stats_section_block, area); + frame.render_widget(cur_symbol, layout[0]); + frame.render_stateful_widget(table, layout[1], &mut state.stats_table); +}