@@ -203,6 +203,7 @@ struct ButtonMapEntry {
203
203
pub key_code : u32 ,
204
204
}
205
205
206
+ type ButtonChangeHandler = Box < dyn Fn ( HashSet < String > ) > ;
206
207
type ButtonHandler = Box < dyn Fn ( bool ) > ;
207
208
208
209
/// This implementation depends on the availability of the EVIOCGKEY ioctl
@@ -211,6 +212,7 @@ type ButtonHandler = Box<dyn Fn(bool)>;
211
212
struct ButtonFileHandler {
212
213
file_map : HashMap < String , FileMapEntry > ,
213
214
button_map : HashMap < String , ButtonMapEntry > ,
215
+ button_change_handler : Option < ButtonChangeHandler > ,
214
216
button_handlers : HashMap < String , ButtonHandler > ,
215
217
pressed_buttons : HashSet < String > ,
216
218
}
@@ -220,6 +222,10 @@ impl std::fmt::Debug for ButtonFileHandler {
220
222
f. debug_struct ( "ButtonFileHandler" )
221
223
. field ( "file_map" , & self . file_map )
222
224
. field ( "button_map" , & self . button_map )
225
+ . field (
226
+ "button_change_handler" ,
227
+ & self . button_change_handler . is_some ( ) ,
228
+ )
223
229
. field ( "button_handlers" , & self . button_map . keys ( ) )
224
230
. field ( "pressed_buttons" , & self . pressed_buttons )
225
231
. finish ( )
@@ -232,6 +238,7 @@ impl ButtonFileHandler {
232
238
ButtonFileHandler {
233
239
file_map : HashMap :: new ( ) ,
234
240
button_map : HashMap :: new ( ) ,
241
+ button_change_handler : None ,
235
242
button_handlers : HashMap :: new ( ) ,
236
243
pressed_buttons : HashSet :: new ( ) ,
237
244
}
@@ -258,15 +265,20 @@ impl ButtonFileHandler {
258
265
Ok ( ( ) )
259
266
}
260
267
261
- /// Sets an event listener for the given button.
262
- fn set_button_listener ( & mut self , name : & str , listener : Option < ButtonHandler > ) {
263
- if let Some ( listener) = listener {
268
+ /// Sets an event handler for the given button.
269
+ fn set_button_handler ( & mut self , name : & str , handler : Option < ButtonHandler > ) {
270
+ if let Some ( listener) = handler {
264
271
self . button_handlers . insert ( name. to_owned ( ) , listener) ;
265
272
} else {
266
273
self . button_handlers . remove ( name) ;
267
274
}
268
275
}
269
276
277
+ /// Sets an event handler for any button state change.
278
+ fn set_button_change_handler ( & mut self , handler : Option < ButtonChangeHandler > ) {
279
+ self . button_change_handler = handler;
280
+ }
281
+
270
282
/// Gets a copy of the currently pressed buttons.
271
283
fn get_pressed_buttons ( & self ) -> HashSet < String > {
272
284
self . pressed_buttons . clone ( )
@@ -309,11 +321,20 @@ impl ButtonFileHandler {
309
321
}
310
322
311
323
let difference = old_pressed_buttons. symmetric_difference ( & self . pressed_buttons ) ;
324
+
325
+ let mut difference_count = 0 ;
312
326
for button in difference {
327
+ difference_count += 1 ;
313
328
if self . button_handlers . contains_key ( button) {
314
329
self . button_handlers [ button] ( self . get_button_state ( button) ) ;
315
330
}
316
331
}
332
+
333
+ if difference_count > 0 {
334
+ if let Some ( ref handler) = self . button_change_handler {
335
+ handler ( self . get_pressed_buttons ( ) ) ;
336
+ }
337
+ }
317
338
}
318
339
}
319
340
@@ -329,10 +350,10 @@ impl ButtonFileHandler {
329
350
/// use std::time::Duration;
330
351
///
331
352
/// # fn main() -> ev3dev_lang_rust::Ev3Result<()> {
332
- /// let button = Button::new()?;
353
+ /// let mut button = Button::new()?;
333
354
///
334
355
/// button.set_down_handler(|is_pressed| {
335
- /// println("Is 'down' pressed: {is_pressed}");
356
+ /// println! ("Is 'down' pressed: {is_pressed}");
336
357
/// });
337
358
///
338
359
/// loop {
@@ -379,10 +400,10 @@ impl Button {
379
400
/// use std::time::Duration;
380
401
///
381
402
/// # fn main() -> ev3dev_lang_rust::Ev3Result<()> {
382
- /// let button = Button::new()?;
403
+ /// let mut button = Button::new()?;
383
404
///
384
405
/// button.set_down_handler(|is_pressed| {
385
- /// println("Is 'down' pressed: {is_pressed}");
406
+ /// println! ("Is 'down' pressed: {is_pressed}");
386
407
/// });
387
408
///
388
409
/// loop {
@@ -420,6 +441,40 @@ impl Button {
420
441
self . button_handler . borrow ( ) . get_pressed_buttons ( )
421
442
}
422
443
444
+ /// Set an event handler, that is called by `process()` if any button state changes.
445
+ /// Has a set of all pressed buttons as parameter.
446
+ ///
447
+ /// ```no_run
448
+ /// use ev3dev_lang_rust::Button;
449
+ /// use std::thread;
450
+ /// use std::time::Duration;
451
+ ///
452
+ /// # fn main() -> ev3dev_lang_rust::Ev3Result<()> {
453
+ /// let mut button = Button::new()?;
454
+ ///
455
+ /// button.set_change_handler(|pressed_buttons| {
456
+ /// println!("pressed buttons: {:?}", pressed_buttons);
457
+ /// });
458
+ ///
459
+ /// loop {
460
+ /// button.process();
461
+ /// thread::sleep(Duration::from_millis(100));
462
+ /// }
463
+ /// # }
464
+ /// ```
465
+ pub fn set_change_handler ( & mut self , handler : impl Fn ( HashSet < String > ) + ' static ) {
466
+ self . button_handler
467
+ . borrow_mut ( )
468
+ . set_button_change_handler ( Some ( Box :: new ( handler) ) )
469
+ }
470
+
471
+ /// Removes the change event handler.
472
+ pub fn remove_change_handler ( & mut self ) {
473
+ self . button_handler
474
+ . borrow_mut ( )
475
+ . set_button_change_handler ( None )
476
+ }
477
+
423
478
ev3_button_functions ! ( up) ;
424
479
ev3_button_functions ! ( down) ;
425
480
ev3_button_functions ! ( left) ;
0 commit comments