Added a help popup

This commit is contained in:
2025-03-09 00:54:34 +00:00
parent 30884d7c35
commit e86c705b5b

View File

@@ -6,7 +6,7 @@ use ratatui::{
layout::{Constraint, Layout, Rect, Flex}, layout::{Constraint, Layout, Rect, Flex},
style::{Style, Stylize, Color}, style::{Style, Stylize, Color},
text::Line, text::Line,
widgets::{Block, BorderType, Borders, Paragraph}, widgets::{Block, BorderType, Borders, Paragraph, Clear, Wrap},
DefaultTerminal, Frame, DefaultTerminal, Frame,
}; };
@@ -18,6 +18,7 @@ pub struct App {
// I should think about making this a Vec so I can highlight a whole stack which is about to move // I should think about making this a Vec so I can highlight a whole stack which is about to move
selected_card: Option<card_stuffs::Card>, selected_card: Option<card_stuffs::Card>,
exit: bool, exit: bool,
show_help: bool,
} }
const CARD_HEIGHT: u16 = 11; const CARD_HEIGHT: u16 = 11;
@@ -69,26 +70,6 @@ fn draw_waste(cards_in_waste: &Vec<card_stuffs::Card>, area: Rect, frame: &mut F
} }
fn deck_widget(cards_in_deck: &Vec<card_stuffs::Card>) -> Paragraph<'static> {
let card_image = format!(
"#############\n\
#############\n\
### Cards ###\n\
### Left ###\n\
#############\n\
#### {:02} #####\n\
#############\n\
#############\n\
#############", cards_in_deck.len()
);
Paragraph::new(card_image)
.block(Block::new()
.borders(Borders::ALL)
.border_type(BorderType::Rounded))
}
fn card_widget<'a>(card: &'a card_stuffs::Card, top: bool, highlight: bool, select: bool) -> Paragraph<'a> { fn card_widget<'a>(card: &'a card_stuffs::Card, top: bool, highlight: bool, select: bool) -> Paragraph<'a> {
if !card.visible { if !card.visible {
return facedown_card(top); return facedown_card(top);
@@ -121,80 +102,6 @@ fn card_widget<'a>(card: &'a card_stuffs::Card, top: bool, highlight: bool, sele
.border_type(BorderType::Rounded)) .border_type(BorderType::Rounded))
} }
fn partially_covered_card(card: &card_stuffs::Card) -> Paragraph {
let card_image = format!(
"{value}{suit}", value=card.value, suit=card.suit
);
let card_style = match card.suit.colour() {
card_stuffs::Colour::Black => Style::new().black().bg(Color::White),
card_stuffs::Colour::Red => Style::new().red().bg(Color::White),
};
let borders = Borders::TOP | Borders::LEFT | Borders::BOTTOM;
let border_style = Style::new().white().on_black();
Paragraph::new(card_image)
.style(card_style)
.block(Block::new()
.style(border_style)
.borders(borders)
.border_type(BorderType::Rounded))
}
/*
struct CardWidget {
card: card_stuffs::Card,
// put display stuff in here?
}
impl Widget for CardWidget {
fn render(self, area: Rect, buf: &mut Buffer) {
let mut border_style = Style::default();
}
}
*/
fn facedown_card(top: bool) -> Paragraph<'static> {
let hidden_card = format!(
"#############\n\
#############\n\
#############\n\
#############\n\
#############\n\
#############\n\
#############\n\
#############\n\
#############"
);
let mut borders = Borders::TOP | Borders::LEFT | Borders::RIGHT;
if top {
borders |= Borders::BOTTOM;
}
Paragraph::new(hidden_card)
.block(Block::new()
.borders(borders)
.border_type(BorderType::Rounded))
}
fn empty_pile() -> Paragraph<'static> {
// made using https://www.asciiart.eu/
let hidden_card = format!(
"
XX XX
XX XX
X X
X X
X X
XXXXXXX"
);
Paragraph::new(hidden_card)
.block(Block::new()
.borders(Borders::ALL)
.border_type(BorderType::Rounded))
}
impl App { impl App {
/// runs the application's main loop until the user quits /// runs the application's main loop until the user quits
@@ -207,12 +114,13 @@ impl App {
} }
fn draw(&self, frame: &mut Frame) { fn draw(&self, frame: &mut Frame) {
let area = frame.area();
let vertical = Layout::vertical([ let vertical = Layout::vertical([
Constraint::Length(1), Constraint::Length(1),
Constraint::Min(0), Constraint::Min(0),
Constraint::Length(1), Constraint::Length(1),
]); ]);
let [title_bar, main_area, status_bar] = vertical.areas(frame.area()); let [title_bar, main_area, status_bar] = vertical.areas(area);
frame.render_widget( frame.render_widget(
Block::new() Block::new()
@@ -222,7 +130,7 @@ impl App {
title_bar title_bar
); );
let status_bar_info = format!("Cards Per-Draw: {} ---- Times Through Deck: {} ", self.cards.num_cards_turned, self.cards.current_num_passes_through_deck); let status_bar_info = format!("Cards Per-Draw: {} ---- Times Through Deck: {} ---- Press 'h' for Help ", self.cards.num_cards_turned, self.cards.current_num_passes_through_deck);
frame.render_widget( frame.render_widget(
Block::new().borders(Borders::TOP).title(status_bar_info), Block::new().borders(Borders::TOP).title(status_bar_info),
status_bar status_bar
@@ -313,6 +221,23 @@ impl App {
} }
} }
} }
if self.show_help {
let block = Block::bordered().title("Help");
let text =
"You are playing \"Legends of Soltar\" - a Klondike thingy
Press 'q' to Quit
Press '1' or '3' to change the number of cards you draw from the deck
Press 'd' to draw from your deck
Press 'w' to put the waste pile back into the deck (you can only do this when the waste is empty)";
let p = Paragraph::new(text).wrap(Wrap { trim: true });
let vertical = Layout::vertical([Constraint::Max(10)]).flex(Flex::Center);
let horizontal = Layout::horizontal([Constraint::Percentage(70)]).flex(Flex::Center);
let [area] = vertical.areas(area);
let [area] = horizontal.areas(area);
frame.render_widget(Clear, area);
frame.render_widget(p.block(block), area);
}
} }
fn handle_events(&mut self) -> io::Result<()> { fn handle_events(&mut self) -> io::Result<()> {
@@ -334,6 +259,7 @@ impl App {
KeyCode::Char('w') => self.cards.waste_to_deck(), KeyCode::Char('w') => self.cards.waste_to_deck(),
KeyCode::Char('1') => self.cards.num_cards_turned = 1, KeyCode::Char('1') => self.cards.num_cards_turned = 1,
KeyCode::Char('3') => self.cards.num_cards_turned = 3, KeyCode::Char('3') => self.cards.num_cards_turned = 3,
KeyCode::Char('h') => self.show_help = !self.show_help, // toggle
_ => {} _ => {}
} }
} }
@@ -351,6 +277,86 @@ fn main() -> io::Result<()> {
} }
fn deck_widget(cards_in_deck: &Vec<card_stuffs::Card>) -> Paragraph<'static> {
let card_image = format!(
"#############\n\
#############\n\
### Cards ###\n\
### Left ###\n\
#############\n\
#### {:02} #####\n\
#############\n\
#############\n\
#############", cards_in_deck.len()
);
Paragraph::new(card_image)
.block(Block::new()
.borders(Borders::ALL)
.border_type(BorderType::Rounded))
}
fn partially_covered_card(card: &card_stuffs::Card) -> Paragraph {
let card_image = format!(
"{value}{suit}", value=card.value, suit=card.suit
);
let card_style = match card.suit.colour() {
card_stuffs::Colour::Black => Style::new().black().bg(Color::White),
card_stuffs::Colour::Red => Style::new().red().bg(Color::White),
};
let borders = Borders::TOP | Borders::LEFT | Borders::BOTTOM;
let border_style = Style::new().white().on_black();
Paragraph::new(card_image)
.style(card_style)
.block(Block::new()
.style(border_style)
.borders(borders)
.border_type(BorderType::Rounded))
}
fn facedown_card(top: bool) -> Paragraph<'static> {
let hidden_card = format!(
"#############\n\
#############\n\
#############\n\
#############\n\
#############\n\
#############\n\
#############\n\
#############\n\
#############"
);
let mut borders = Borders::TOP | Borders::LEFT | Borders::RIGHT;
if top {
borders |= Borders::BOTTOM;
}
Paragraph::new(hidden_card)
.block(Block::new()
.borders(borders)
.border_type(BorderType::Rounded))
}
fn empty_pile() -> Paragraph<'static> {
// made using https://www.asciiart.eu/
let hidden_card = format!(
"
XX XX
XX XX
X X
X X
X X
XXXXXXX"
);
Paragraph::new(hidden_card)
.block(Block::new()
.borders(Borders::ALL)
.border_type(BorderType::Rounded))
}
fn card_paragraph(c: &card_stuffs::Card) -> String { fn card_paragraph(c: &card_stuffs::Card) -> String {
match c.value { match c.value {