use std::cell::RefCell;
use std::rc::Rc;
use turbo_vision::app::Application;
use turbo_vision::core::command::{CM_CANCEL, CM_OK};
use turbo_vision::core::geometry::Rect;
use turbo_vision::views::{
button::ButtonBuilder,
dialog::DialogBuilder,
input_line::InputLineBuilder,
label::LabelBuilder,
picture_validator::PictureValidator,
static_text::StaticTextBuilder,
validator::{FilterValidator, RangeValidator, Validator},
};
fn main() -> turbo_vision::core::error::Result<()> {
let mut app = Application::new()?;
demo_all_validators(&mut app);
Ok(())
}
fn demo_all_validators(app: &mut Application) {
let (width, height) = app.terminal.size();
let dialog_width = 65;
let dialog_height = 34;
let dialog_x = (width - dialog_width) / 2;
let dialog_y = (height - dialog_height) / 2;
let mut dialog = DialogBuilder::new()
.bounds(Rect::new(
dialog_x,
dialog_y,
dialog_x + dialog_width,
dialog_y + dialog_height,
))
.title("All Validator Types")
.build();
let instructions = StaticTextBuilder::new()
.bounds(Rect::new(2, 1, dialog_width - 4, 3))
.text("Try typing in each field. Invalid characters are rejected.\nClick OK to validate final values.")
.build();
dialog.add(Box::new(instructions));
let mut y = 4;
let section1 = StaticTextBuilder::new()
.bounds(Rect::new(2, y, dialog_width - 4, y + 1))
.text("=== Filter & Range Validators ===")
.build();
dialog.add(Box::new(section1));
y += 2;
let label1 = LabelBuilder::new()
.bounds(Rect::new(2, y, dialog_width - 4, y + 1))
.text("Digits only:")
.build();
dialog.add(Box::new(label1));
y += 1;
let field1_data = Rc::new(RefCell::new(String::from("12345")));
let field1_validator = Rc::new(RefCell::new(FilterValidator::new("0123456789")));
let input1 = InputLineBuilder::new()
.bounds(Rect::new(2, y, dialog_width - 4, y + 1))
.max_length(20)
.data(field1_data.clone())
.validator(field1_validator.clone())
.build();
dialog.add(Box::new(input1));
y += 2;
let label2 = LabelBuilder::new()
.bounds(Rect::new(2, y, dialog_width - 4, y + 1))
.text("Number (0-100):")
.build();
dialog.add(Box::new(label2));
y += 1;
let field2_data = Rc::new(RefCell::new(String::from("50")));
let field2_validator = Rc::new(RefCell::new(RangeValidator::new(0, 100)));
let input2 = InputLineBuilder::new()
.bounds(Rect::new(2, y, dialog_width - 4, y + 1))
.max_length(20)
.data(field2_data.clone())
.validator(field2_validator.clone())
.build();
dialog.add(Box::new(input2));
y += 2;
let label3 = LabelBuilder::new()
.bounds(Rect::new(2, y, dialog_width - 4, y + 1))
.text("Number (-50 to 50):")
.build();
dialog.add(Box::new(label3));
y += 1;
let field3_data = Rc::new(RefCell::new(String::from("-25")));
let field3_validator = Rc::new(RefCell::new(RangeValidator::new(-50, 50)));
let input3 = InputLineBuilder::new()
.bounds(Rect::new(2, y, dialog_width - 4, y + 1))
.max_length(20)
.data(field3_data.clone())
.validator(field3_validator.clone())
.build();
dialog.add(Box::new(input3));
y += 2;
let label4 = LabelBuilder::new()
.bounds(Rect::new(2, y, dialog_width - 4, y + 1))
.text("Hex (0x00-0xFF):")
.build();
dialog.add(Box::new(label4));
y += 1;
let field4_data = Rc::new(RefCell::new(String::from("0xAB")));
let field4_validator = Rc::new(RefCell::new(RangeValidator::new(0, 255)));
let input4 = InputLineBuilder::new()
.bounds(Rect::new(2, y, dialog_width - 4, y + 1))
.max_length(20)
.data(field4_data.clone())
.validator(field4_validator.clone())
.build();
dialog.add(Box::new(input4));
y += 3;
let section2 = StaticTextBuilder::new()
.bounds(Rect::new(2, y, dialog_width - 4, y + 1))
.text("=== Picture Mask Validators ===")
.build();
dialog.add(Box::new(section2));
y += 2;
let phone_label = LabelBuilder::new()
.bounds(Rect::new(2, y, 18, y + 1))
.text("~P~hone Number:")
.build();
dialog.add(Box::new(phone_label));
let phone_data = Rc::new(RefCell::new(String::new()));
let mut phone_input = InputLineBuilder::new()
.bounds(Rect::new(18, y, 35, y + 1))
.max_length(20)
.data(phone_data.clone())
.build();
phone_input.set_validator(Rc::new(RefCell::new(PictureValidator::new(
"(###) ###-####",
))));
dialog.add(Box::new(phone_input));
let phone_hint = StaticTextBuilder::new()
.bounds(Rect::new(36, y, 51, y + 1))
.text("(###) ###-####")
.build();
dialog.add(Box::new(phone_hint));
y += 2;
let date_label = LabelBuilder::new()
.bounds(Rect::new(2, y, 18, y + 1))
.text("~D~ate:")
.build();
dialog.add(Box::new(date_label));
let date_data = Rc::new(RefCell::new(String::new()));
let mut date_input = InputLineBuilder::new()
.bounds(Rect::new(18, y, 30, y + 1))
.max_length(10)
.data(date_data.clone())
.build();
date_input.set_validator(Rc::new(RefCell::new(PictureValidator::new("##/##/####"))));
dialog.add(Box::new(date_input));
let date_hint = StaticTextBuilder::new()
.bounds(Rect::new(31, y, 51, y + 1))
.text("##/##/####")
.build();
dialog.add(Box::new(date_hint));
y += 2;
let code_label = LabelBuilder::new()
.bounds(Rect::new(2, y, 18, y + 1))
.text("Product ~C~ode:")
.build();
dialog.add(Box::new(code_label));
let code_data = Rc::new(RefCell::new(String::new()));
let mut code_input = InputLineBuilder::new()
.bounds(Rect::new(18, y, 31, y + 1))
.max_length(9)
.data(code_data.clone())
.build();
code_input.set_validator(Rc::new(RefCell::new(PictureValidator::new("@@@@-####"))));
dialog.add(Box::new(code_input));
let code_hint = StaticTextBuilder::new()
.bounds(Rect::new(32, y, 51, y + 1))
.text("@@@@-####")
.build();
dialog.add(Box::new(code_hint));
y += 2;
let legend = StaticTextBuilder::new()
.bounds(Rect::new(2, y, dialog_width - 4, y + 2))
.text("Legend: # = digit, @ = letter, ! = any\nLiterals (like /, -, ()) are inserted automatically")
.build();
dialog.add(Box::new(legend));
y += 3;
let ok_button = ButtonBuilder::new()
.bounds(Rect::new(20, y, 30, y + 2))
.title(" OK ")
.command(CM_OK)
.default(true)
.build();
dialog.add(Box::new(ok_button));
let cancel_button = ButtonBuilder::new()
.bounds(Rect::new(35, y, 45, y + 2))
.title("Cancel")
.command(CM_CANCEL)
.build();
dialog.add(Box::new(cancel_button));
dialog.set_initial_focus();
let result = dialog.execute(app);
if result == CM_OK {
let mut all_valid = true;
println!("\n\nValidation Results:");
println!("==================");
let field1_text = field1_data.borrow().clone();
let field1_valid = field1_validator.borrow().is_valid(&field1_text);
println!(
"Field 1 (Digits only): \"{}\" - {}",
field1_text,
if field1_valid { "VALID" } else { "INVALID" }
);
all_valid &= field1_valid;
let field2_text = field2_data.borrow().clone();
let field2_valid = field2_validator.borrow().is_valid(&field2_text);
println!(
"Field 2 (0-100): \"{}\" - {}",
field2_text,
if field2_valid { "VALID" } else { "INVALID" }
);
all_valid &= field2_valid;
let field3_text = field3_data.borrow().clone();
let field3_valid = field3_validator.borrow().is_valid(&field3_text);
println!(
"Field 3 (-50 to 50): \"{}\" - {}",
field3_text,
if field3_valid { "VALID" } else { "INVALID" }
);
all_valid &= field3_valid;
let field4_text = field4_data.borrow().clone();
let field4_valid = field4_validator.borrow().is_valid(&field4_text);
println!(
"Field 4 (0x00-0xFF): \"{}\" - {}",
field4_text,
if field4_valid { "VALID" } else { "INVALID" }
);
all_valid &= field4_valid;
println!("\nFormatted Data Entered:");
println!("Phone: {}", phone_data.borrow());
println!("Date: {}", date_data.borrow());
println!("Code: {}", code_data.borrow());
println!(
"\nOverall: {}",
if all_valid {
"ALL FIELDS VALID"
} else {
"SOME FIELDS INVALID"
}
);
} else {
println!("\nDialog cancelled");
}
}