2
2
3
3
extern crate iui;
4
4
use iui:: prelude:: * ;
5
- use iui:: controls:: { Label , Spinbox , Slider , VerticalBox , HorizontalBox , Group } ;
5
+ use iui:: controls:: { Label , Spinbox , Slider , Entry , MultilineEntry , VerticalBox , HorizontalBox , HorizontalSeparator , Group , Spacer } ;
6
6
use std:: rc:: Rc ;
7
7
use std:: cell:: RefCell ;
8
8
9
9
/// This struct will hold the values that multiple callbacks will need to access.
10
10
struct State {
11
11
slider_val : i64 ,
12
- spinner_val : i64
12
+ spinner_val : i64 ,
13
+ entry_val : String ,
14
+ multi_val : String ,
13
15
}
14
16
15
17
fn main ( ) {
16
18
// Initialize the UI framework.
17
19
let ui = UI :: init ( ) . unwrap ( ) ;
18
20
19
21
// Initialize the state of the application.
20
- let state = Rc :: new ( RefCell :: new ( State { slider_val : 0 , spinner_val : 0 } ) ) ;
21
-
22
- let input_group = Group :: new ( & ui, "Inputs" ) ;
23
- let input_vbox = VerticalBox :: new ( & ui) ;
24
- let slider = Slider :: new ( & ui, 1 , 100 ) ;
25
- let spinner = Spinbox :: new ( & ui, 1 , 100 ) ;
26
- input_vbox. append ( & ui, slider. clone ( ) , LayoutStrategy :: Compact ) ;
27
- input_vbox. append ( & ui, spinner. clone ( ) , LayoutStrategy :: Compact ) ;
28
- input_group. set_child ( & ui, input_vbox) ;
29
-
30
- let output_group = Group :: new ( & ui, "Outputs" ) ;
31
- let output_vbox = VerticalBox :: new ( & ui) ;
32
- let add_label = Label :: new ( & ui, "" ) ;
33
- let sub_label = Label :: new ( & ui, "" ) ;
34
- output_vbox. append ( & ui, add_label. clone ( ) , LayoutStrategy :: Compact ) ;
35
- output_vbox. append ( & ui, sub_label. clone ( ) , LayoutStrategy :: Compact ) ;
36
- output_group. set_child ( & ui, output_vbox) ;
22
+ let state = Rc :: new ( RefCell :: new ( State { slider_val : 0 , spinner_val : 0 , entry_val : "" . into ( ) , multi_val : "" . into ( ) } ) ) ;
37
23
24
+ // Set up the inputs for the application.
25
+ // While it's not necessary to create a block for this, it makes the code a lot easier
26
+ // to read; the indentation presents a visual cue informing the reader that these
27
+ // statements are related.
28
+ let ( input_group, slider, spinner, entry, multi) = {
29
+ // The group will hold all the inputs
30
+ let input_group = Group :: new ( & ui, "Inputs" ) ;
31
+ // The vertical box arranges the inputs within the groups
32
+ let input_vbox = VerticalBox :: new ( & ui) ;
33
+ input_vbox. set_padded ( & ui, true ) ;
34
+ // Numerical inputs
35
+ let slider = Slider :: new ( & ui, 1 , 100 ) ;
36
+ let spinner = Spinbox :: new ( & ui, 1 , 100 ) ;
37
+ let entry = Entry :: new ( & ui) ;
38
+ let multi = MultilineEntry :: new ( & ui) ;
39
+ // Add everything in hierarchy
40
+ // Note the reverse order here. Again, it's not necessary, but it improves
41
+ // readability.
42
+ input_vbox. append ( & ui, slider. clone ( ) , LayoutStrategy :: Compact ) ;
43
+ input_vbox. append ( & ui, spinner. clone ( ) , LayoutStrategy :: Compact ) ;
44
+ input_vbox. append ( & ui, Spacer :: new ( & ui) , LayoutStrategy :: Compact ) ;
45
+ input_vbox. append ( & ui, HorizontalSeparator :: new ( & ui) , LayoutStrategy :: Compact ) ;
46
+ input_vbox. append ( & ui, Spacer :: new ( & ui) , LayoutStrategy :: Compact ) ;
47
+ input_vbox. append ( & ui, entry. clone ( ) , LayoutStrategy :: Compact ) ;
48
+ input_vbox. append ( & ui, multi. clone ( ) , LayoutStrategy :: Stretchy ) ;
49
+ input_group. set_child ( & ui, input_vbox) ;
50
+ ( input_group, slider, spinner, entry, multi)
51
+ } ;
52
+
53
+ // Set up the outputs for the application.
54
+ let ( output_group, add_label, sub_label, text_label, bigtext_label) = {
55
+ let output_group = Group :: new ( & ui, "Outputs" ) ;
56
+ let output_vbox = VerticalBox :: new ( & ui) ;
57
+ let add_label = Label :: new ( & ui, "" ) ;
58
+ let sub_label = Label :: new ( & ui, "" ) ;
59
+ let text_label = Label :: new ( & ui, "" ) ;
60
+ let bigtext_label = Label :: new ( & ui, "" ) ;
61
+ output_vbox. append ( & ui, add_label. clone ( ) , LayoutStrategy :: Compact ) ;
62
+ output_vbox. append ( & ui, sub_label. clone ( ) , LayoutStrategy :: Compact ) ;
63
+ output_vbox. append ( & ui, text_label. clone ( ) , LayoutStrategy :: Compact ) ;
64
+ output_vbox. append ( & ui, bigtext_label. clone ( ) , LayoutStrategy :: Stretchy ) ;
65
+ output_group. set_child ( & ui, output_vbox) ;
66
+ ( output_group, add_label, sub_label, text_label, bigtext_label)
67
+ } ;
68
+
69
+ // This horizontal box will arrange the two groups of controls.
38
70
let hbox = HorizontalBox :: new ( & ui) ;
39
71
hbox. append ( & ui, input_group, LayoutStrategy :: Stretchy ) ;
40
72
hbox. append ( & ui, output_group, LayoutStrategy :: Stretchy ) ;
41
73
74
+ // The window allows all constituent components to be displayed.
42
75
let window = Window :: new ( & ui, "Input Output Test" , 300 , 150 , WindowType :: NoMenubar ) ;
43
76
window. set_child ( & ui, hbox) ;
44
77
window. show ( & ui) ;
45
78
79
+ // This update_view function is defined inline so that it can capture the environment, rather than
80
+ // needing to be passed ui, the labels, and the state each time it is invoked.
81
+ // It is wrapped in a refcounted pointer so it can be shared with several other closures.
46
82
let update_view = Rc :: new ( {
47
83
let ui = ui. clone ( ) ;
48
84
let add_label = add_label. clone ( ) ;
@@ -52,30 +88,54 @@ fn main() {
52
88
let state = state. borrow ( ) ;
53
89
add_label. set_text ( & ui, & format ! ( "Added: {}" , state. slider_val + state. spinner_val) ) ;
54
90
sub_label. set_text ( & ui, & format ! ( "Subtracted: {}" , state. slider_val - state. spinner_val) ) ;
91
+ text_label. set_text ( & ui, & format ! ( "Text: {}" , state. entry_val) ) ;
92
+ bigtext_label. set_text ( & ui, & format ! ( "Multiline Text: {}" , state. multi_val) ) ;
55
93
}
56
94
} ) ;
57
95
58
- update_view ( ) ;
96
+ // These on_changed functions allow updating the application state when a
97
+ // control changes its value.
98
+ // Note the calls to update_view after each change to the state!
59
99
60
- {
61
- let ui = ui. clone ( ) ;
100
+ slider. on_changed ( & ui, {
62
101
let update_view = update_view. clone ( ) ;
63
102
let state = state. clone ( ) ;
64
- slider . on_changed ( & ui , |val| {
103
+ move |val| {
65
104
state. borrow_mut ( ) . slider_val = val;
66
105
update_view ( ) ;
67
- } ) ;
68
- }
106
+ }
107
+ } ) ;
69
108
70
- {
71
- let ui = ui. clone ( ) ;
109
+ spinner. on_changed ( & ui, {
72
110
let update_view = update_view. clone ( ) ;
73
111
let state = state. clone ( ) ;
74
- spinner . on_changed ( & ui , |val| {
112
+ move |val| {
75
113
state. borrow_mut ( ) . spinner_val = val;
76
114
update_view ( ) ;
77
- } ) ;
78
- }
115
+ }
116
+ } ) ;
117
+
118
+ entry. on_changed ( & ui, {
119
+ let update_view = update_view. clone ( ) ;
120
+ let state = state. clone ( ) ;
121
+ move |val| {
122
+ state. borrow_mut ( ) . entry_val = val;
123
+ update_view ( ) ;
124
+ }
125
+ } ) ;
126
+
127
+ multi. on_changed ( & ui, {
128
+ let update_view = update_view. clone ( ) ;
129
+ let state = state. clone ( ) ;
130
+ move |val| {
131
+ state. borrow_mut ( ) . multi_val = val;
132
+ update_view ( ) ;
133
+ }
134
+ } ) ;
135
+
136
+ // The initial call to update_view sets up the initial GUI state.
137
+ update_view ( ) ;
79
138
139
+ // Start the application.
80
140
ui. main ( ) ;
81
141
}
0 commit comments