extern crate native_windows_gui as nwg;
extern crate native_windows_derive as nwd;
use nwd::NwgUi;
use nwg::NativeUi;
use std::{thread, cell::RefCell};
#[derive(Default, NwgUi)]
pub struct ThreadingDialog {
data: RefCell<String>,
#[nwg_control(size: (300, 115), position: (650, 300), title: "A dialog", flags: "WINDOW|VISIBLE")]
#[nwg_events( OnWindowClose: [ThreadingDialog::close] )]
window: nwg::Window,
#[nwg_control(text: "YES", position: (10, 10), size: (130, 95))]
#[nwg_events( OnButtonClick: [ThreadingDialog::choose(SELF, CTRL)] )]
choice_yes: nwg::Button,
#[nwg_control(text: "NO", position: (160, 10), size: (130, 95), focus: true)]
#[nwg_events( OnButtonClick: [ThreadingDialog::choose(SELF, CTRL)] )]
choice_no: nwg::Button,
}
impl ThreadingDialog {
fn close(&self) {
nwg::stop_thread_dispatch();
}
fn choose(&self, btn: &nwg::Button) {
let mut data = self.data.borrow_mut();
if btn == &self.choice_no {
*data = "No!".to_string();
} else if btn == &self.choice_yes {
*data = "Yes!".to_string();
}
self.window.close();
}
}
#[derive(Default, NwgUi)]
pub struct ThreadingApp {
dialog_data: RefCell<Option<thread::JoinHandle<String>>>,
#[nwg_control(size: (300, 115), position: (300, 300), title: "Multithreading example", flags: "WINDOW|VISIBLE")]
#[nwg_events( OnWindowClose: [ThreadingApp::exit] )]
window: nwg::Window,
#[nwg_control]
#[nwg_events( OnNotice: [ThreadingApp::read_dialog_output] )]
dialog_notice: nwg::Notice,
#[nwg_control(size: (280, 25), position: (10, 10), readonly: true)]
name_edit: nwg::TextInput,
#[nwg_control(text: "Open Dialog", size: (280, 60), position: (10, 40), focus: true)]
#[nwg_events( OnButtonClick: [ThreadingApp::open_dialog] )]
button: nwg::Button,
}
impl ThreadingApp {
fn exit(&self) {
nwg::stop_thread_dispatch();
}
fn open_dialog(&self) {
let mut data = self.dialog_data.borrow_mut();
if data.is_some() {
nwg::error_message("Error", "The dialog is already running!");
return;
}
let notice = self.dialog_notice.sender();
*data = Some(thread::spawn(move || {
let app = ThreadingDialog::build_ui(Default::default()).expect("Failed to build UI");
nwg::dispatch_thread_events();
notice.notice();
{
let data = app.data.borrow();
data.clone()
}
}))
}
fn read_dialog_output(&self) {
let mut data = self.dialog_data.borrow_mut();
match data.take() {
Some(handle) => {
self.name_edit.set_text(&handle.join().unwrap());
self.button.set_focus();
},
None => {}
}
}
}
fn main() {
nwg::init().expect("Failed to init Native Windows GUI");
nwg::Font::set_global_family("Segoe UI").expect("Failed to set default font");
let _app = ThreadingApp::build_ui(Default::default()).expect("Failed to build UI");
nwg::dispatch_thread_events();
}