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