diff --git a/src/app/app.rs b/src/app/app.rs index c49c034..78a4bee 100644 --- a/src/app/app.rs +++ b/src/app/app.rs @@ -60,7 +60,7 @@ impl App { let Some(state) = self.states_mut() else { panic!("State issue") }; - state.skirmish.board.resize_change(&window_area); + state.skirmish.board.change_resize(&window_area); } } } diff --git a/src/app/keybindings/keybindings.rs b/src/app/keybindings/keybindings.rs index 6aa75a9..0249aa7 100644 --- a/src/app/keybindings/keybindings.rs +++ b/src/app/keybindings/keybindings.rs @@ -197,17 +197,17 @@ pub static KEYBINDINGS: &[KeyBinding] = &[ modifiers: KeyModifiers::NONE, group: Group::Select, symbol: "Space", - description: "Select", - }, - KeyBinding { - action: Action::Enter, - code: KeyCode::Enter, - kind: KeyEventKind::Press, - modifiers: KeyModifiers::NONE, - group: Group::Select, - symbol: "Enter", - description: "Submit", + description: "Marking cells", }, + // KeyBinding { + // action: Action::Enter, + // code: KeyCode::Enter, + // kind: KeyEventKind::Press, + // modifiers: KeyModifiers::NONE, + // group: Group::Select, + // symbol: "Enter", + // description: "Submit", + // }, KeyBinding { action: Action::Esc, code: KeyCode::Esc, @@ -222,9 +222,9 @@ pub static KEYBINDINGS: &[KeyBinding] = &[ code: KeyCode::Backspace, kind: KeyEventKind::Press, modifiers: KeyModifiers::NONE, - group: Group::Input, + group: Group::Select, symbol: "Backspace", - description: "Delete character", + description: "Cancel marking", }, KeyBinding { action: Action::ZoomIn, diff --git a/src/app/keybindings/skirmish.rs b/src/app/keybindings/skirmish.rs index 15080b6..f65ab2e 100644 --- a/src/app/keybindings/skirmish.rs +++ b/src/app/keybindings/skirmish.rs @@ -62,27 +62,40 @@ pub fn skirmish_keybindings(app: &mut App, key_event: &KeyEvent) { Action::ZoomIn => match board.zoom_level { ZoomLevel::ZoomedIn => {} ZoomLevel::Default => { - board.zoom_change(ZoomLevel::ZoomedIn); + board.change_zoom(ZoomLevel::ZoomedIn); board.vertical_offset.next(); } ZoomLevel::ZoomedOut => { - board.zoom_change(ZoomLevel::Default); + board.change_zoom(ZoomLevel::Default); board.vertical_offset.next(); board.vertical_offset.next(); } }, Action::ZoomOut => match board.zoom_level { ZoomLevel::ZoomedIn => { - board.zoom_change(ZoomLevel::Default); + board.change_zoom(ZoomLevel::Default); board.vertical_offset.prev(); } ZoomLevel::Default => { - board.zoom_change(ZoomLevel::ZoomedOut); + board.change_zoom(ZoomLevel::ZoomedOut); board.vertical_offset.prev(); board.vertical_offset.prev(); } ZoomLevel::ZoomedOut => {} }, + Action::Space => { + if board.marking_cells { + board.marking_cells = false; + board.clear_marked_cells(); + } else { + board.marking_cells = true; + board.start_marking_cells(); + } + } + Action::Backspace => { + board.marking_cells = false; + board.clear_marked_cells() + } _ => (), } } diff --git a/src/app/states/skirmish_states/board.rs b/src/app/states/skirmish_states/board.rs index 77df666..20cb84b 100644 --- a/src/app/states/skirmish_states/board.rs +++ b/src/app/states/skirmish_states/board.rs @@ -21,6 +21,8 @@ pub struct BoardState { focused_cell: FocusedCell, player_base_coords: (usize, usize), enemy_base_coords: (usize, usize), + pub marking_cells: bool, + marked_cells: Vec<(usize, usize)>, } impl BoardState { @@ -70,6 +72,9 @@ impl BoardState { cells.push(rows); } + let marking_cells: bool = false; + let marked_cells: Vec<(usize, usize)> = Vec::new(); + Self { cells_area, cell_width, @@ -85,6 +90,8 @@ impl BoardState { focused_cell, player_base_coords, enemy_base_coords, + marking_cells, + marked_cells, } } @@ -92,11 +99,76 @@ impl BoardState { &mut self.cells[row][col] } + pub fn get_marked_cells(&self) -> Vec<&CellWidget> { + self.marked_cells + .iter() + .map(move |&(row, col)| &self.cells[row][col]) + .collect() + } + + fn get_last_marked_cell(&self) -> Option<(usize, usize)> { + self.marked_cells.last().cloned() + } + + pub fn set_marked_cell(&mut self, row: usize, col: usize, old_row: usize, old_col: usize) { + let last_cell: Option<(usize, usize)> = self.get_last_marked_cell(); + let cell: &mut CellWidget = self.get_mut_cell(row, col); + + if cell.get_marked() { + if last_cell == Some((old_row, old_col)) { + self.get_mut_cell(old_row, old_col).set_marked(false); + self.marked_cells.pop(); + } + } else { + cell.set_marked(true); + self.marked_cells.push((row, col)); + } + } + + pub fn start_marking_cells(&mut self) { + let row: usize = self.focused_cell.get_row(); + let col: usize = self.focused_cell.get_col(); + + let cell: &mut CellWidget = self.get_mut_cell(row, col); + cell.set_marked(true); + + self.marked_cells.push((row, col)); + } + + pub fn clear_marked_cells(&mut self) { + for (row, col) in self.marked_cells.clone() { + self.get_mut_cell(row, col).set_marked(false); + } + + self.marked_cells.clear(); + } + fn max_offset(map_size: usize, size: usize) -> usize { if map_size > size { map_size - size } else { 0 } } - pub fn resize_change(&mut self, area: &Rect) { + pub fn is_focused_cell_visible(&self) -> bool { + let vertical_offset: usize = self.vertical_offset.get_value(); + let horizontal_offset: usize = self.horizontal_offset.get_value(); + + let row: usize = self.focused_cell.get_row(); + let col: usize = self.focused_cell.get_col(); + + if 0usize.saturating_add(vertical_offset) > row + || row >= self.rows.saturating_add(vertical_offset) + { + return false; + } + if 0usize.saturating_add(horizontal_offset) > col + || col >= self.cols.saturating_add(horizontal_offset) + { + return false; + } + + true + } + + pub fn change_resize(&mut self, area: &Rect) { self.cells_area = cells_area_helper(area); self.cols = (self.cells_area.width / self.cell_width as u16) as usize; @@ -111,7 +183,7 @@ impl BoardState { Offset::new(Some(self.vertical_offset.get_value()), Some(v_max_offset)); } - pub fn zoom_change(&mut self, new_zoom_level: ZoomLevel) { + pub fn change_zoom(&mut self, new_zoom_level: ZoomLevel) { self.zoom_level = new_zoom_level; self.cell_width = cell_size_helper(CellSizes::Width, self.zoom_level); @@ -149,26 +221,9 @@ impl BoardState { self.get_mut_cell(old_row, old_col).set_selected(false); self.get_mut_cell(new_row, new_col).set_selected(true); - } - pub fn is_focused_cell_visible(&self) -> bool { - let vertical_offset: usize = self.vertical_offset.get_value(); - let horizontal_offset: usize = self.horizontal_offset.get_value(); - - let row: usize = self.focused_cell.get_row(); - let col: usize = self.focused_cell.get_col(); - - if 0usize.saturating_add(vertical_offset) > row - || row >= self.rows.saturating_add(vertical_offset) - { - return false; + if self.marking_cells { + self.set_marked_cell(new_row, new_col, old_row, old_col); } - if 0usize.saturating_add(horizontal_offset) > col - || col >= self.cols.saturating_add(horizontal_offset) - { - return false; - } - - true } } diff --git a/src/app/views/skirmish.rs b/src/app/views/skirmish.rs index 587144f..5d67553 100644 --- a/src/app/views/skirmish.rs +++ b/src/app/views/skirmish.rs @@ -25,6 +25,8 @@ const ACTIONS: &[Action] = &[ Action::ZoomOut, Action::VolumeUp, Action::VolumeDown, + Action::Space, + Action::Backspace, Action::Mute, Action::Quit, Action::Quit2, @@ -92,19 +94,16 @@ pub fn skirmish_view(app: &App, area: Rect, buf: &mut Buffer) { horizontal: 1, vertical: 1, }); + // .centered( + // Constraint::Length( + // (states.skirmish.board.cell_width * states.skirmish.board.cols) as u16, + // ), + // Constraint::Length( + // (states.skirmish.board.cell_height * states.skirmish.board.rows) as u16, + // ), + // ); - // TODO: add actual (effective) board sizes as Constraints - BoardWidget::new(&states.skirmish.board).render( - cells_area.centered( - Constraint::Length( - (states.skirmish.board.cell_width * states.skirmish.board.cols) as u16, - ), - Constraint::Length( - (states.skirmish.board.cell_height * states.skirmish.board.rows) as u16, - ), - ), - buf, - ); + BoardWidget::new(&states.skirmish.board).render(cells_area, buf); } { diff --git a/src/app/widgets/cell.rs b/src/app/widgets/cell.rs index 9e23ddf..8eb5b02 100644 --- a/src/app/widgets/cell.rs +++ b/src/app/widgets/cell.rs @@ -27,6 +27,7 @@ pub struct CellWidget { selected: bool, zoom_level: ZoomLevel, tag: CellTag, + marked: bool, } impl CellWidget { @@ -43,6 +44,7 @@ impl CellWidget { selected, zoom_level, tag, + marked: false, } } @@ -58,6 +60,14 @@ impl CellWidget { self.tag = tag; } + pub fn get_marked(&self) -> bool { + self.marked + } + + pub fn set_marked(&mut self, marked: bool) { + self.marked = marked + } + fn col_to_letters(&self) -> String { let mut col: usize = self.col + 1; let mut letters: Vec = Vec::new(); @@ -80,6 +90,7 @@ impl CellWidget { fn fg_color(&self) -> Color { match self.tag { + _ if self.marked => Color::LightMagenta, _ if self.selected => Color::LightYellow, CellTag::Base(Players::Player) if !self.selected => Color::LightBlue, CellTag::Base(Players::Enemy) if !self.selected => Color::LightRed,