1extern crate native_windows_gui as nwg;
9use nwg::NativeUi;
10
11
12#[derive(Default)]
13pub struct PartialDemo {
14 window: nwg::Window,
15 layout: nwg::FlexboxLayout,
16 menu: nwg::ListBox<&'static str>,
17 frame1: nwg::Frame,
18 frame2: nwg::Frame,
19 frame3: nwg::Frame,
20
21 people_ui: PeopleUi,
22 animal_ui: AnimalUi,
23 food_ui: FoodUi,
24}
25
26impl PartialDemo {
27
28 fn change_interface(&self) {
29 self.frame1.set_visible(false);
30 self.frame2.set_visible(false);
31 self.frame3.set_visible(false);
32
33 let layout = &self.layout;
34 if layout.has_child(&self.frame1) { layout.remove_child(&self.frame1); }
35 if layout.has_child(&self.frame2) { layout.remove_child(&self.frame2); }
36 if layout.has_child(&self.frame3) { layout.remove_child(&self.frame3); }
37
38 use nwg::stretch::{geometry::Size, style::{Style, Dimension as D}};
39 let mut style = Style::default();
40 style.size = Size { width: D::Percent(1.0), height: D::Auto };
41
42 match self.menu.selection() {
43 None | Some(0) => {
44 layout.add_child(&self.frame1, style).unwrap();
45 self.frame1.set_visible(true);
46 },
47 Some(1) => {
48 layout.add_child(&self.frame2, style).unwrap();
49 self.frame2.set_visible(true);
50 },
51 Some(2) => {
52 layout.add_child(&self.frame3, style).unwrap();
53 self.frame3.set_visible(true);
54 },
55 Some(_) => unreachable!()
56 }
57 }
58
59 fn save(&self) {
60 nwg::simple_message("Saved!", "Data saved!");
61 }
62
63 fn exit(&self) {
64 nwg::stop_thread_dispatch();
65 }
66}
67
68#[derive(Default)]
69pub struct PeopleUi {
70 layout: nwg::GridLayout,
71 layout2: nwg::GridLayout,
72
73 label1: nwg::Label,
74 label2: nwg::Label,
75 label3: nwg::Label,
76
77 name_input: nwg::TextInput,
78 age_input: nwg::TextInput,
79 job_input: nwg::TextInput,
80
81 save_btn: nwg::Button,
82}
83
84#[derive(Default)]
85pub struct AnimalUi {
86 layout: nwg::GridLayout,
87 layout2: nwg::GridLayout,
88
89 label1: nwg::Label,
90 label2: nwg::Label,
91 label3: nwg::Label,
92
93 name_input: nwg::TextInput,
94 race_input: nwg::ComboBox<&'static str>,
95 is_soft_input: nwg::CheckBox,
96
97 save_btn: nwg::Button,
98}
99
100#[derive(Default)]
101pub struct FoodUi {
102 layout: nwg::GridLayout,
103 layout2: nwg::GridLayout,
104
105 label1: nwg::Label,
106 label2: nwg::Label,
107
108 name_input: nwg::TextInput,
109 tasty_input: nwg::CheckBox,
110
111 save_btn: nwg::Button,
112}
113
114
115mod partial_demo_ui {
119 use native_windows_gui as nwg;
120 use self::nwg::PartialUi;
121 use super::*;
122 use std::rc::Rc;
123 use std::cell::RefCell;
124 use std::ops::Deref;
125
126 pub struct PartialDemoUi {
127 inner: PartialDemo,
128 default_handler: RefCell<Vec<nwg::EventHandler>>
129 }
130
131 impl nwg::NativeUi<Rc<PartialDemoUi>> for PartialDemo {
132 fn build_ui(mut data: PartialDemo) -> Result<Rc<PartialDemoUi>, nwg::NwgError> {
133 use nwg::Event as E;
134
135 nwg::Window::builder()
137 .size((500, 400))
138 .position((300, 300))
139 .title("Many UI")
140 .build(&mut data.window)?;
141
142 nwg::ListBox::builder()
143 .collection(vec!["People", "Animals", "Food"])
144 .focus(true)
145 .parent(&data.window)
146 .build(&mut data.menu)?;
147
148 nwg::Frame::builder()
149 .parent(&data.window)
150 .build(&mut data.frame1)?;
151
152 nwg::Frame::builder()
153 .flags(nwg::FrameFlags::BORDER)
154 .parent(&data.window)
155 .build(&mut data.frame2)?;
156
157 nwg::Frame::builder()
158 .flags(nwg::FrameFlags::BORDER)
159 .parent(&data.window)
160 .build(&mut data.frame3)?;
161
162 PeopleUi::build_partial(&mut data.people_ui, Some(&data.frame1))?;
164 AnimalUi::build_partial(&mut data.animal_ui, Some(&data.frame2))?;
165 FoodUi::build_partial(&mut data.food_ui, Some(&data.frame3))?;
166
167 let ui = Rc::new(PartialDemoUi {
169 inner: data,
170 default_handler: Default::default()
171 });
172
173 let mut window_handles = vec![&ui.window.handle];
175 window_handles.append(&mut ui.people_ui.handles());
176 window_handles.append(&mut ui.animal_ui.handles());
177 window_handles.append(&mut ui.food_ui.handles());
178
179 for handle in window_handles.iter() {
180 let evt_ui = ui.clone();
181 let handle_events = move |evt, evt_data, handle| {
182 evt_ui.people_ui.process_event(evt, &evt_data, handle);
183 evt_ui.animal_ui.process_event(evt, &evt_data, handle);
184 evt_ui.food_ui.process_event(evt, &evt_data, handle);
185
186 match evt {
187 E::OnListBoxSelect =>
188 if &handle == &evt_ui.menu {
189 PartialDemo::change_interface(&evt_ui.inner);
190 },
191 E::OnWindowClose =>
192 if &handle == &evt_ui.window {
193 PartialDemo::exit(&evt_ui.inner);
194 },
195 E::OnButtonClick =>
196 if &handle == &evt_ui.people_ui.save_btn || &handle == &evt_ui.animal_ui.save_btn ||&handle == &evt_ui.food_ui.save_btn {
197 PartialDemo::save(&evt_ui.inner);
198 },
199 _ => {}
200 }
201 };
202
203 ui.default_handler.borrow_mut().push(
204 nwg::full_bind_event_handler(handle, handle_events)
205 );
206 }
207
208 use nwg::stretch::{geometry::Size, style::Dimension as D};
210
211 nwg::FlexboxLayout::builder()
212 .parent(&ui.window)
213 .child(&ui.menu)
214 .child_size(Size { width: D::Percent(0.3), height: D::Auto })
215 .child(&ui.frame1)
216 .child_size(Size { width: D::Percent(1.0), height: D::Auto })
217 .build(&ui.layout)?;
218
219 return Ok(ui);
220 }
221 }
222
223 impl PartialDemoUi {
224 pub fn destroy(&self) {
226 let mut handlers = self.default_handler.borrow_mut();
227 for handler in handlers.drain(0..) {
228 nwg::unbind_event_handler(&handler);
229 }
230 }
231 }
232
233 impl Deref for PartialDemoUi {
234 type Target = PartialDemo;
235
236 fn deref(&self) -> &PartialDemo {
237 &self.inner
238 }
239 }
240
241}
242
243mod partial_people_ui {
244 use native_windows_gui as nwg;
245 use self::nwg::{PartialUi, NwgError, ControlHandle};
246 use super::*;
247
248 impl PartialUi for PeopleUi {
249
250 fn build_partial<W: Into<ControlHandle>>(data: &mut PeopleUi, parent: Option<W>) -> Result<(), NwgError> {
251 let parent = parent.unwrap().into();
252
253 nwg::Label::builder()
254 .text("Name:")
255 .h_align(nwg::HTextAlign::Right)
256 .parent(&parent)
257 .build(&mut data.label1)?;
258
259 nwg::Label::builder()
260 .text("Age:")
261 .h_align(nwg::HTextAlign::Right)
262 .parent(&parent)
263 .build(&mut data.label2)?;
264
265 nwg::Label::builder()
266 .text("Job:")
267 .h_align(nwg::HTextAlign::Right)
268 .parent(&parent)
269 .build(&mut data.label3)?;
270
271 nwg::TextInput::builder()
272 .text("John Doe")
273 .parent(&parent)
274 .build(&mut data.name_input)?;
275
276 nwg::TextInput::builder()
277 .text("75")
278 .flags(nwg::TextInputFlags::VISIBLE | nwg::TextInputFlags::NUMBER)
279 .parent(&parent)
280 .build(&mut data.age_input)?;
281
282 nwg::TextInput::builder()
283 .text("Programmer")
284 .parent(&parent)
285 .build(&mut data.job_input)?;
286
287 nwg::Button::builder()
288 .text("Save")
289 .parent(&parent)
290 .build(&mut data.save_btn)?;
291
292 nwg::GridLayout::builder()
293 .parent(&parent)
294 .max_size([1000, 150])
295 .min_size([100, 120])
296 .child(0, 0, &data.label1)
297 .child(0, 1, &data.label2)
298 .child(0, 2, &data.label3)
299 .child(1, 0, &data.name_input)
300 .child(1, 1, &data.age_input)
301 .child(1, 2, &data.job_input)
302 .build(&data.layout)?;
303
304 nwg::GridLayout::builder()
305 .min_size([100, 200])
306 .max_column(Some(2))
307 .max_row(Some(6))
308 .child(1, 5, &data.save_btn)
309 .parent(&parent)
310 .build(&data.layout2)?;
311
312 Ok(())
313 }
314
315 fn process_event<'a>(&self, _evt: nwg::Event, _evt_data: &nwg::EventData, _handle: ControlHandle) {
316 }
317
318 fn handles(&self) -> Vec<&ControlHandle> {
319 Vec::new()
320 }
321 }
322}
323
324mod partial_animal_ui {
325 use native_windows_gui as nwg;
326 use self::nwg::{PartialUi, NwgError, ControlHandle};
327 use super::*;
328
329 impl PartialUi for AnimalUi {
330
331 fn build_partial<W: Into<ControlHandle>>(data: &mut AnimalUi, parent: Option<W>) -> Result<(), NwgError> {
332 let parent = parent.unwrap().into();
333
334 nwg::Label::builder()
335 .text("Name:")
336 .h_align(nwg::HTextAlign::Right)
337 .parent(&parent)
338 .build(&mut data.label1)?;
339
340 nwg::Label::builder()
341 .text("Race:")
342 .h_align(nwg::HTextAlign::Right)
343 .parent(&parent)
344 .build(&mut data.label2)?;
345
346 nwg::Label::builder()
347 .text("Is fluffy:")
348 .h_align(nwg::HTextAlign::Right)
349 .parent(&parent)
350 .build(&mut data.label3)?;
351
352 nwg::TextInput::builder()
353 .text("Mittens")
354 .parent(&parent)
355 .build(&mut data.name_input)?;
356
357 nwg::ComboBox::builder()
358 .collection(vec!["Cat", "Dog", "Pidgeon", "Monkey"])
359 .selected_index(Some(0))
360 .parent(&parent)
361 .build(&mut data.race_input)?;
362
363 nwg::CheckBox::builder()
364 .text("")
365 .check_state(nwg::CheckBoxState::Checked)
366 .parent(&parent)
367 .build(&mut data.is_soft_input)?;
368
369 nwg::Button::builder()
370 .text("Save")
371 .parent(&parent)
372 .build(&mut data.save_btn)?;
373
374 nwg::GridLayout::builder()
375 .parent(&parent)
376 .max_size([1000, 150])
377 .min_size([100, 120])
378 .child(0, 0, &data.label1)
379 .child(0, 1, &data.label2)
380 .child(0, 2, &data.label3)
381 .child(1, 0, &data.name_input)
382 .child(1, 1, &data.race_input)
383 .child(1, 2, &data.is_soft_input)
384 .build(&data.layout)?;
385
386 nwg::GridLayout::builder()
387 .min_size([100, 200])
388 .max_column(Some(2))
389 .max_row(Some(6))
390 .child(1, 5, &data.save_btn)
391 .parent(&parent)
392 .build(&data.layout2)?;
393
394 Ok(())
395 }
396
397 fn process_event<'a>(&self, _evt: nwg::Event, _evt_data: &nwg::EventData, _handle: ControlHandle) {
398 }
399
400 fn handles(&self) -> Vec<&ControlHandle> {
401 Vec::new()
402 }
403 }
404}
405
406mod partial_food_ui {
407 use native_windows_gui as nwg;
408 use self::nwg::{PartialUi, NwgError, ControlHandle};
409 use super::*;
410
411 impl PartialUi for FoodUi {
412 fn build_partial<W: Into<ControlHandle>>(data: &mut FoodUi, parent: Option<W>) -> Result<(), NwgError> {
413 let parent = parent.unwrap().into();
414
415 nwg::Label::builder()
416 .text("Name:")
417 .h_align(nwg::HTextAlign::Right)
418 .parent(&parent)
419 .build(&mut data.label1)?;
420
421 nwg::Label::builder()
422 .text("Tasty:")
423 .h_align(nwg::HTextAlign::Right)
424 .parent(&parent)
425 .build(&mut data.label2)?;
426
427 nwg::TextInput::builder()
428 .text("Banana")
429 .parent(&parent)
430 .build(&mut data.name_input)?;
431
432 nwg::CheckBox::builder()
433 .text("")
434 .check_state(nwg::CheckBoxState::Checked)
435 .parent(&parent)
436 .build(&mut data.tasty_input)?;
437
438 nwg::Button::builder()
439 .text("Save")
440 .parent(&parent)
441 .build(&mut data.save_btn)?;
442
443 nwg::GridLayout::builder()
444 .parent(&parent)
445 .max_size([1000, 90])
446 .min_size([100, 80])
447 .child(0, 0, &data.label1)
448 .child(0, 1, &data.label2)
449 .child(1, 0, &data.name_input)
450 .child(1, 1, &data.tasty_input)
451 .build(&data.layout)?;
452
453 nwg::GridLayout::builder()
454 .min_size([100, 200])
455 .max_column(Some(2))
456 .max_row(Some(6))
457 .child(1, 5, &data.save_btn)
458 .parent(&parent)
459 .build(&data.layout2)?;
460
461 Ok(())
462 }
463
464 fn process_event<'a>(&self, _evt: nwg::Event, _evt_data: &nwg::EventData, _handle: ControlHandle) {
465 }
466
467 fn handles(&self) -> Vec<&ControlHandle> {
468 Vec::new()
469 }
470 }
471}
472
473
474
475fn main() {
476 nwg::init().expect("Failed to init Native Windows GUI");
477 nwg::Font::set_global_family("Segoe UI").expect("Failed to set default font");
478
479 let ui = PartialDemo::build_ui(Default::default()).expect("Failed to build UI");
480 nwg::dispatch_thread_events();
481 ui.destroy();
482}