Added deck and the start of the waste

I think I'm going to need some mode advanced widget that I make myself though
This commit is contained in:
2025-02-26 19:26:17 +00:00
parent dcbcb92376
commit 0ae0bf73b2
2 changed files with 105 additions and 21 deletions

View File

@@ -97,6 +97,7 @@ impl fmt::Display for Value {
}
}
#[derive(PartialEq, Debug, Copy, Clone)]
pub struct Card {
pub suit: Suit,

View File

@@ -1,27 +1,88 @@
use std::io;
use card_stuffs::{self, NUM_PILES_KLONDIKE};
use card_stuffs::{self};
use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind};
use ratatui::{
buffer::Buffer,
layout::{Constraint, Layout, Rect, Flex},
style::{Style, Stylize, Color},
symbols::border,
text::{Line, Text},
widgets::{block::title, Block, BorderType, Borders, Paragraph, Widget, Padding, ListItem, List},
text::Line,
widgets::{Block, BorderType, Borders, ListItem, List},
DefaultTerminal, Frame,
};
#[derive(Debug, Default)]
pub struct App {
cards: card_stuffs::Klondike,
// There aren't pretty... not sure what else I can do about that though...
highlighted_card: Option<card_stuffs::Card>,
// 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>,
exit: bool,
}
const CARD_HEIGHT: u16 = 11;
const CARD_WIDTH: u16 = 15;
fn card_widget(card: &card_stuffs::Card, top: bool) -> List {
fn waste_widget(cards_in_waste: &Vec<card_stuffs::Card>) -> List {
let mut cards_to_display = Vec::new();
if cards_in_waste.len() >= 3 {
cards_to_display.push(cards_in_waste.windows(3).last());
} else if cards_in_waste.len() == 2 {
cards_to_display.push(cards_in_waste.windows(2).last());
} else if cards_in_waste.len() == 1 {
cards_to_display.push(cards_in_waste.windows(1).last());
}
// Eeeek - we're no longer a basic "List"... I think maybe I need
// a new widget I've make myself... I probably should do that for all cards
// to be toootaly honest
let hidden_card = [
format!("#############"),
format!("#############"),
format!("#############"),
format!("#####TODO####"),
format!("#############"),
format!("#############"),
format!("#############"),
format!("#############"),
format!("#############"),
];
let card_image: Vec<ListItem> = hidden_card.iter().map(|m| {
ListItem::new(m.to_string())
})
.collect();
List::new(card_image)
.block(Block::new()
.borders(Borders::ALL)
.border_type(BorderType::Rounded))
}
fn deck_widget(cards_in_deck: &Vec<card_stuffs::Card>) -> List<'static> {
let hidden_card = [
format!("#############"),
format!("#############"),
format!("### Cards ###"),
format!("### Left ###"),
format!("#############"),
format!("#### {:02} #####", cards_in_deck.len()),
format!("#############"),
format!("#############"),
format!("#############"),
];
let card_image: Vec<ListItem> = hidden_card.iter().map(|m| {
ListItem::new(m.to_string())
})
.collect();
List::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) -> List<'a> {
let five_card = [
format!("{value}{suit} ", value=card.value, suit=card.suit),
format!(" "),
@@ -37,7 +98,7 @@ fn card_widget(card: &card_stuffs::Card, top: bool) -> List {
card_stuffs::Colour::Black => Style::new().black().bg(Color::White),
card_stuffs::Colour::Red => Style::new().red().bg(Color::White),
};
let card: Vec<ListItem> = five_card.iter().map(|m| {
let card_image: Vec<ListItem> = five_card.iter().map(|m| {
ListItem::new(m.to_string())
.style(card_style)
})
@@ -48,12 +109,18 @@ fn card_widget(card: &card_stuffs::Card, top: bool) -> List {
borders |= Borders::BOTTOM;
}
List::new(card)
let mut border_style = Style::default();
if highlight {
border_style = border_style.fg(Color::Blue);
} else if select {
border_style = border_style.fg(Color::Green);
}
List::new(card_image)
.block(Block::new()
//.style(Style::new().red().bold().italic())
// Might use something like this for "active"/"selected"
.borders(borders)
.border_type(BorderType::Rounded))
.style(border_style)
.borders(borders)
.border_type(BorderType::Rounded))
}
fn turned_over_card(top: bool) -> List<'static> {
@@ -66,6 +133,7 @@ fn turned_over_card(top: bool) -> List<'static> {
format!("#############"),
format!("#############"),
format!("#############"),
format!("#############"),
];
let card: Vec<ListItem> = hidden_card.iter().map(|m| {
ListItem::new(m.to_string())
@@ -84,7 +152,6 @@ fn turned_over_card(top: bool) -> List<'static> {
}
impl App {
/// runs the application's main loop until the user quits
pub fn run(&mut self, terminal: &mut DefaultTerminal) -> io::Result<()> {
while !self.exit {
@@ -100,7 +167,7 @@ impl App {
Constraint::Min(0),
Constraint::Length(1),
]);
let [title_bar, main_area, status_bar] = vertical.areas(frame.area());
let [title_bar, main_area, _status_bar] = vertical.areas(frame.area());
frame.render_widget(
Block::new()
@@ -111,19 +178,32 @@ impl App {
);
let vertical = Layout::vertical([
Constraint::Length(CARD_HEIGHT + 2), // for padding
Constraint::Length(CARD_HEIGHT),
Constraint::Min(0)
]);
let [dwf_area, piles_area] = vertical.areas(main_area);
let horizontal = Layout::horizontal([
Constraint::Length(CARD_WIDTH),
Constraint::Length(3 + 3 + CARD_WIDTH), // 3+3 for 2 cards shown underneath
Constraint::Length(CARD_WIDTH),
Constraint::Length(CARD_WIDTH),
Constraint::Length(CARD_WIDTH),
Constraint::Length(CARD_WIDTH),
]).flex(Flex::SpaceAround);
let [deck_area, waste_area, fa, fb, fc, fd] = horizontal.areas(dwf_area);
let _foundation_areas = [fa, fb, fc, fd];
frame.render_widget(
Block::new().borders(Borders::ALL).title("dwf_area"),
dwf_area
deck_widget(&self.cards.deck),
deck_area
);
frame.render_widget(
Block::new().borders(Borders::ALL).title("piles_area"),
piles_area
waste_widget(&self.cards.waste),
waste_area
);
let horizontal = Layout::horizontal([
Constraint::Length(CARD_WIDTH),
Constraint::Length(CARD_WIDTH),
@@ -154,15 +234,18 @@ impl App {
}
let vertical = Layout::vertical(constraints);
let card_display: [Rect; card_stuffs::NUM_PILES_KLONDIKE + 13] = vertical.areas(pileses[pile]);
for (i, card) in card_display.iter().enumerate() {
match self.cards.piles[pile].get(i) {
None => break,
Some(c) => {
let is_top_card = i == self.cards.piles[pile].len() - 1;
let highlight = self.highlighted_card.is_some() && *c == self.highlighted_card.unwrap();
let selected = self.selected_card.is_some() && *c == self.selected_card.unwrap();
let a_card = match c.visible {
true => card_widget(c, is_top_card),
true => card_widget(c, is_top_card, highlight, selected),
//false => turned_over_card(is_top_card),
false => card_widget(c, is_top_card),
false => card_widget(c, is_top_card, highlight, selected),
};
frame.render_widget(
&a_card,