generated from GarandPLG/rust-flake-template
Refactor view handling and keybinding API
Move the `View` enum to a dedicated module and implement `Widget` for `&App` there. Rename `default_view_keybindings` to `default_keybindings` and adjust its signature. Redesign `KeybindingsWidget` to accept an explicit list of bindings instead of a `View`. Update imports, function signatures, and rendering logic across the codebase to reflect these changes.
This commit is contained in:
+3
-11
@@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
app::{GameStates, handle_keybindings},
|
app::{GameStates, handle_keybindings, view::View},
|
||||||
cli::Cli,
|
cli::Cli,
|
||||||
};
|
};
|
||||||
use clap::ValueEnum;
|
use clap::ValueEnum;
|
||||||
@@ -34,15 +34,6 @@ pub struct App {
|
|||||||
pub skill_points_limit: u16,
|
pub skill_points_limit: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, ValueEnum)]
|
|
||||||
pub enum View {
|
|
||||||
MainMenu,
|
|
||||||
Skirmish,
|
|
||||||
PerkDecks,
|
|
||||||
SkillsConfig,
|
|
||||||
Settings,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, ValueEnum)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, ValueEnum)]
|
||||||
pub enum GameMode {
|
pub enum GameMode {
|
||||||
LastManStanding,
|
LastManStanding,
|
||||||
@@ -100,7 +91,8 @@ impl App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_key_event(&mut self, key_event: KeyEvent) -> Result<()> {
|
fn handle_key_event(&mut self, key_event: KeyEvent) -> Result<()> {
|
||||||
handle_keybindings(self, key_event)
|
handle_keybindings(self, key_event);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-7
@@ -1,16 +1,14 @@
|
|||||||
use crate::app::{
|
use crate::app::{
|
||||||
App, View,
|
App,
|
||||||
keybindings::{default_view_keybindings, main_menu_keybindings, settings_keybindings},
|
keybindings::{default_keybindings, main_menu_keybindings, settings_keybindings},
|
||||||
|
view::View,
|
||||||
};
|
};
|
||||||
use ratatui::crossterm::event::KeyEvent;
|
use ratatui::crossterm::event::KeyEvent;
|
||||||
use std::io::Result;
|
|
||||||
|
|
||||||
pub fn handle_keybindings(app: &mut App, key_event: KeyEvent) -> Result<()> {
|
pub fn handle_keybindings(app: &mut App, key_event: KeyEvent) {
|
||||||
match app.view {
|
match app.view {
|
||||||
View::MainMenu => main_menu_keybindings(app, &key_event),
|
View::MainMenu => main_menu_keybindings(app, &key_event),
|
||||||
View::Settings => settings_keybindings(app, &key_event),
|
View::Settings => settings_keybindings(app, &key_event),
|
||||||
_ => default_view_keybindings(app, &key_event),
|
_ => default_keybindings(app, &key_event),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use crate::app::{
|
|||||||
};
|
};
|
||||||
use ratatui::crossterm::event::KeyEvent;
|
use ratatui::crossterm::event::KeyEvent;
|
||||||
|
|
||||||
pub fn default_view_keybindings(app: &mut App, key_event: &KeyEvent) {
|
pub fn default_keybindings(app: &mut App, key_event: &KeyEvent) {
|
||||||
if let Some(action) = event_to_action(&key_event) {
|
if let Some(action) = event_to_action(&key_event) {
|
||||||
match action {
|
match action {
|
||||||
Action::Quit => app.exit = true,
|
Action::Quit => app.exit = true,
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
use crate::app::View;
|
|
||||||
use ratatui::crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
|
use ratatui::crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
|
||||||
use std::collections::HashSet;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum Action {
|
pub enum Action {
|
||||||
@@ -115,51 +113,3 @@ pub fn event_to_action(event: &KeyEvent) -> Option<Action> {
|
|||||||
.find(|b| b.code == event.code && b.kind == event.kind && b.modifiers == event.modifiers)
|
.find(|b| b.code == event.code && b.kind == event.kind && b.modifiers == event.modifiers)
|
||||||
.map(|b| b.action)
|
.map(|b| b.action)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn used_groups_in_view(keybindings: &Vec<Option<&'static KeyBinding>>) -> HashSet<Group> {
|
|
||||||
keybindings
|
|
||||||
.iter()
|
|
||||||
.filter_map(|b| b.map(|binding| binding.group))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn binding_for_view(view: View) -> (HashSet<Group>, Vec<Option<&'static KeyBinding>>) {
|
|
||||||
let main_menu_keybindings: Vec<Option<&'static KeyBinding>> = vec![
|
|
||||||
binding_for(Action::Up),
|
|
||||||
binding_for(Action::Down),
|
|
||||||
binding_for(Action::Space),
|
|
||||||
binding_for(Action::Quit),
|
|
||||||
binding_for(Action::Quit2),
|
|
||||||
];
|
|
||||||
|
|
||||||
let settings_keybinding: Vec<Option<&'static KeyBinding>> = vec![
|
|
||||||
binding_for(Action::Up),
|
|
||||||
binding_for(Action::Down),
|
|
||||||
binding_for(Action::Space),
|
|
||||||
binding_for(Action::Enter),
|
|
||||||
binding_for(Action::Quit),
|
|
||||||
binding_for(Action::Quit2),
|
|
||||||
binding_for(Action::Esc),
|
|
||||||
];
|
|
||||||
|
|
||||||
let default_keybindings: Vec<Option<&'static KeyBinding>> = vec![
|
|
||||||
binding_for(Action::Quit),
|
|
||||||
binding_for(Action::Quit2),
|
|
||||||
binding_for(Action::Esc),
|
|
||||||
];
|
|
||||||
|
|
||||||
match view {
|
|
||||||
View::MainMenu => (
|
|
||||||
used_groups_in_view(&main_menu_keybindings),
|
|
||||||
main_menu_keybindings,
|
|
||||||
),
|
|
||||||
View::Settings => (
|
|
||||||
used_groups_in_view(&settings_keybinding),
|
|
||||||
settings_keybinding,
|
|
||||||
),
|
|
||||||
_ => (
|
|
||||||
used_groups_in_view(&default_keybindings),
|
|
||||||
default_keybindings,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,9 +3,7 @@ pub mod keybindings;
|
|||||||
pub mod main_menu;
|
pub mod main_menu;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
|
|
||||||
pub use default::default_view_keybindings;
|
pub use default::default_keybindings;
|
||||||
pub use keybindings::{
|
pub use keybindings::{Action, Group, KEYBINDINGS, KeyBinding, binding_for, event_to_action};
|
||||||
Action, Group, KEYBINDINGS, KeyBinding, binding_for, binding_for_view, event_to_action,
|
|
||||||
};
|
|
||||||
pub use main_menu::main_menu_keybindings;
|
pub use main_menu::main_menu_keybindings;
|
||||||
pub use settings::settings_keybindings;
|
pub use settings::settings_keybindings;
|
||||||
|
|||||||
+4
-2
@@ -2,11 +2,13 @@ pub mod app;
|
|||||||
pub mod game_states;
|
pub mod game_states;
|
||||||
pub mod keybind;
|
pub mod keybind;
|
||||||
pub mod keybindings;
|
pub mod keybindings;
|
||||||
pub mod widget;
|
pub mod view;
|
||||||
|
pub mod views;
|
||||||
pub mod widgets;
|
pub mod widgets;
|
||||||
|
|
||||||
pub use app::{App, Event, GameMode, PerkDecks, View, handle_input_events};
|
pub use app::{App, Event, GameMode, PerkDecks, handle_input_events};
|
||||||
pub use game_states::{
|
pub use game_states::{
|
||||||
GameStates, MainMenuState, PerkDecksState, SettingsState, SkillsConfigState, SkirmishState,
|
GameStates, MainMenuState, PerkDecksState, SettingsState, SkillsConfigState, SkirmishState,
|
||||||
};
|
};
|
||||||
pub use keybind::handle_keybindings;
|
pub use keybind::handle_keybindings;
|
||||||
|
pub use view::View;
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
use crate::app::{
|
||||||
|
App,
|
||||||
|
views::{default_view, main_menu_view, settings_view},
|
||||||
|
};
|
||||||
|
use clap::ValueEnum;
|
||||||
|
use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, ValueEnum)]
|
||||||
|
pub enum View {
|
||||||
|
MainMenu,
|
||||||
|
Skirmish,
|
||||||
|
PerkDecks,
|
||||||
|
SkillsConfig,
|
||||||
|
Settings,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for &App {
|
||||||
|
fn render(self, area: Rect, buf: &mut Buffer)
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
match self.view {
|
||||||
|
View::MainMenu => main_menu_view(self, area, buf),
|
||||||
|
View::Settings => settings_view(self, area, buf),
|
||||||
|
_ => default_view(area, buf),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
use crate::app::{App, widgets::KeybindingsWidget};
|
use crate::app::{
|
||||||
|
keybindings::{Action, KeyBinding, binding_for},
|
||||||
|
widgets::KeybindingsWidget,
|
||||||
|
};
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
buffer::Buffer,
|
buffer::Buffer,
|
||||||
layout::{Alignment, Constraint, Layout, Rect},
|
layout::{Alignment, Constraint, Layout, Rect},
|
||||||
@@ -6,7 +9,7 @@ use ratatui::{
|
|||||||
widgets::{Block, Borders, Paragraph, Widget},
|
widgets::{Block, Borders, Paragraph, Widget},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn default_view_widget(app: &App, area: Rect, buf: &mut Buffer) {
|
pub fn default_view(area: Rect, buf: &mut Buffer) {
|
||||||
let vertical_layout: Layout = Layout::vertical([Constraint::Fill(1), Constraint::Length(4)]);
|
let vertical_layout: Layout = Layout::vertical([Constraint::Fill(1), Constraint::Length(4)]);
|
||||||
|
|
||||||
let [main_area, keybindings_area] = vertical_layout.areas(area);
|
let [main_area, keybindings_area] = vertical_layout.areas(area);
|
||||||
@@ -21,5 +24,13 @@ pub fn default_view_widget(app: &App, area: Rect, buf: &mut Buffer) {
|
|||||||
)
|
)
|
||||||
.render(main_area, buf);
|
.render(main_area, buf);
|
||||||
|
|
||||||
KeybindingsWidget::new(app.view).render(keybindings_area, buf);
|
{
|
||||||
|
let keybindings: Vec<Option<&'static KeyBinding>> = vec![
|
||||||
|
binding_for(Action::Quit),
|
||||||
|
binding_for(Action::Quit2),
|
||||||
|
binding_for(Action::Esc),
|
||||||
|
];
|
||||||
|
|
||||||
|
KeybindingsWidget::new(keybindings).render(keybindings_area, buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
use crate::app::{App, View, widgets::KeybindingsWidget};
|
use crate::app::{
|
||||||
|
App, View,
|
||||||
|
keybindings::{Action, KeyBinding, binding_for},
|
||||||
|
widgets::KeybindingsWidget,
|
||||||
|
};
|
||||||
use clap::ValueEnum;
|
use clap::ValueEnum;
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
buffer::Buffer,
|
buffer::Buffer,
|
||||||
@@ -26,7 +30,7 @@ fn view_options() -> Vec<(usize, String)> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main_menu_widget(app: &App, area: Rect, buf: &mut Buffer) {
|
pub fn main_menu_view(app: &App, area: Rect, buf: &mut Buffer) {
|
||||||
let vertical_layout: Layout = Layout::vertical([Constraint::Fill(1), Constraint::Length(4)]);
|
let vertical_layout: Layout = Layout::vertical([Constraint::Fill(1), Constraint::Length(4)]);
|
||||||
|
|
||||||
let [main_menu_area, keybindings_area] = vertical_layout.areas(area);
|
let [main_menu_area, keybindings_area] = vertical_layout.areas(area);
|
||||||
@@ -81,5 +85,15 @@ pub fn main_menu_widget(app: &App, area: Rect, buf: &mut Buffer) {
|
|||||||
.render(options_area, buf);
|
.render(options_area, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
KeybindingsWidget::new(View::MainMenu).render(keybindings_area, buf);
|
{
|
||||||
|
let keybindings: Vec<Option<&'static KeyBinding>> = vec![
|
||||||
|
binding_for(Action::Up),
|
||||||
|
binding_for(Action::Down),
|
||||||
|
binding_for(Action::Space),
|
||||||
|
binding_for(Action::Quit),
|
||||||
|
binding_for(Action::Quit2),
|
||||||
|
];
|
||||||
|
|
||||||
|
KeybindingsWidget::new(keybindings).render(keybindings_area, buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
pub mod default;
|
||||||
|
pub mod main_menu;
|
||||||
|
pub mod settings;
|
||||||
|
|
||||||
|
pub use default::default_view;
|
||||||
|
pub use main_menu::main_menu_view;
|
||||||
|
pub use settings::settings_view;
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
use crate::app::{App, widgets::KeybindingsWidget};
|
use crate::app::{
|
||||||
|
App,
|
||||||
|
keybindings::{Action, KeyBinding, binding_for},
|
||||||
|
widgets::KeybindingsWidget,
|
||||||
|
};
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
buffer::Buffer,
|
buffer::Buffer,
|
||||||
layout::{Alignment, Constraint, Layout, Rect},
|
layout::{Alignment, Constraint, Layout, Rect},
|
||||||
@@ -6,7 +10,7 @@ use ratatui::{
|
|||||||
widgets::{Block, Borders, Padding, Paragraph, Widget},
|
widgets::{Block, Borders, Padding, Paragraph, Widget},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn settings_widget(app: &App, area: Rect, buf: &mut Buffer) {
|
pub fn settings_view(app: &App, area: Rect, buf: &mut Buffer) {
|
||||||
let vertical_layout: Layout = Layout::vertical([
|
let vertical_layout: Layout = Layout::vertical([
|
||||||
Constraint::Length(10),
|
Constraint::Length(10),
|
||||||
Constraint::Fill(1),
|
Constraint::Fill(1),
|
||||||
@@ -37,5 +41,17 @@ pub fn settings_widget(app: &App, area: Rect, buf: &mut Buffer) {
|
|||||||
)
|
)
|
||||||
.render(main_area, buf);
|
.render(main_area, buf);
|
||||||
|
|
||||||
KeybindingsWidget::new(app.view).render(keybindings_area, buf);
|
{
|
||||||
|
let keybindings: Vec<Option<&'static KeyBinding>> = vec![
|
||||||
|
binding_for(Action::Up),
|
||||||
|
binding_for(Action::Down),
|
||||||
|
binding_for(Action::Space),
|
||||||
|
binding_for(Action::Enter),
|
||||||
|
binding_for(Action::Quit),
|
||||||
|
binding_for(Action::Quit2),
|
||||||
|
binding_for(Action::Esc),
|
||||||
|
];
|
||||||
|
|
||||||
|
KeybindingsWidget::new(keybindings).render(keybindings_area, buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
use crate::app::{
|
|
||||||
App, View,
|
|
||||||
widgets::{default_view_widget, main_menu_widget, settings_widget},
|
|
||||||
};
|
|
||||||
use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
|
|
||||||
|
|
||||||
impl Widget for &App {
|
|
||||||
fn render(self, area: Rect, buf: &mut Buffer)
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
match self.view {
|
|
||||||
View::MainMenu => main_menu_widget(self, area, buf),
|
|
||||||
View::Settings => settings_widget(self, area, buf),
|
|
||||||
_ => default_view_widget(self, area, buf),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
use crate::app::{
|
use std::collections::HashSet;
|
||||||
View,
|
|
||||||
keybindings::{Group, binding_for_view},
|
use crate::app::keybindings::{Group, KeyBinding};
|
||||||
};
|
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
buffer::Buffer,
|
buffer::Buffer,
|
||||||
layout::{Alignment, Constraint, Layout, Rect},
|
layout::{Alignment, Constraint, Layout, Rect},
|
||||||
@@ -15,8 +14,11 @@ pub struct KeybindingsWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl KeybindingsWidget {
|
impl KeybindingsWidget {
|
||||||
pub fn new(view: View) -> Self {
|
pub fn new(keybindings: Vec<Option<&'static KeyBinding>>) -> Self {
|
||||||
let (used_groups, keybindings) = binding_for_view(view);
|
let used_groups: HashSet<Group> = keybindings
|
||||||
|
.iter()
|
||||||
|
.filter_map(|b| b.map(|binding| binding.group))
|
||||||
|
.collect();
|
||||||
|
|
||||||
let mut grouped_keybindings: Vec<Paragraph<'static>> = Vec::new();
|
let mut grouped_keybindings: Vec<Paragraph<'static>> = Vec::new();
|
||||||
for (i, group) in Group::iter().enumerate() {
|
for (i, group) in Group::iter().enumerate() {
|
||||||
|
|||||||
@@ -1,9 +1,3 @@
|
|||||||
pub mod default;
|
|
||||||
pub mod keybindings;
|
pub mod keybindings;
|
||||||
pub mod main_menu;
|
|
||||||
pub mod settings;
|
|
||||||
|
|
||||||
pub use default::default_view_widget;
|
|
||||||
pub use keybindings::KeybindingsWidget;
|
pub use keybindings::KeybindingsWidget;
|
||||||
pub use main_menu::main_menu_widget;
|
|
||||||
pub use settings::settings_widget;
|
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
use crate::app::{GameMode, PerkDecks, View};
|
use crate::app::{GameMode, PerkDecks, view::View};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
|
|||||||
Reference in New Issue
Block a user