You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

132 lines
3.9 KiB

use crate::traits::Render;
use crate::State;
use rltk::prelude::*;
use rltk::DrawBatch;
use rltk::Rltk;
use std::fmt::Display;
pub type Inventory = Vec<Item>;
#[derive(Clone)]
pub struct InventoryView {
pub inv: Inventory,
pub selected_item: usize,
detail_menu: Option<Vec<Action>>,
detail_selected_item: usize,
}
impl InventoryView {
pub fn new(inv: Inventory) -> Self {
Self {
inv,
detail_menu: None,
detail_selected_item: 0,
selected_item: 0,
}
}
/// If possible, decreases the current position of the item or action
pub fn selection_up(&mut self) {
match &self.detail_menu {
Some(_) => match self.detail_selected_item {
0 => {}
_ => self.detail_selected_item -= 1,
},
None => match self.selected_item {
0 => {}
_ => self.selected_item -= 1,
},
}
}
/// If possible, increases the current position of the item or action
pub fn selection_down(&mut self) {
match &self.detail_menu {
Some(menu) => match self.detail_selected_item {
n if n >= menu.len() => {}
_ => self.detail_selected_item += 1,
},
None => match self.selected_item {
n if n >= self.inv.len() => {}
_ => self.selected_item += 1,
},
}
}
pub fn select(&mut self) {
let item = &self.inv[self.selected_item];
let mut menu = Vec::new();
// TODO: cloning here might lead to problems later.
// We should probably use a lifetime instead
menu.push(Action::EquipLeft(item.clone()));
menu.push(Action::EquipRight(item.clone()));
menu.push(Action::ThrowAway(item.clone()));
self.detail_menu = Some(menu);
}
}
#[derive(Clone)]
enum Action {
EquipRight(Item),
EquipLeft(Item),
ThrowAway(Item),
}
impl Display for Action {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
match self {
Self::EquipLeft(_) => f.write_str("Equip left"),
Self::EquipRight(_) => f.write_str("Equip right"),
Self::ThrowAway(_) => f.write_str("Drop"),
}
}
}
#[derive(Clone)]
pub struct Item {
pub name: String,
}
impl Render for InventoryView {
fn render(&mut self, _gs: &mut State, ctx: &mut Rltk) {
let mut draw_batch = DrawBatch::new();
ctx.cls();
for (i, item) in self.inv.iter().enumerate() {
// Set color, based on if the item is selected
let color = match self.selected_item {
// CLEANUP: self.detail_menu.is_none gets checked twice in this method
j if j == i && self.detail_menu.is_none() => {
ColorPair::new(rltk::BLACK, rltk::WHITE)
}
_ => ColorPair::new(rltk::WHITE, rltk::BLACK),
};
draw_batch.print_color(Point::new(4, i * 2 + 1), &item.name, color);
if self.selected_item == i && self.detail_menu.is_none() {
draw_batch.print_color(
Point::new(1, i * 2 + 1),
"->",
ColorPair::new(rltk::WHITE, rltk::BLACK),
);
}
}
if let Some(menu) = &self.detail_menu {
for (i, action) in menu.iter().enumerate() {
// Set color, based on if the item is selected
let color = match self.detail_selected_item {
j if j == i => ColorPair::new(rltk::BLACK, rltk::WHITE),
_ => ColorPair::new(rltk::WHITE, rltk::BLACK),
};
draw_batch.print_color(Point::new(50, i * 2 + 1), action, color);
}
}
draw_batch.submit(0).expect("Batch error");
render_draw_buffer(ctx).expect("Render error");
}
}