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);
}
}
_ => (),
}
}
+11 -9
View File
@@ -11,15 +11,17 @@ 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()
.block(
Block::new()
.gray()
.borders(Borders::LEFT | Borders::TOP | Borders::RIGHT),
)
.render(main_area, buf);
{
Paragraph::new("Work in progress")
.alignment(Alignment::Center)
.yellow()
.block(
Block::new()
.gray()
.borders(Borders::LEFT | Borders::TOP | Borders::RIGHT),
)
.render(main_area, buf);
}
{
let actions: Vec<Action> = vec![Action::Quit, Action::Quit2, Action::Esc];
+42 -33
View File
@@ -15,36 +15,42 @@ 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()
.block(
Block::new()
.gray()
.borders(Borders::LEFT | Borders::TOP | Borders::RIGHT)
.padding(Padding::new(1, 1, 1, 1)),
{
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);
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<'_> = Paragraph::new(
app.game_states
.settings_state
.selected_setting_new_value
.clone(),
)
.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);
let popup_area = 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")
.wrap(Wrap { trim: true })
.style(Style::default().yellow())
.block(
@@ -55,19 +61,22 @@ pub fn settings_view(app: &App, area: Rect, buf: &mut Buffer) {
.border_style(Style::default().blue()),
);
if app.game_states.settings_state.show_popup {
popup.render(popup_area, buf);
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);