Add text input handling to settings popup

Introduce a `selected_setting_new_value` field in `SettingsState` and
initialize it.
Add `Backspace` and `WildCard(char)` actions with an `Input` group, and
corresponding keybindings.
Update `event_to_action` to map wildcard characters to
`Action::WildCard`.
Handle backspace and character input in `settings_keybindings` to edit
the new field.
Display the edited value in the settings popup and include the new
actions in the UI.
This commit is contained in:
2026-03-15 22:37:11 +01:00
parent 9d4ff19b6e
commit 2dbe378470
5 changed files with 112 additions and 46 deletions
+4 -2
View File
@@ -1,4 +1,4 @@
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct GameStates {
pub main_menu_state: MainMenuState,
pub skirmish_state: SkirmishState,
@@ -34,12 +34,13 @@ pub struct SkillsConfigState {
pub selected_skill: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SettingsState {
pub id: usize,
pub name: &'static str,
pub selected_setting: usize,
pub show_popup: bool,
pub selected_setting_new_value: String,
}
impl GameStates {
@@ -69,6 +70,7 @@ impl GameStates {
name: "Settings",
selected_setting: 0,
show_popup: false,
selected_setting_new_value: String::new(),
},
}
}
+37 -2
View File
@@ -10,12 +10,15 @@ pub enum Action {
Space,
Enter,
Esc,
Backspace,
WildCard(char),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, ValueEnum)]
pub enum Group {
Movement,
Select,
Input,
Quit,
}
@@ -94,6 +97,24 @@ pub static KEYBINDINGS: &[KeyBinding] = &[
symbol: "Esc",
description: "Go back",
},
KeyBinding {
action: Action::Backspace,
code: KeyCode::Backspace,
kind: KeyEventKind::Press,
modifiers: KeyModifiers::NONE,
group: Group::Input,
symbol: "Backspace",
description: "Delete character",
},
KeyBinding {
action: Action::WildCard('_'),
code: KeyCode::Char('_'),
kind: KeyEventKind::Press,
modifiers: KeyModifiers::NONE,
group: Group::Input,
symbol: "*",
description: "All keyboard characters",
},
];
pub fn binding_for(action: Action) -> Option<&'static KeyBinding> {
@@ -101,8 +122,22 @@ pub fn binding_for(action: Action) -> Option<&'static KeyBinding> {
}
pub fn event_to_action(event: &KeyEvent) -> Option<Action> {
KEYBINDINGS
if let Some(b) = KEYBINDINGS
.iter()
.find(|b| b.code == event.code && b.kind == event.kind && b.modifiers == event.modifiers)
.map(|b| b.action)
{
return Some(b.action);
}
if KEYBINDINGS.iter().any(|b| {
matches!(b.action, Action::WildCard(_))
&& b.kind == event.kind
&& b.modifiers == event.modifiers
}) {
if let KeyCode::Char(c) = event.code {
return Some(Action::WildCard(c));
}
}
None
}
+18
View File
@@ -7,6 +7,8 @@ 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::Up,
// Action::Down,
Action::Quit => app.exit = true,
Action::Quit2 => app.exit = true,
Action::Esc => app.view = View::MainMenu,
@@ -14,6 +16,22 @@ pub fn settings_keybindings(app: &mut App, key_event: &KeyEvent) {
app.game_states.settings_state.show_popup =
!app.game_states.settings_state.show_popup
}
Action::Backspace => {
if app.game_states.settings_state.show_popup {
app.game_states
.settings_state
.selected_setting_new_value
.pop();
}
}
Action::WildCard(c) => {
if app.game_states.settings_state.show_popup {
app.game_states
.settings_state
.selected_setting_new_value
.push(c);
}
}
_ => (),
}
}
+2
View File
@@ -11,6 +11,7 @@ pub fn default_view(area: Rect, buf: &mut Buffer) {
let [main_area, keybindings_area] = vertical_layout.areas(area);
{
Paragraph::new("Work in progress")
.alignment(Alignment::Center)
.yellow()
@@ -20,6 +21,7 @@ pub fn default_view(area: Rect, buf: &mut Buffer) {
.borders(Borders::LEFT | Borders::TOP | Borders::RIGHT),
)
.render(main_area, buf);
}
{
let actions: Vec<Action> = vec![Action::Quit, Action::Quit2, Action::Esc];
+13 -4
View File
@@ -15,6 +15,7 @@ pub fn settings_view(app: &App, area: Rect, buf: &mut Buffer) {
let [title_area, main_area, keybindings_area] = vertical_layout.areas(area);
{
Paragraph::new("War in tunnels")
.alignment(Alignment::Left)
.yellow()
@@ -37,14 +38,19 @@ pub fn settings_view(app: &App, area: Rect, buf: &mut Buffer) {
)
.render(main_area, buf);
let popup_area = Rect {
let popup_area: Rect = Rect {
x: main_area.width / 4,
y: main_area.height / 3,
width: main_area.width / 2,
height: main_area.height / 3,
};
let popup = Paragraph::new("Test popup")
let popup: Paragraph<'_> = Paragraph::new(
app.game_states
.settings_state
.selected_setting_new_value
.clone(),
)
.wrap(Wrap { trim: true })
.style(Style::default().yellow())
.block(
@@ -58,16 +64,19 @@ pub fn settings_view(app: &App, area: Rect, buf: &mut Buffer) {
if app.game_states.settings_state.show_popup {
popup.render(popup_area, buf);
}
}
{
let actions: Vec<Action> = vec![
Action::Up,
Action::Down,
Action::Space,
Action::Enter,
Action::Quit,
Action::Quit2,
Action::Esc,
Action::Space,
Action::Enter,
Action::Backspace,
Action::WildCard('_'),
];
KeybindingsWidget::new(actions).render(keybindings_area, buf);