generated from GarandPLG/rust-flake-template
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:
@@ -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(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user