Skip to main content

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