cushy/examples/focus-order.rs
2024-07-26 10:34:30 -07:00

70 lines
2.2 KiB
Rust

use std::process::exit;
use cushy::figures::units::Lp;
use cushy::value::{Dynamic, MapEach, Source};
use cushy::widget::{MakeWidget, MakeWidgetWithTag, WidgetTag};
use cushy::widgets::grid::{Grid, GridDimension, GridWidgets};
use cushy::widgets::input::{InputValue, MaskedString};
use cushy::widgets::Expand;
use cushy::Run;
/// This example is the same as login, but it has an explicit tab order to
/// change from the default order (username, password, cancel, log in) to
/// username, password, log in, cancel.
fn main() -> cushy::Result {
let username = Dynamic::default();
let password = Dynamic::default();
let valid =
(&username, &password).map_each(|(username, password)| validate(username, password));
let (login_tag, login_id) = WidgetTag::new();
let (cancel_tag, cancel_id) = WidgetTag::new();
let (username_tag, username_id) = WidgetTag::new();
let username_row = ("Username", username.to_input().make_with_tag(username_tag));
let password_row = ("Password", password.to_input().with_next_focus(login_id));
let buttons = "Cancel"
.into_button()
.on_click(|_| {
eprintln!("Login cancelled");
exit(0)
})
.make_with_tag(cancel_tag)
.into_escape()
.with_next_focus(username_id)
.and(Expand::empty())
.and(
"Log In"
.into_button()
.on_click(move |_| {
println!("Welcome, {}", username.get());
exit(0);
})
.make_with_tag(login_tag)
.with_enabled(valid)
.into_default()
.with_next_focus(cancel_id),
)
.into_columns();
Grid::from_rows(GridWidgets::from(username_row).and(password_row))
.dimensions([
GridDimension::FitContent,
GridDimension::Fractional { weight: 1 },
])
.and(buttons)
.into_rows()
.contain()
.width(Lp::points(300)..Lp::points(600))
.scroll()
.centered()
.run()
}
#[allow(clippy::ptr_arg)] // Changing &String to &str breaks type inference
fn validate(username: &String, password: &MaskedString) -> bool {
!username.is_empty() && !password.is_empty()
}