flexbox/
flexbox.rs

1/*!
2    A very simple application that show how to use a flexbox layout.
3
4    Requires the following features: `cargo run --example flexbox --features "flexbox"`
5*/
6
7extern crate native_windows_gui2 as nwg;
8use nwg::NativeUi;
9
10#[derive(Default)]
11pub struct FlexBoxApp {
12    window: nwg::Window,
13    layout: nwg::FlexboxLayout,
14    button1: nwg::Button,
15    button2: nwg::Button,
16    button3: nwg::Button,
17}
18
19impl FlexBoxApp {
20    fn exit(&self) {
21        nwg::stop_thread_dispatch();
22    }
23}
24
25//
26// ALL of this stuff is handled by native-windows-derive
27//
28mod flexbox_app_ui {
29    use super::*;
30    use native_windows_gui2 as nwg;
31    use std::cell::RefCell;
32    use std::ops::Deref;
33    use std::rc::Rc;
34
35    pub struct FlexBoxAppUi {
36        inner: Rc<FlexBoxApp>,
37        default_handler: RefCell<Option<nwg::EventHandler>>,
38    }
39
40    impl nwg::NativeUi<FlexBoxAppUi> for FlexBoxApp {
41        fn build_ui(mut data: FlexBoxApp) -> Result<FlexBoxAppUi, nwg::NwgError> {
42            use nwg::Event as E;
43
44            // Controls
45            nwg::Window::builder()
46                .size((500, 300))
47                .position((300, 300))
48                .title("Flexbox example")
49                .build(&mut data.window)?;
50
51            nwg::Button::builder()
52                .text("Btn 1")
53                .parent(&data.window)
54                .focus(true)
55                .build(&mut data.button1)?;
56
57            nwg::Button::builder()
58                .text("Btn 2")
59                .parent(&data.window)
60                .build(&mut data.button2)?;
61
62            nwg::Button::builder()
63                .text("Btn 3")
64                .parent(&data.window)
65                .build(&mut data.button3)?;
66
67            // Wrap-up
68            let ui = FlexBoxAppUi {
69                inner: Rc::new(data),
70                default_handler: Default::default(),
71            };
72
73            // Events
74            let evt_ui = Rc::downgrade(&ui.inner);
75            let handle_events = move |evt, _evt_data, handle| {
76                if let Some(evt_ui) = evt_ui.upgrade() {
77                    match evt {
78                        E::OnWindowClose => {
79                            if &handle == &evt_ui.window {
80                                FlexBoxApp::exit(&evt_ui);
81                            }
82                        }
83                        _ => {}
84                    }
85                }
86            };
87
88            *ui.default_handler.borrow_mut() = Some(nwg::full_bind_event_handler(
89                &ui.window.handle,
90                handle_events,
91            ));
92
93            // Layout
94            use nwg::stretch::{
95                geometry::{Rect, Size},
96                style::{AlignSelf, Dimension as D, FlexDirection},
97            };
98            const FIFTY_PC: D = D::Percent(0.5);
99            const PT_10: D = D::Points(10.0);
100            const PT_5: D = D::Points(5.0);
101            const PADDING: Rect<D> = Rect {
102                start: PT_10,
103                end: PT_10,
104                top: PT_10,
105                bottom: PT_10,
106            };
107            const MARGIN: Rect<D> = Rect {
108                start: PT_5,
109                end: PT_5,
110                top: PT_5,
111                bottom: PT_5,
112            };
113
114            nwg::FlexboxLayout::builder()
115                .parent(&ui.window)
116                .flex_direction(FlexDirection::Row)
117                .padding(PADDING)
118                .child(&ui.button1)
119                .child_margin(MARGIN)
120                .child_max_size(Size {
121                    width: D::Points(200.0),
122                    height: D::Undefined,
123                })
124                .child_size(Size {
125                    width: FIFTY_PC,
126                    height: D::Auto,
127                })
128                .child(&ui.button2)
129                .child_margin(MARGIN)
130                .child_align_self(AlignSelf::FlexEnd)
131                .child_size(Size {
132                    width: D::Percent(0.25),
133                    height: FIFTY_PC,
134                })
135                .child(&ui.button3)
136                .child_margin(MARGIN)
137                .child_flex_grow(2.0)
138                .child_size(Size {
139                    width: D::Auto,
140                    height: D::Auto,
141                })
142                .build(&ui.layout)?;
143
144            return Ok(ui);
145        }
146    }
147
148    impl Drop for FlexBoxAppUi {
149        /// To make sure that everything is freed without issues, the default handler must be unbound.
150        fn drop(&mut self) {
151            let handler = self.default_handler.borrow();
152            if handler.is_some() {
153                nwg::unbind_event_handler(handler.as_ref().unwrap());
154            }
155        }
156    }
157
158    impl Deref for FlexBoxAppUi {
159        type Target = FlexBoxApp;
160
161        fn deref(&self) -> &FlexBoxApp {
162            &self.inner
163        }
164    }
165}
166
167fn main() {
168    nwg::init().expect("Failed to init Native Windows GUI");
169    nwg::Font::set_global_family("Segoe UI").expect("Failed to set default font");
170
171    let _ui = FlexBoxApp::build_ui(Default::default()).expect("Failed to build UI");
172
173    nwg::dispatch_thread_events();
174}