generated from GarandPLG/rust-flake-template
Add Settings view, widget, and keybindings
Introduce Settings view handling in key events and widgets. Add `Enter` action with its keybinding. Refactor keybinding lookup to use `Option<&KeyBinding>` for missing entries. Update view option generation to safely filter possible values. Export `settings_keybindings` and `settings_widget` from their modules.
This commit is contained in:
+2
-1
@@ -1,6 +1,6 @@
|
|||||||
use crate::app::{
|
use crate::app::{
|
||||||
App, View,
|
App, View,
|
||||||
keybindings::{default_view_keybindings, main_menu_keybindings},
|
keybindings::{default_view_keybindings, main_menu_keybindings, settings_keybindings},
|
||||||
};
|
};
|
||||||
use ratatui::crossterm::event::KeyEvent;
|
use ratatui::crossterm::event::KeyEvent;
|
||||||
use std::io::Result;
|
use std::io::Result;
|
||||||
@@ -8,6 +8,7 @@ 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) -> Result<()> {
|
||||||
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),
|
||||||
_ => default_view_keybindings(app, &key_event),
|
_ => default_view_keybindings(app, &key_event),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ pub enum Action {
|
|||||||
Up,
|
Up,
|
||||||
Down,
|
Down,
|
||||||
Space,
|
Space,
|
||||||
|
Enter,
|
||||||
Esc,
|
Esc,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,6 +85,15 @@ pub static KEYBINDINGS: &[KeyBinding] = &[
|
|||||||
symbol: "Space",
|
symbol: "Space",
|
||||||
description: "Select",
|
description: "Select",
|
||||||
},
|
},
|
||||||
|
KeyBinding {
|
||||||
|
action: Action::Enter,
|
||||||
|
code: KeyCode::Enter,
|
||||||
|
kind: KeyEventKind::Press,
|
||||||
|
modifiers: KeyModifiers::NONE,
|
||||||
|
group: Group::Select,
|
||||||
|
symbol: "Enter",
|
||||||
|
description: "Submit",
|
||||||
|
},
|
||||||
KeyBinding {
|
KeyBinding {
|
||||||
action: Action::Esc,
|
action: Action::Esc,
|
||||||
code: KeyCode::Esc,
|
code: KeyCode::Esc,
|
||||||
@@ -106,23 +116,36 @@ pub fn event_to_action(event: &KeyEvent) -> Option<Action> {
|
|||||||
.map(|b| b.action)
|
.map(|b| b.action)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn used_groups_in_view(keybindings: &Vec<&'static KeyBinding>) -> HashSet<Group> {
|
fn used_groups_in_view(keybindings: &Vec<Option<&'static KeyBinding>>) -> HashSet<Group> {
|
||||||
keybindings.iter().map(|b| b.group).collect()
|
keybindings
|
||||||
|
.iter()
|
||||||
|
.filter_map(|b| b.map(|binding| binding.group))
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn binding_for_view(view: View) -> (HashSet<Group>, Vec<&'static KeyBinding>) {
|
pub fn binding_for_view(view: View) -> (HashSet<Group>, Vec<Option<&'static KeyBinding>>) {
|
||||||
let main_menu_keybindings: Vec<&'static KeyBinding> = vec![
|
let main_menu_keybindings: Vec<Option<&'static KeyBinding>> = vec![
|
||||||
binding_for(Action::Up).unwrap(),
|
binding_for(Action::Up),
|
||||||
binding_for(Action::Down).unwrap(),
|
binding_for(Action::Down),
|
||||||
binding_for(Action::Space).unwrap(),
|
binding_for(Action::Space),
|
||||||
binding_for(Action::Quit).unwrap(),
|
binding_for(Action::Quit),
|
||||||
binding_for(Action::Quit2).unwrap(),
|
binding_for(Action::Quit2),
|
||||||
];
|
];
|
||||||
|
|
||||||
let default_keybindings: Vec<&'static KeyBinding> = vec![
|
let settings_keybinding: Vec<Option<&'static KeyBinding>> = vec![
|
||||||
binding_for(Action::Quit).unwrap(),
|
binding_for(Action::Up),
|
||||||
binding_for(Action::Quit2).unwrap(),
|
binding_for(Action::Down),
|
||||||
binding_for(Action::Esc).unwrap(),
|
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 {
|
match view {
|
||||||
@@ -130,6 +153,10 @@ pub fn binding_for_view(view: View) -> (HashSet<Group>, Vec<&'static KeyBinding>
|
|||||||
used_groups_in_view(&main_menu_keybindings),
|
used_groups_in_view(&main_menu_keybindings),
|
||||||
main_menu_keybindings,
|
main_menu_keybindings,
|
||||||
),
|
),
|
||||||
|
View::Settings => (
|
||||||
|
used_groups_in_view(&settings_keybinding),
|
||||||
|
settings_keybinding,
|
||||||
|
),
|
||||||
_ => (
|
_ => (
|
||||||
used_groups_in_view(&default_keybindings),
|
used_groups_in_view(&default_keybindings),
|
||||||
default_keybindings,
|
default_keybindings,
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
pub mod default;
|
pub mod default;
|
||||||
pub mod keybindings;
|
pub mod keybindings;
|
||||||
pub mod main_menu;
|
pub mod main_menu;
|
||||||
|
pub mod settings;
|
||||||
|
|
||||||
pub use default::default_view_keybindings;
|
pub use default::default_view_keybindings;
|
||||||
pub use keybindings::{
|
pub use keybindings::{
|
||||||
Action, Group, KEYBINDINGS, KeyBinding, binding_for, binding_for_view, 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;
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
use crate::app::{
|
||||||
|
App, View,
|
||||||
|
keybindings::{Action, event_to_action},
|
||||||
|
};
|
||||||
|
use ratatui::crossterm::event::KeyEvent;
|
||||||
|
|
||||||
|
pub fn settings_keybindings(app: &mut App, key_event: &KeyEvent) {
|
||||||
|
if let Some(action) = event_to_action(&key_event) {
|
||||||
|
match action {
|
||||||
|
Action::Quit => app.exit = true,
|
||||||
|
Action::Quit2 => app.exit = true,
|
||||||
|
Action::Esc => app.view = View::MainMenu,
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-1
@@ -1,6 +1,6 @@
|
|||||||
use crate::app::{
|
use crate::app::{
|
||||||
App, View,
|
App, View,
|
||||||
widgets::{default_view_widget, main_menu_widget},
|
widgets::{default_view_widget, main_menu_widget, settings_widget},
|
||||||
};
|
};
|
||||||
use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
|
use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
|
||||||
|
|
||||||
@@ -11,6 +11,7 @@ impl Widget for &App {
|
|||||||
{
|
{
|
||||||
match self.view {
|
match self.view {
|
||||||
View::MainMenu => main_menu_widget(self, area, buf),
|
View::MainMenu => main_menu_widget(self, area, buf),
|
||||||
|
View::Settings => settings_widget(self, area, buf),
|
||||||
_ => default_view_widget(self, area, buf),
|
_ => default_view_widget(self, area, buf),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,9 +26,15 @@ impl KeybindingsWidget {
|
|||||||
|
|
||||||
let grouped_lines: Vec<Line<'_>> = keybindings
|
let grouped_lines: Vec<Line<'_>> = keybindings
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|b| b.group == group)
|
.filter(|b| b.as_ref().map_or(false, |kb| kb.group == group))
|
||||||
.map(|b| {
|
.filter_map(|b| {
|
||||||
Line::from_iter([b.symbol.red().bold(), " - ".into(), b.description.into()])
|
b.as_ref().map(|kb| {
|
||||||
|
Line::from_iter([
|
||||||
|
kb.symbol.red().bold(),
|
||||||
|
" - ".into(),
|
||||||
|
kb.description.into(),
|
||||||
|
])
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|||||||
@@ -12,16 +12,16 @@ fn view_options() -> Vec<(usize, String)> {
|
|||||||
View::value_variants()
|
View::value_variants()
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, v)| {
|
.filter_map(|(i, v)| {
|
||||||
let name = v
|
v.to_possible_value().map(|possible_value| {
|
||||||
.to_possible_value()
|
let name = possible_value
|
||||||
.unwrap()
|
|
||||||
.get_name()
|
.get_name()
|
||||||
.replace('-', " ")
|
.replace('-', " ")
|
||||||
.to_uppercase()
|
.to_uppercase()
|
||||||
.to_string();
|
.to_string();
|
||||||
(i, name)
|
(i, name)
|
||||||
})
|
})
|
||||||
|
})
|
||||||
.filter(|(_, v)| v != "MAIN MENU")
|
.filter(|(_, v)| v != "MAIN MENU")
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
pub mod default;
|
pub mod default;
|
||||||
pub mod keybindings;
|
pub mod keybindings;
|
||||||
pub mod main_menu;
|
pub mod main_menu;
|
||||||
|
pub mod settings;
|
||||||
|
|
||||||
pub use default::default_view_widget;
|
pub use default::default_view_widget;
|
||||||
pub use keybindings::KeybindingsWidget;
|
pub use keybindings::KeybindingsWidget;
|
||||||
pub use main_menu::main_menu_widget;
|
pub use main_menu::main_menu_widget;
|
||||||
|
pub use settings::settings_widget;
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
use crate::app::{App, widgets::KeybindingsWidget};
|
||||||
|
use ratatui::{
|
||||||
|
buffer::Buffer,
|
||||||
|
layout::{Alignment, Constraint, Layout, Rect},
|
||||||
|
style::Stylize,
|
||||||
|
widgets::{Block, Borders, Padding, Paragraph, Widget},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn settings_widget(app: &App, area: Rect, buf: &mut Buffer) {
|
||||||
|
let vertical_layout: Layout = Layout::vertical([
|
||||||
|
Constraint::Length(10),
|
||||||
|
Constraint::Fill(1),
|
||||||
|
Constraint::Length(4),
|
||||||
|
]);
|
||||||
|
|
||||||
|
let [title_area, main_area, keybindings_area] = vertical_layout.areas(area);
|
||||||
|
|
||||||
|
Paragraph::new("War in tunnels")
|
||||||
|
.alignment(Alignment::Left)
|
||||||
|
.yellow()
|
||||||
|
.block(
|
||||||
|
Block::new()
|
||||||
|
.gray()
|
||||||
|
.borders(Borders::LEFT | Borders::TOP | Borders::RIGHT)
|
||||||
|
.padding(Padding::new(1, 1, 1, 1)),
|
||||||
|
)
|
||||||
|
.render(title_area, buf);
|
||||||
|
|
||||||
|
Paragraph::new("Settings")
|
||||||
|
.alignment(Alignment::Center)
|
||||||
|
.yellow()
|
||||||
|
.block(
|
||||||
|
Block::new()
|
||||||
|
.gray()
|
||||||
|
.borders(Borders::LEFT | Borders::RIGHT)
|
||||||
|
.padding(Padding::new(1, 1, 1, 1)),
|
||||||
|
)
|
||||||
|
.render(main_area, buf);
|
||||||
|
|
||||||
|
KeybindingsWidget::new(app.view).render(keybindings_area, buf);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user