Add new confirm dialog
This commit is contained in:
		@@ -22,7 +22,8 @@ async fn run_app<B: Backend>(terminal: &mut Terminal<B>) -> Result<(), Box<dyn E
 | 
			
		||||
    /*let mut rules = GameRules::default();
 | 
			
		||||
    rules.boats_can_touch = true;
 | 
			
		||||
    let res = set_boats_layout::set_boat_layout(&rules, terminal)?; // select_bot_type::select_bot_type(terminal)?;*/
 | 
			
		||||
    let res = popup_screen::popup_screen("Hi\nWelcome there", terminal);
 | 
			
		||||
    /*let res = popup_screen::popup_screen("Hi\nWelcome there", terminal);*/
 | 
			
		||||
    let res = confirm_dialog::confirm_dialog("Do you really want to interrupt game ?", terminal)?; // select_bot_type::select_bot_type(terminal)?;
 | 
			
		||||
    Err(io::Error::new(
 | 
			
		||||
        ErrorKind::Other,
 | 
			
		||||
        format!("result: {:?}", res),
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										112
									
								
								rust/cli_player/src/ui_screens/confirm_dialog.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								rust/cli_player/src/ui_screens/confirm_dialog.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,112 @@
 | 
			
		||||
use std::io;
 | 
			
		||||
use std::time::{Duration, Instant};
 | 
			
		||||
 | 
			
		||||
use crossterm::event;
 | 
			
		||||
use crossterm::event::{Event, KeyCode};
 | 
			
		||||
use tui::backend::Backend;
 | 
			
		||||
use tui::layout::*;
 | 
			
		||||
use tui::text::*;
 | 
			
		||||
use tui::widgets::*;
 | 
			
		||||
use tui::{Frame, Terminal};
 | 
			
		||||
 | 
			
		||||
use crate::constants::*;
 | 
			
		||||
use crate::ui_screens::utils::centered_rect_size;
 | 
			
		||||
use crate::ui_screens::ScreenResult;
 | 
			
		||||
use crate::ui_widgets::button_widget::ButtonWidget;
 | 
			
		||||
 | 
			
		||||
struct ConfirmDialogScreen<'a> {
 | 
			
		||||
    title: &'a str,
 | 
			
		||||
    msg: &'a str,
 | 
			
		||||
    is_confirm: bool,
 | 
			
		||||
    can_cancel: bool,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn confirm_dialog<B: Backend>(
 | 
			
		||||
    msg: &str,
 | 
			
		||||
    terminal: &mut Terminal<B>,
 | 
			
		||||
) -> io::Result<ScreenResult<bool>> {
 | 
			
		||||
    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<B: Backend>(f: &mut Frame<B>, 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::<Vec<_>>();
 | 
			
		||||
    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]);
 | 
			
		||||
}
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user