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