generated from GarandPLG/rust-flake-template
Refactor keybinding handling and update widgets
- Remove the old `keybindings.rs` and stop re‑exporting its symbols. - Add view‑specific handling: `App::handle_key_event` now delegates to `main_menu_keybindings` when the view is `MainMenu`. - Update imports in `app.rs`, `widget.rs`, and widget modules to use the new `app::keybindings` path. - Enhance `keybindings_widget` to display ↑, ↓ and “Space” for special keys. - Change main menu layout percentages from 90/10 to 87/13. - Reorder the `clap` import in `cli.rs` for consistency.
This commit is contained in:
+10
-8
@@ -1,4 +1,4 @@
|
||||
use crate::app::{Action, event_to_action};
|
||||
use crate::app::keybindings::{Action, event_to_action, main_menu_keybindings};
|
||||
use clap::ValueEnum;
|
||||
use ratatui::{
|
||||
DefaultTerminal, Frame,
|
||||
@@ -59,13 +59,15 @@ impl App {
|
||||
}
|
||||
|
||||
fn handle_key_event(&mut self, key_event: KeyEvent) -> Result<()> {
|
||||
// if key_event.kind == KeyEventKind::Press && key_event.code == KeyCode::Char('q') {
|
||||
// self.exit = true;
|
||||
// }
|
||||
|
||||
if let Some(action) = event_to_action(&key_event) {
|
||||
match action {
|
||||
Action::Quit => self.exit = true,
|
||||
match self.window {
|
||||
View::MainMenu => main_menu_keybindings(self, &key_event),
|
||||
_ => {
|
||||
if let Some(action) = event_to_action(&key_event) {
|
||||
match action {
|
||||
Action::Quit => self.exit = true,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
use ratatui::crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
|
||||
|
||||
use crate::app::View;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum Action {
|
||||
Quit,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct KeyBinding {
|
||||
pub action: Action,
|
||||
pub code: KeyCode,
|
||||
pub kind: KeyEventKind,
|
||||
pub modifiers: KeyModifiers,
|
||||
pub description: &'static str,
|
||||
}
|
||||
|
||||
pub static KEYBINDINGS: &[KeyBinding] = &[KeyBinding {
|
||||
action: Action::Quit,
|
||||
code: KeyCode::Char('q'),
|
||||
kind: KeyEventKind::Press,
|
||||
modifiers: KeyModifiers::NONE,
|
||||
description: "Quit",
|
||||
}];
|
||||
|
||||
pub fn binding_for(action: Action) -> Option<&'static KeyBinding> {
|
||||
KEYBINDINGS.iter().find(|b| b.action == action)
|
||||
}
|
||||
|
||||
pub fn event_to_action(event: &KeyEvent) -> Option<Action> {
|
||||
KEYBINDINGS
|
||||
.iter()
|
||||
.find(|b| b.code == event.code && b.kind == event.kind && b.modifiers == event.modifiers)
|
||||
.map(|b| b.action)
|
||||
}
|
||||
|
||||
pub fn binding_for_view(view: View) -> Vec<&'static KeyBinding> {
|
||||
match view {
|
||||
View::MainMenu => binding_for(Action::Quit)
|
||||
.map(|b| vec![b])
|
||||
.unwrap_or_else(|| vec![]),
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
use crate::app::View;
|
||||
use ratatui::crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum Action {
|
||||
Quit,
|
||||
ScrollUp,
|
||||
ScrollDown,
|
||||
Select,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct KeyBinding {
|
||||
pub action: Action,
|
||||
pub code: KeyCode,
|
||||
pub kind: KeyEventKind,
|
||||
pub modifiers: KeyModifiers,
|
||||
pub description: &'static str,
|
||||
}
|
||||
|
||||
pub static KEYBINDINGS: &[KeyBinding] = &[
|
||||
KeyBinding {
|
||||
action: Action::Quit,
|
||||
code: KeyCode::Char('q'),
|
||||
kind: KeyEventKind::Press,
|
||||
modifiers: KeyModifiers::NONE,
|
||||
description: "Quit",
|
||||
},
|
||||
KeyBinding {
|
||||
action: Action::ScrollUp,
|
||||
code: KeyCode::Up,
|
||||
kind: KeyEventKind::Press,
|
||||
modifiers: KeyModifiers::NONE,
|
||||
description: "Up",
|
||||
},
|
||||
KeyBinding {
|
||||
action: Action::ScrollDown,
|
||||
code: KeyCode::Down,
|
||||
kind: KeyEventKind::Press,
|
||||
modifiers: KeyModifiers::NONE,
|
||||
description: "Down",
|
||||
},
|
||||
KeyBinding {
|
||||
action: Action::Select,
|
||||
code: KeyCode::Char(' '),
|
||||
kind: KeyEventKind::Press,
|
||||
modifiers: KeyModifiers::NONE,
|
||||
description: "Select",
|
||||
},
|
||||
];
|
||||
|
||||
pub fn binding_for(action: Action) -> Option<&'static KeyBinding> {
|
||||
KEYBINDINGS.iter().find(|b| b.action == action)
|
||||
}
|
||||
|
||||
pub fn event_to_action(event: &KeyEvent) -> Option<Action> {
|
||||
KEYBINDINGS
|
||||
.iter()
|
||||
.find(|b| b.code == event.code && b.kind == event.kind && b.modifiers == event.modifiers)
|
||||
.map(|b| b.action)
|
||||
}
|
||||
|
||||
pub fn binding_for_view(view: View) -> Vec<&'static KeyBinding> {
|
||||
match view {
|
||||
View::MainMenu => vec![
|
||||
binding_for(Action::ScrollUp).unwrap(),
|
||||
binding_for(Action::ScrollDown).unwrap(),
|
||||
binding_for(Action::Select).unwrap(),
|
||||
binding_for(Action::Quit).unwrap(),
|
||||
],
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
use crate::app::{
|
||||
App,
|
||||
keybindings::{Action, event_to_action},
|
||||
};
|
||||
use ratatui::crossterm::event::KeyEvent;
|
||||
|
||||
pub fn main_menu_keybindings(app: &mut App, event: &KeyEvent) {
|
||||
if let Some(action) = event_to_action(&event) {
|
||||
match action {
|
||||
Action::Quit => app.exit = true,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
pub mod keybindings;
|
||||
pub mod main_menu;
|
||||
|
||||
pub use keybindings::{
|
||||
Action, KEYBINDINGS, KeyBinding, binding_for, binding_for_view, event_to_action,
|
||||
};
|
||||
pub use main_menu::main_menu_keybindings;
|
||||
@@ -4,6 +4,3 @@ pub mod widget;
|
||||
pub mod widgets;
|
||||
|
||||
pub use app::{App, Event, View, handle_input_events};
|
||||
pub use keybindings::{
|
||||
Action, KEYBINDINGS, KeyBinding, binding_for, binding_for_view, event_to_action,
|
||||
};
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
|
||||
|
||||
use crate::app::{App, View, widgets::main_menu_widget};
|
||||
use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
|
||||
|
||||
impl Widget for &App {
|
||||
fn render(self, area: Rect, buf: &mut Buffer)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::app::{View, keybindings::binding_for_view};
|
||||
use ratatui::{
|
||||
crossterm::event::KeyCode,
|
||||
layout::Alignment,
|
||||
@@ -6,13 +7,14 @@ use ratatui::{
|
||||
widgets::{Block, Borders, Paragraph},
|
||||
};
|
||||
|
||||
use crate::app::{View, binding_for_view};
|
||||
|
||||
pub fn keybindings_widget(view: View) -> Paragraph<'static> {
|
||||
let lines: Vec<Line> = binding_for_view(view)
|
||||
.iter()
|
||||
.map(|b| {
|
||||
let key_span = match b.code {
|
||||
KeyCode::Up => Span::raw("↑".to_string()),
|
||||
KeyCode::Down => Span::raw("↓".to_string()),
|
||||
KeyCode::Char(' ') => Span::raw("Space".to_string()),
|
||||
KeyCode::Char(c) => Span::raw(c.to_string()),
|
||||
other => Span::raw(format!("{:?}", other)),
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::app::{View, widgets::keybindings_widget};
|
||||
use ratatui::{
|
||||
buffer::Buffer,
|
||||
layout::{Alignment, Constraint, Layout, Rect},
|
||||
@@ -5,11 +6,9 @@ use ratatui::{
|
||||
widgets::{Block, Borders, Paragraph, Widget},
|
||||
};
|
||||
|
||||
use crate::app::{View, widgets::keybindings_widget};
|
||||
|
||||
pub fn main_menu_widget(area: Rect, buf: &mut Buffer) {
|
||||
let vertical_layout: Layout =
|
||||
Layout::vertical([Constraint::Percentage(90), Constraint::Percentage(10)]);
|
||||
Layout::vertical([Constraint::Percentage(87), Constraint::Percentage(13)]);
|
||||
|
||||
let [main_menu_area, keybindings_area] = vertical_layout.areas(area);
|
||||
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
use clap::Parser;
|
||||
|
||||
use crate::app::View;
|
||||
use clap::Parser;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about = "War in Tunnels", long_about = "War in Tunnels")]
|
||||
|
||||
Reference in New Issue
Block a user