generated from GarandPLG/rust-flake-template
Add marking mode; rename resize and zoom methods
Introduce a marking mode that lets users toggle cells with Space and clear them with Backspace. BoardState now stores `marking_cells` and a list of `marked_cells` and provides methods to start, clear, and update marks. CellWidget tracks a `marked` flag and renders marked cells in LightMagenta. Keybindings are updated: Space now reads “Marking cells”, Backspace reads “Cancel marking”, and the original Enter binding is commented out. The former `resize_change` and `zoom_change` functions are renamed to `change_resize` and `change_zoom`; all call sites are updated accordingly.
This commit is contained in:
+1
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+11
-12
@@ -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);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -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<char> = 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,
|
||||
|
||||
Reference in New Issue
Block a user