basic_layout/
basic_layout.rs

1/*!
2    A very simple application that show your name in a message box.
3    Uses layouts to position the controls in the window
4*/
5
6extern crate native_windows_gui as nwg;
7use nwg::NativeUi;
8
9
10#[derive(Default)]
11pub struct BasicApp {
12    window: nwg::Window,
13    layout: nwg::GridLayout,
14    name_edit: nwg::TextInput,
15    hello_button: nwg::Button
16}
17
18impl BasicApp {
19
20    fn say_hello(&self) {
21        nwg::modal_info_message(&self.window, "Hello", &format!("Hello {}", self.name_edit.text()));
22    }
23    
24    fn say_goodbye(&self) {
25        nwg::modal_info_message(&self.window, "Goodbye", &format!("Goodbye {}", self.name_edit.text()));
26        nwg::stop_thread_dispatch();
27    }
28
29}
30
31//
32// ALL of this stuff is handled by native-windows-derive
33//
34mod basic_app_ui {
35    use native_windows_gui as nwg;
36    use super::*;
37    use std::rc::Rc;
38    use std::cell::RefCell;
39    use std::ops::Deref;
40
41    pub struct BasicAppUi {
42        inner: Rc<BasicApp>,
43        default_handler: RefCell<Option<nwg::EventHandler>>
44    }
45
46    impl nwg::NativeUi<BasicAppUi> for BasicApp {
47        fn build_ui(mut data: BasicApp) -> Result<BasicAppUi, nwg::NwgError> {
48            use nwg::Event as E;
49            
50            // Controls
51            nwg::Window::builder()
52                .flags(nwg::WindowFlags::WINDOW | nwg::WindowFlags::VISIBLE)
53                .size((300, 115))
54                .position((300, 300))
55                .title("Basic example")
56                .build(&mut data.window)?;
57
58            nwg::TextInput::builder()
59                .text("Heisenberg")
60                .parent(&data.window)
61                .focus(true)
62                .build(&mut data.name_edit)?;
63
64            nwg::Button::builder()
65                .text("Say my name")
66                .parent(&data.window)
67                .build(&mut data.hello_button)?;
68
69            // Wrap-up
70            let ui = BasicAppUi {
71                inner: Rc::new(data),
72                default_handler: Default::default(),
73            };
74
75            // Events
76            let evt_ui = Rc::downgrade(&ui.inner);
77            let handle_events = move |evt, _evt_data, handle| {
78                if let Some(evt_ui) = evt_ui.upgrade() {
79                    match evt {
80                        E::OnButtonClick => 
81                            if &handle == &evt_ui.hello_button {
82                                BasicApp::say_hello(&evt_ui);
83                            },
84                        E::OnWindowClose => 
85                            if &handle == &evt_ui.window {
86                                BasicApp::say_goodbye(&evt_ui);
87                            },
88                        _ => {}
89                    }
90                }
91            };
92
93           *ui.default_handler.borrow_mut() = Some(nwg::full_bind_event_handler(&ui.window.handle, handle_events));
94
95           // Layouts
96           nwg::GridLayout::builder()
97            .parent(&ui.window)
98            .spacing(1)
99            .child(0, 0, &ui.name_edit)
100            .child_item(nwg::GridLayoutItem::new(&ui.hello_button, 0, 1, 1, 2))
101            .build(&ui.layout)?;
102
103            return Ok(ui);
104        }
105    }
106
107    impl Drop for BasicAppUi {
108        /// To make sure that everything is freed without issues, the default handler must be unbound.
109        fn drop(&mut self) {
110            let handler = self.default_handler.borrow();
111            if handler.is_some() {
112                nwg::unbind_event_handler(handler.as_ref().unwrap());
113            }
114        }
115    }
116
117    impl Deref for BasicAppUi {
118        type Target = BasicApp;
119
120        fn deref(&self) -> &BasicApp {
121            &self.inner
122        }
123    }
124}
125
126fn main() {
127    nwg::init().expect("Failed to init Native Windows GUI");
128    nwg::Font::set_global_family("Segoe UI").expect("Failed to set default font");
129    let _ui = BasicApp::build_ui(Default::default()).expect("Failed to build UI");
130    nwg::dispatch_thread_events();
131}