diff --git a/src/ui/debug_view.rs b/src/ui/debug_view.rs index 60fc60e..41c4270 100644 --- a/src/ui/debug_view.rs +++ b/src/ui/debug_view.rs @@ -56,7 +56,7 @@ impl<'a> DebugView<'a> { view } - pub fn control(&mut self) -> (bool, Option) { + pub fn control(&mut self, _game: &mut Game) -> (bool, Option) { match read() { Ok(Event::Key(event)) => { match event.code { diff --git a/src/ui/guest_selection.rs b/src/ui/guest_selection.rs new file mode 100644 index 0000000..640fba7 --- /dev/null +++ b/src/ui/guest_selection.rs @@ -0,0 +1,100 @@ +use crossterm::event::{read, Event, KeyCode}; +use tui::{backend::Backend, Frame}; + +use crate::game::Game; + +use super::{AppStatus, DefaultLayout, controls::Controls, status_line::StatusLine}; + +pub struct GuestSelectionView<'a> { + guest_list: Vec>, + guest_list_state: tui::widgets::ListState, +} + +impl<'a> GuestSelectionView<'a> { + pub fn new(game: &Game) -> GuestSelectionView<'a> { + let guest_list = game.state.guests().iter().map(|creature_id| { + let creature = game.state.get_creature(*creature_id).unwrap(); + tui::widgets::ListItem::new(format!( + "{} ({}, {} items)", + creature.name, + creature.profession, game.state.get_inventory(creature.entity.id).len() + )) + }).collect(); + let mut guest_list_state = tui::widgets::ListState::default(); + guest_list_state.select(Some(0)); + + GuestSelectionView { + guest_list, + guest_list_state, + } + } + + pub fn control(&mut self, game: &mut Game) -> (bool, Option) { + match read() { + Ok(Event::Key(event)) => { + match event.code { + KeyCode::Up => { + let selected = self.guest_list_state.selected().unwrap(); + if selected > 0 { + self.guest_list_state.select(Some(selected - 1)); + } + }, + KeyCode::Down => { + let selected = self.guest_list_state.selected().unwrap(); + if selected < self.guest_list.len() - 1 { + self.guest_list_state.select(Some(selected + 1)); + } + }, + KeyCode::Enter => { + if game.state.guests().len() > 0 { + match self.guest_list_state.selected() { + Some(selected) => { + // let guest_id = &self.game.state.guests()[selected]; + // self.conversation = Chat::new(); + // self.greet_guest(Some(*guest_id)); + // self.status = AppStatus::TalkToGuest(Some(*guest_id)); + }, + None => {} + } + } + }, + KeyCode::Char('?') => { + return (true, Some(AppStatus::Debug)) + }, + KeyCode::Char('.') => { + game.step(); + return (true, Some(AppStatus::Initial)); + }, + KeyCode::Esc => { + return (false, None); + }, + _ => {} + } + }, + _ => {} + } + (true, None) + } + + pub fn draw(&mut self, f: &mut Frame, game: &Game) { + let chunks = DefaultLayout::default(f.size()); + + let main_window = tui::widgets::List::new(self.guest_list.clone()) + .block(tui::widgets::Block::default().title("Guests").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("↑↓".to_owned(), "select guest".to_owned()) + .add("⏎".to_owned(), "talk to guest".to_owned()) + .add(".".to_owned(), "pass one day".to_owned()) + .add("Esc".to_owned(), "quit".to_owned()) + .render(); + + StatusLine::draw(f, chunks.status, game); + f.render_stateful_widget(main_window, chunks.main, &mut self.guest_list_state); + f.render_widget(controls, chunks.controls); + } +} \ No newline at end of file diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 93a2103..055a234 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -1,6 +1,7 @@ mod chat; mod controls; mod debug_view; +mod guest_selection; mod status_line; use crossterm::event::{read, Event, KeyCode}; @@ -8,7 +9,7 @@ use tui::{backend::Backend, Frame, layout::Layout}; use crate::{game::Game, entity::{EntityId, EntityType}, world::Terrain}; -use self::{chat::{Chat, ChatLine}, controls::Controls, debug_view::DebugView}; +use self::{chat::{Chat, ChatLine}, controls::Controls, debug_view::DebugView, guest_selection::GuestSelectionView}; /** * |........................| @@ -32,15 +33,14 @@ pub struct App<'a> { status: AppStatus, // Guest Selection - guest_list: Vec>, - guest_list_state: tui::widgets::ListState, + guest_selection: Option>, // Conversation conversation: Chat, conversation_scroll: u16, // Debug - debug_view: Option>, + debug_view: Option>, } pub struct DefaultLayout { @@ -74,8 +74,7 @@ impl<'a> App<'a> { pub fn new(state: Game) -> App<'a> { App { game: state, - guest_list: vec![], - guest_list_state: tui::widgets::ListState::default(), + guest_selection: None, status: AppStatus::Initial, conversation: Chat::new(), conversation_scroll: 0, @@ -86,65 +85,17 @@ impl<'a> App<'a> { pub fn step(&mut self) -> bool { match &self.status { AppStatus::Initial => { - // determine guests - self.guest_list = self.game.state.guests().iter().map(|creature_id| { - let creature = self.game.state.get_creature(*creature_id).unwrap(); - tui::widgets::ListItem::new(format!( - "{} ({}, {} items)", - creature.name, - creature.profession, self.game.state.get_inventory(creature.entity.id).len() - )) - }).collect(); - self.guest_list_state = tui::widgets::ListState::default(); - self.guest_list_state.select(Some(0)); + self.guest_selection = Some(GuestSelectionView::new(&self.game)); self.status = AppStatus::GuestSelection; true }, AppStatus::GuestSelection => { - match read() { - Ok(Event::Key(event)) => { - match event.code { - KeyCode::Up => { - let selected = self.guest_list_state.selected().unwrap(); - if selected > 0 { - self.guest_list_state.select(Some(selected - 1)); - } - }, - KeyCode::Down => { - let selected = self.guest_list_state.selected().unwrap(); - if selected < self.guest_list.len() - 1 { - self.guest_list_state.select(Some(selected + 1)); - } - }, - KeyCode::Enter => { - if self.game.state.guests().len() > 0 { - match self.guest_list_state.selected() { - Some(selected) => { - let guest_id = &self.game.state.guests()[selected]; - self.conversation = Chat::new(); - self.greet_guest(Some(*guest_id)); - self.status = AppStatus::TalkToGuest(Some(*guest_id)); - }, - None => {} - } - } - }, - KeyCode::Char('?') => { - self.open_debug(); - }, - KeyCode::Char('.') => { - self.game.step(); - self.status = AppStatus::Initial; - }, - KeyCode::Esc => { - return false; - }, - _ => {} - } - }, - _ => {} + let ret = self.guest_selection.as_mut().unwrap().control(&mut self.game); + if let Some(next) = ret.1 { + self.debug_view = None; + self.status = next; } - true + ret.0 }, AppStatus::TalkToGuest(guest) => { match read() { @@ -189,7 +140,7 @@ impl<'a> App<'a> { true }, AppStatus::Debug => { - let ret = self.debug_view.as_mut().unwrap().control(); + let ret = self.debug_view.as_mut().unwrap().control(&mut self.game); if let Some(next) = ret.1 { self.debug_view = None; self.status = next; @@ -214,7 +165,7 @@ impl<'a> App<'a> { self.draw_initial(f); }, AppStatus::GuestSelection => { - self.draw_guest_selection(f); + self.guest_selection.as_mut().unwrap().draw(f, &self.game); }, AppStatus::TalkToGuest(guest_id) => { self.draw_talk_to_guest(f, *guest_id); @@ -252,28 +203,6 @@ impl<'a> App<'a> { pub fn draw_initial(&mut self, _f: &mut Frame) {} - pub fn draw_guest_selection(&mut self, f: &mut Frame) { - let chunks = DefaultLayout::default(f.size()); - - let main_window = tui::widgets::List::new(self.guest_list.clone()) - .block(tui::widgets::Block::default().title("Guests").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("↑↓".to_owned(), "select guest".to_owned()) - .add("⏎".to_owned(), "talk to guest".to_owned()) - .add(".".to_owned(), "pass one day".to_owned()) - .add("Esc".to_owned(), "quit".to_owned()) - .render(); - - self.draw_status(f, chunks.status); - f.render_stateful_widget(main_window, chunks.main, &mut self.guest_list_state); - f.render_widget(controls, chunks.controls); - } - fn draw_talk_to_guest(&self, f: &mut Frame, guest: Option) { let chunks = DefaultLayout::default(f.size());