From 3e3169dd27e160136f960da065bc9718c1acecb1 Mon Sep 17 00:00:00 2001 From: Pierre Hubert Date: Sat, 8 Oct 2022 16:27:06 +0200 Subject: [PATCH] Add new confirm dialog --- rust/cli_player/src/main.rs | 3 +- .../src/ui_screens/confirm_dialog.rs | 112 ++++++++++++++++++ rust/cli_player/src/ui_screens/mod.rs | 1 + 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 rust/cli_player/src/ui_screens/confirm_dialog.rs diff --git a/rust/cli_player/src/main.rs b/rust/cli_player/src/main.rs index 802f0f2..e7bc837 100644 --- a/rust/cli_player/src/main.rs +++ b/rust/cli_player/src/main.rs @@ -22,7 +22,8 @@ async fn run_app(terminal: &mut Terminal) -> Result<(), Box { + title: &'a str, + msg: &'a str, + is_confirm: bool, + can_cancel: bool, +} + +pub fn confirm_dialog( + msg: &str, + terminal: &mut Terminal, +) -> io::Result> { + let mut model = ConfirmDialogScreen { + title: "Confirmation Request", + msg, + is_confirm: true, + can_cancel: false, + }; + + let mut last_tick = Instant::now(); + loop { + terminal.draw(|f| ui(f, &mut model))?; + + let timeout = TICK_RATE + .checked_sub(last_tick.elapsed()) + .unwrap_or_else(|| Duration::from_secs(0)); + + if event::poll(timeout)? { + if let Event::Key(key) = event::read()? { + match key.code { + KeyCode::Esc | KeyCode::Char('q') if model.can_cancel => { + return Ok(ScreenResult::Canceled) + } + + // Toggle selected choice + KeyCode::Left | KeyCode::Right | KeyCode::Tab => { + model.is_confirm = !model.is_confirm + } + + // Submit choice + KeyCode::Enter => { + return Ok(ScreenResult::Ok(model.is_confirm)); + } + _ => {} + } + } + } + if last_tick.elapsed() >= TICK_RATE { + last_tick = Instant::now(); + } + } +} + +fn ui(f: &mut Frame, model: &mut ConfirmDialogScreen) { + // Preprocess message + let lines = textwrap::wrap(model.msg, f.size().width as usize - 20); + let line_max_len = lines.iter().map(|l| l.len()).max().unwrap(); + + let area = centered_rect_size(line_max_len as u16 + 4, 5 + lines.len() as u16, &f.size()); + + let block = Block::default().borders(Borders::ALL).title(model.title); + f.render_widget(block, area); + + // Create two chunks with equal horizontal screen space + let chunks = Layout::default() + .direction(Direction::Vertical) + .constraints( + [ + Constraint::Length(lines.len() as u16), + Constraint::Length(3), + ] + .as_ref(), + ) + .split(area.inner(&Margin { + horizontal: 2, + vertical: 1, + })); + + let text = lines + .iter() + .map(|s| Spans::from(s.as_ref())) + .collect::>(); + let paragraph = Paragraph::new(text); + f.render_widget(paragraph, chunks[0]); + + // Buttons + let buttons_area = Layout::default() + .direction(Direction::Horizontal) + .constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref()) + .split(chunks[1]); + + let cancel_button = ButtonWidget::new("Cancel", true).set_disabled(model.is_confirm); + f.render_widget(cancel_button, buttons_area[0]); + + let ok_button = ButtonWidget::new("Confirm", true).set_disabled(!model.is_confirm); + f.render_widget(ok_button, buttons_area[1]); +} diff --git a/rust/cli_player/src/ui_screens/mod.rs b/rust/cli_player/src/ui_screens/mod.rs index 48d7495..24aa98d 100644 --- a/rust/cli_player/src/ui_screens/mod.rs +++ b/rust/cli_player/src/ui_screens/mod.rs @@ -1,4 +1,5 @@ pub mod configure_game_rules; +pub mod confirm_dialog; pub mod popup_screen; pub mod select_bot_type; pub mod select_play_mode;