1
1
use cascade:: cascade;
2
- use futures:: { prelude:: * , stream:: FuturesUnordered } ;
3
- use glib:: clone;
4
2
use gtk:: prelude:: * ;
5
3
use gtk:: subclass:: prelude:: * ;
6
4
use once_cell:: sync:: Lazy ;
7
- use std:: { cell :: RefCell , collections:: HashMap , rc :: Rc } ;
5
+ use std:: collections:: HashMap ;
8
6
9
7
use crate :: Keyboard ;
10
8
use backend:: DerefCell ;
11
9
12
10
mod picker_group;
11
+ mod picker_group_box;
13
12
mod picker_json;
14
13
mod picker_key;
15
14
16
- use picker_group :: PickerGroup ;
15
+ use picker_group_box :: PickerGroupBox ;
17
16
use picker_json:: picker_json;
18
17
use picker_key:: PickerKey ;
19
18
20
- const DEFAULT_COLS : usize = 3 ;
21
- const HSPACING : i32 = 64 ;
22
- const VSPACING : i32 = 32 ;
23
- const PICKER_CSS : & str = r#"
24
- button {
25
- margin: 0;
26
- padding: 0;
27
- }
28
-
29
- .selected {
30
- border-color: #fbb86c;
31
- border-width: 4px;
32
- }
33
- "# ;
34
-
35
19
pub static SCANCODE_LABELS : Lazy < HashMap < String , String > > = Lazy :: new ( || {
36
20
let mut labels = HashMap :: new ( ) ;
37
21
for group in picker_json ( ) {
@@ -44,187 +28,41 @@ pub static SCANCODE_LABELS: Lazy<HashMap<String, String>> = Lazy::new(|| {
44
28
45
29
#[ derive( Default ) ]
46
30
pub struct PickerInner {
47
- groups : DerefCell < Vec < PickerGroup > > ,
48
- keys : DerefCell < HashMap < String , Rc < PickerKey > > > ,
49
- keyboard : RefCell < Option < Keyboard > > ,
50
- selected : RefCell < Vec < String > > ,
31
+ group_box : DerefCell < PickerGroupBox > ,
51
32
}
52
33
53
34
#[ glib:: object_subclass]
54
35
impl ObjectSubclass for PickerInner {
55
36
const NAME : & ' static str = "S76KeyboardPicker" ;
56
- type ParentType = gtk:: Container ;
37
+ type ParentType = gtk:: Box ;
57
38
type Type = Picker ;
58
39
}
59
40
60
41
impl ObjectImpl for PickerInner {
61
42
fn constructed ( & self , picker : & Picker ) {
62
43
self . parent_constructed ( picker) ;
63
44
64
- let style_provider = cascade ! {
65
- gtk:: CssProvider :: new( ) ;
66
- ..load_from_data( & PICKER_CSS . as_bytes( ) ) . expect( "Failed to parse css" ) ;
67
- } ;
68
-
69
- let mut groups = Vec :: new ( ) ;
70
- let mut keys = HashMap :: new ( ) ;
71
-
72
- for json_group in picker_json ( ) {
73
- let mut group = PickerGroup :: new ( json_group. label , json_group. cols ) ;
74
-
75
- for json_key in json_group. keys {
76
- let key = PickerKey :: new (
77
- json_key. keysym . clone ( ) ,
78
- json_key. label ,
79
- json_group. width ,
80
- & style_provider,
81
- ) ;
82
-
83
- group. add_key ( key. clone ( ) ) ;
84
- keys. insert ( json_key. keysym , key) ;
85
- }
86
-
87
- groups. push ( group) ;
88
- }
89
-
90
- for group in & groups {
91
- group. vbox . show ( ) ;
92
- group. vbox . set_parent ( picker) ;
93
- }
94
-
95
- self . keys . set ( keys) ;
96
- self . groups . set ( groups) ;
45
+ let group_box = PickerGroupBox :: new ( ) ;
97
46
98
47
cascade ! {
99
48
picker;
100
- ..connect_signals ( ) ;
49
+ ..add ( & group_box ) ;
101
50
..show_all( ) ;
102
51
} ;
103
- }
104
- }
105
-
106
- impl WidgetImpl for PickerInner {
107
- fn get_request_mode ( & self , _widget : & Self :: Type ) -> gtk:: SizeRequestMode {
108
- gtk:: SizeRequestMode :: HeightForWidth
109
- }
110
-
111
- fn get_preferred_width ( & self , _widget : & Self :: Type ) -> ( i32 , i32 ) {
112
- let minimum_width = self
113
- . groups
114
- . iter ( )
115
- . map ( |x| x. vbox . get_preferred_width ( ) . 1 )
116
- . max ( )
117
- . unwrap ( ) ;
118
- let natural_width = self
119
- . groups
120
- . chunks ( 3 )
121
- . map ( |row| {
122
- row. iter ( )
123
- . map ( |x| x. vbox . get_preferred_width ( ) . 1 )
124
- . sum :: < i32 > ( )
125
- } )
126
- . max ( )
127
- . unwrap ( )
128
- + 2 * HSPACING ;
129
- ( minimum_width, natural_width)
130
- }
131
-
132
- fn get_preferred_height_for_width ( & self , widget : & Self :: Type , width : i32 ) -> ( i32 , i32 ) {
133
- let rows = widget. rows_for_width ( width) ;
134
- let height = rows
135
- . iter ( )
136
- . map ( |row| {
137
- row. iter ( )
138
- . map ( |x| x. vbox . get_preferred_height ( ) . 1 )
139
- . max ( )
140
- . unwrap ( )
141
- } )
142
- . sum :: < i32 > ( )
143
- + ( rows. len ( ) as i32 - 1 ) * VSPACING ;
144
-
145
- ( height, height)
146
- }
147
-
148
- fn size_allocate ( & self , obj : & Self :: Type , allocation : & gtk:: Allocation ) {
149
- self . parent_size_allocate ( obj, allocation) ;
150
-
151
- let rows = obj. rows_for_width ( allocation. width ) ;
152
-
153
- let total_width = rows
154
- . iter ( )
155
- . map ( |row| {
156
- row. iter ( )
157
- . map ( |x| x. vbox . get_preferred_width ( ) . 1 )
158
- . sum :: < i32 > ( )
159
- + ( row. len ( ) as i32 - 1 ) * HSPACING
160
- } )
161
- . max ( )
162
- . unwrap ( ) ;
163
-
164
- let mut y = 0 ;
165
- for row in rows {
166
- let mut x = ( allocation. width - total_width) / 2 ;
167
- for group in row {
168
- let height = group. vbox . get_preferred_height ( ) . 1 ;
169
- let width = group. vbox . get_preferred_width ( ) . 1 ;
170
- group. vbox . size_allocate ( & gtk:: Allocation {
171
- x,
172
- y,
173
- width,
174
- height,
175
- } ) ;
176
- x += width + HSPACING ;
177
- }
178
- y += row
179
- . iter ( )
180
- . map ( |x| x. vbox . get_preferred_height ( ) . 1 )
181
- . max ( )
182
- . unwrap ( )
183
- + VSPACING ;
184
- }
185
- }
186
-
187
- fn realize ( & self , widget : & Self :: Type ) {
188
- let allocation = widget. get_allocation ( ) ;
189
- widget. set_realized ( true ) ;
190
-
191
- let attrs = gdk:: WindowAttr {
192
- x : Some ( allocation. x ) ,
193
- y : Some ( allocation. y ) ,
194
- width : allocation. width ,
195
- height : allocation. height ,
196
- window_type : gdk:: WindowType :: Child ,
197
- event_mask : widget. get_events ( ) ,
198
- wclass : gdk:: WindowWindowClass :: InputOutput ,
199
- ..Default :: default ( )
200
- } ;
201
52
202
- let window = gdk:: Window :: new ( widget. get_parent_window ( ) . as_ref ( ) , & attrs) ;
203
- widget. register_window ( & window) ;
204
- widget. set_window ( & window) ;
53
+ self . group_box . set ( group_box) ;
205
54
}
206
55
}
207
56
208
- impl ContainerImpl for PickerInner {
209
- fn forall (
210
- & self ,
211
- _obj : & Self :: Type ,
212
- _include_internals : bool ,
213
- cb : & gtk:: subclass:: container:: Callback ,
214
- ) {
215
- for group in self . groups . iter ( ) {
216
- cb. call ( group. vbox . upcast_ref ( ) ) ;
217
- }
218
- }
57
+ impl BoxImpl for PickerInner { }
219
58
220
- fn remove ( & self , _obj : & Self :: Type , child : & gtk:: Widget ) {
221
- child. unparent ( ) ;
222
- }
223
- }
59
+ impl WidgetImpl for PickerInner { }
60
+
61
+ impl ContainerImpl for PickerInner { }
224
62
225
63
glib:: wrapper! {
226
64
pub struct Picker ( ObjectSubclass <PickerInner >)
227
- @extends gtk:: Container , gtk:: Widget , @implements gtk:: Orientable ;
65
+ @extends gtk:: Box , gtk :: Container , gtk:: Widget , @implements gtk:: Orientable ;
228
66
}
229
67
230
68
impl Picker {
@@ -236,101 +74,16 @@ impl Picker {
236
74
PickerInner :: from_instance ( self )
237
75
}
238
76
239
- fn connect_signals ( & self ) {
240
- let picker = self ;
241
- for group in self . inner ( ) . groups . iter ( ) {
242
- for key in group. iter_keys ( ) {
243
- let button = & key. gtk ;
244
- let name = key. name . to_string ( ) ;
245
- button. connect_clicked ( clone ! ( @weak picker => @default -panic, move |_| {
246
- let kb = match picker. inner( ) . keyboard. borrow( ) . clone( ) {
247
- Some ( kb) => kb,
248
- None => {
249
- return ;
250
- }
251
- } ;
252
- let layer = kb. layer( ) ;
253
-
254
- info!( "Clicked {} layer {:?}" , name, layer) ;
255
- if let Some ( layer) = layer {
256
- let futures = FuturesUnordered :: new( ) ;
257
- for i in kb. selected( ) . iter( ) {
258
- let i = * i;
259
- futures. push( clone!( @strong kb, @strong name => async move {
260
- kb. keymap_set( i, layer, & name) . await ;
261
- } ) ) ;
262
- }
263
- glib:: MainContext :: default ( ) . spawn_local( async { futures. collect:: <( ) >( ) . await } ) ;
264
- }
265
- } ) ) ;
266
- }
267
- }
268
- }
269
-
270
- fn get_button ( & self , scancode_name : & str ) -> Option < & gtk:: Button > {
271
- self . inner ( ) . keys . get ( scancode_name) . map ( |k| & k. gtk )
272
- }
273
-
274
77
pub ( crate ) fn set_keyboard ( & self , keyboard : Option < Keyboard > ) {
275
- if let Some ( old_kb) = & * self . inner ( ) . keyboard . borrow ( ) {
276
- old_kb. set_picker ( None ) ;
277
- }
78
+ self . inner ( ) . group_box . set_keyboard ( keyboard. clone ( ) ) ;
79
+
278
80
if let Some ( kb) = & keyboard {
279
- for group in self . inner ( ) . groups . iter ( ) {
280
- for key in group. iter_keys ( ) {
281
- // Check that scancode is available for the keyboard
282
- let visible = kb. has_scancode ( & key. name ) ;
283
- key. gtk . set_visible ( visible) ;
284
- }
285
- }
286
81
kb. set_picker ( Some ( & self ) ) ;
287
82
}
288
- * self . inner ( ) . keyboard . borrow_mut ( ) = keyboard;
289
83
}
290
84
291
85
pub ( crate ) fn set_selected ( & self , scancode_names : Vec < String > ) {
292
- let mut selected = self . inner ( ) . selected . borrow_mut ( ) ;
293
-
294
- for i in selected. iter ( ) {
295
- if let Some ( button) = self . get_button ( i) {
296
- button. get_style_context ( ) . remove_class ( "selected" ) ;
297
- }
298
- }
299
-
300
- * selected = scancode_names;
301
-
302
- for i in selected. iter ( ) {
303
- if let Some ( button) = self . get_button ( i) {
304
- button. get_style_context ( ) . add_class ( "selected" ) ;
305
- }
306
- }
307
- }
308
-
309
- fn rows_for_width ( & self , container_width : i32 ) -> Vec < & [ PickerGroup ] > {
310
- let mut rows = Vec :: new ( ) ;
311
- let groups = & * self . inner ( ) . groups ;
312
-
313
- let mut row_start = 0 ;
314
- let mut row_width = 0 ;
315
- for ( i, group) in groups. iter ( ) . enumerate ( ) {
316
- let width = group. vbox . get_preferred_width ( ) . 1 ;
317
-
318
- row_width += width;
319
- if i != 0 {
320
- row_width += HSPACING ;
321
- }
322
- if i - row_start >= DEFAULT_COLS || row_width > container_width {
323
- rows. push ( & groups[ row_start..i] ) ;
324
- row_start = i;
325
- row_width = width;
326
- }
327
- }
328
-
329
- if !groups[ row_start..] . is_empty ( ) {
330
- rows. push ( & groups[ row_start..] ) ;
331
- }
332
-
333
- rows
86
+ self . inner ( ) . group_box . set_selected ( scancode_names) ;
334
87
}
335
88
}
336
89
0 commit comments