use super::DialogButtons;
use super::DialogResult;
use crate::prelude::*;
#[ModalWindow(events = ButtonEvents, internal: true, response: DialogResult)]
pub struct GenericAlertDialog {
b_ok: Handle<Button>,
b_yes: Handle<Button>,
b_no: Handle<Button>,
b_cancel: Handle<Button>,
b_retry: Handle<Button>,
}
impl GenericAlertDialog {
const BUTTON_SIZE: u32 = 12;
fn compute_text_width_and_lines(text: &str) -> (u32, u32) {
let mut nr_lines = 0;
let mut max_length = 0;
let mut current_line_len = 0;
for c in text.chars() {
if c == '\n' {
max_length = max_length.max(current_line_len);
current_line_len = 0;
nr_lines += 1;
} else {
current_line_len += 1;
}
}
if current_line_len > 0 {
max_length = max_length.max(current_line_len);
nr_lines += 1;
}
nr_lines = nr_lines.max(1);
(nr_lines, max_length)
}
fn compute_text_lines(text: &str, width: u32) -> u32 {
let mut nr_lines = 0;
let mut current_line_len = 0;
for c in text.chars() {
if c == '\n' {
current_line_len = 0;
nr_lines += 1;
} else {
current_line_len += 1;
if current_line_len == width {
current_line_len = 0;
nr_lines += 1;
}
}
}
if current_line_len > 0 {
nr_lines += 1;
}
nr_lines = nr_lines.max(1);
nr_lines
}
fn add_button(text: &str, x: i32, y: i32) -> Button {
Button::with_type(text, LayoutBuilder::new().x(x).y(y).width(11).build(), button::Type::Normal)
}
pub(super) fn new(title: &str, caption: &str, buttons: DialogButtons, background: window::Background) -> Self {
let size = RuntimeManager::get().terminal_size();
let min_window_width = buttons.count() * GenericAlertDialog::BUTTON_SIZE + 3;
let max_window_width = min_window_width.max(size.width * 8 / 10);
let (mut nr_lines, mut text_width) = GenericAlertDialog::compute_text_width_and_lines(caption);
if text_width + 4 <= max_window_width {
text_width = text_width.max(min_window_width - 4);
} else {
text_width = (max_window_width - 4).max(min_window_width - 4);
nr_lines = GenericAlertDialog::compute_text_lines(caption, text_width);
}
let max_window_height = (size.height * 8 / 10).max(8);
nr_lines = nr_lines.min(max_window_height - 7);
let window_width = text_width + 4;
let window_height = nr_lines + 7;
let mut w = Self {
base: ModalWindow::with_background(
title,
LayoutBuilder::new()
.alignment(Alignment::Center)
.width(window_width)
.height(window_height)
.build(),
window::Flags::NoCloseButton,
background,
),
b_ok: Handle::None,
b_yes: Handle::None,
b_no: Handle::None,
b_cancel: Handle::None,
b_retry: Handle::None,
};
let mut lb_info = label!("'',l:1,t:1,r:1,b:3");
lb_info.set_caption(caption);
w.add(lb_info);
let mut x = ((window_width - (buttons.count() * GenericAlertDialog::BUTTON_SIZE)) >> 1) as i32;
let y = (window_height - 4) as i32;
match buttons {
DialogButtons::Ok => {
w.b_ok = w.add(GenericAlertDialog::add_button("&Ok", x, y));
}
DialogButtons::YesNo => {
w.b_yes = w.add(GenericAlertDialog::add_button("&Yes", x, y));
x += GenericAlertDialog::BUTTON_SIZE as i32;
w.b_no = w.add(GenericAlertDialog::add_button("&No", x, y));
}
DialogButtons::YesNoCancel => {
w.b_yes = w.add(GenericAlertDialog::add_button("&Yes", x, y));
x += GenericAlertDialog::BUTTON_SIZE as i32;
w.b_no = w.add(GenericAlertDialog::add_button("&No", x, y));
x += GenericAlertDialog::BUTTON_SIZE as i32;
w.b_cancel = w.add(GenericAlertDialog::add_button("&Cancel", x, y));
}
DialogButtons::RetryCancel => {
w.b_retry = w.add(GenericAlertDialog::add_button("&Retry", x, y));
x += GenericAlertDialog::BUTTON_SIZE as i32;
w.b_cancel = w.add(GenericAlertDialog::add_button("&Cancel", x, y));
}
}
w
}
}
impl ButtonEvents for GenericAlertDialog {
fn on_pressed(&mut self, handle: Handle<Button>) -> EventProcessStatus {
match () {
_ if handle == self.b_ok => {
self.exit_with(DialogResult::Ok);
}
_ if handle == self.b_yes => {
self.exit_with(DialogResult::Yes);
}
_ if handle == self.b_no => {
self.exit_with(DialogResult::No);
}
_ if handle == self.b_cancel => {
self.exit_with(DialogResult::Cancel);
}
_ if handle == self.b_retry => {
self.exit_with(DialogResult::Retry);
}
_ => {
return EventProcessStatus::Ignored;
}
}
EventProcessStatus::Processed
}
}