mod chat; mod controls; mod debug_view; mod guest_selection; mod talk_to_guest; mod status_line; use crossterm::event::{read, Event, KeyCode}; use tui::{backend::Backend, Frame, layout::Layout, Terminal}; use crate::{game::Game, entity::{EntityId, EntityType}, world::Terrain}; use self::{chat::{Chat, ChatLine}, controls::Controls, debug_view::DebugView, guest_selection::GuestSelectionView, talk_to_guest::TalkToGuestView}; /** * |........................| * | Conversations/Selection| * | | * |........................| * | Available Options | * |........................| */ pub enum AppStatus { Initial, GuestSelection(GuestSelectionView), TalkToGuest(TalkToGuestView), BuyFromGuest(EntityId), Debug(DebugView), } pub struct App { game: Game, status: AppStatus, } pub struct DefaultLayout { pub status: tui::layout::Rect, pub main: tui::layout::Rect, pub controls: tui::layout::Rect, } impl DefaultLayout { pub fn default(rect: tui::layout::Rect) -> DefaultLayout { let chunks = Layout::default() .direction(tui::layout::Direction::Vertical) .constraints( [ tui::layout::Constraint::Length(1), tui::layout::Constraint::Min(3), tui::layout::Constraint::Length(2) ] .as_ref(), ).split(rect); DefaultLayout { status: chunks[0], main: chunks[1], controls: chunks[2], } } } impl App { pub fn new(state: Game) -> App { App { game: state, status: AppStatus::Initial, } } pub fn step(&mut self) -> bool { let mut ret = (true, None); match &mut self.status { AppStatus::Initial => { ret.1 = Some(AppStatus::GuestSelection(GuestSelectionView::new(&self.game))); }, AppStatus::GuestSelection(ref mut guest_selection) => { ret = guest_selection.control(&mut self.game); }, AppStatus::TalkToGuest(talk_view) => { ret = talk_view.control(&mut self.game); }, AppStatus::BuyFromGuest(guest_id) => { // match read() { // Ok(Event::Key(event)) => { // match event.code { // KeyCode::Esc => { // self.status = AppStatus::TalkToGuest(Some(*guest_id)); // }, // _ => {} // } // }, // _ => {} // } }, AppStatus::Debug(debug_view) => { ret = debug_view.control(&mut self.game); } } if let Some(next_status) = ret.1 { self.status = next_status; } ret.0 } fn open_debug(&mut self) { self.status = AppStatus::Debug(DebugView::new(&self.game)); } // fn default_layout(&self) -> Layout { // DefaultLayout::default() // } pub fn draw(&mut self, f: &mut Frame) { match &mut self.status { AppStatus::Initial => { self.draw_initial(f); }, AppStatus::GuestSelection(view) => { view.draw(f, &self.game); }, AppStatus::TalkToGuest(view) => { view.draw(f, &self.game); }, AppStatus::BuyFromGuest(guest_id) => { // self.draw_buy_from_guest(f, *guest_id); }, AppStatus::Debug(view) => { view.draw(f, &self.game); }, } } fn draw_status(&self, f: &mut Frame, rect: tui::layout::Rect) { let tavern = self.game.state.world.get_site( self.game.state.tavern.unwrap() ).unwrap(); let spans = tui::text::Spans::from(vec![ tui::text::Span::raw("Date: "), tui::text::Span::raw(format!("{}", self.game.state.time)), tui::text::Span::raw(" "), tui::text::Span::raw("Funds: "), tui::text::Span::raw(format!("{} gold coins", tavern.coins)), ]); let status_text = tui::widgets::Paragraph::new(spans) .block(tui::widgets::Block::default().borders(tui::widgets::Borders::LEFT | tui::widgets::Borders::RIGHT)) .style(tui::style::Style::default().fg(tui::style::Color::White)); f.render_widget(status_text, rect); } pub fn draw_initial(&mut self, _f: &mut Frame) {} fn draw_buy_from_guest(&self, f: &mut Frame, guest_id: EntityId) { let chunks = DefaultLayout::default(f.size()); let guest = self.game.state.get_creature(guest_id).unwrap(); let inventory = self.game.state.get_inventory(guest_id); let mut list_items = vec![]; for item in inventory { let item = self.game.state.get_item(item).unwrap(); list_items.push(tui::widgets::ListItem::new(format!("{} ({} gold)", item.name, item.value()))); } let main_window = tui::widgets::List::new(list_items) .block(tui::widgets::Block::default().title(guest.name.clone()).borders(tui::widgets::Borders::ALL)) .style(tui::style::Style::default().fg(tui::style::Color::White)) .highlight_style(tui::style::Style::default().add_modifier(tui::style::Modifier::ITALIC)) .highlight_symbol(">>"); let mut binding = Controls::new(); let controls = binding .add("a-z".to_owned(), "Select".to_owned()) .add("Esc".to_owned(), "Back".to_owned()) .render(); self.draw_status(f, chunks.status); f.render_widget(main_window, chunks.main); f.render_widget(controls, chunks.controls); } }