@@ -11,6 +11,8 @@ use std::os::unix::io::AsRawFd;
11
11
use std:: path:: Path ;
12
12
use std:: rc:: Rc ;
13
13
14
+ use paste:: paste;
15
+
14
16
use crate :: driver:: DRIVER_PATH ;
15
17
use crate :: utils:: OrErr ;
16
18
use crate :: { Attribute , Ev3Result } ;
@@ -201,27 +203,41 @@ struct ButtonMapEntry {
201
203
pub key_code : u32 ,
202
204
}
203
205
206
+ type ButtonHandler = Box < dyn Fn ( bool ) > ;
207
+
204
208
/// This implementation depends on the availability of the EVIOCGKEY ioctl
205
209
/// to be able to read the button state buffer. See Linux kernel source
206
210
/// in /include/uapi/linux/input.h for details.
207
- #[ derive( Debug ) ]
208
211
struct ButtonFileHandler {
209
212
file_map : HashMap < String , FileMapEntry > ,
210
213
button_map : HashMap < String , ButtonMapEntry > ,
214
+ button_handlers : HashMap < String , ButtonHandler > ,
211
215
pressed_buttons : HashSet < String > ,
212
216
}
213
217
218
+ impl std:: fmt:: Debug for ButtonFileHandler {
219
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
220
+ f. debug_struct ( "ButtonFileHandler" )
221
+ . field ( "file_map" , & self . file_map )
222
+ . field ( "button_map" , & self . button_map )
223
+ . field ( "button_handlers" , & self . button_map . keys ( ) )
224
+ . field ( "pressed_buttons" , & self . pressed_buttons )
225
+ . finish ( )
226
+ }
227
+ }
228
+
214
229
impl ButtonFileHandler {
215
230
/// Create a new instance.
216
231
fn new ( ) -> Self {
217
232
ButtonFileHandler {
218
233
file_map : HashMap :: new ( ) ,
219
234
button_map : HashMap :: new ( ) ,
235
+ button_handlers : HashMap :: new ( ) ,
220
236
pressed_buttons : HashSet :: new ( ) ,
221
237
}
222
238
}
223
239
224
- /// Add a button the the file handler.
240
+ /// Add a button to the file handler.
225
241
fn add_button ( & mut self , name : & str , file_name : & str , key_code : u32 ) -> Ev3Result < ( ) > {
226
242
if !self . file_map . contains_key ( file_name) {
227
243
let file = File :: open ( file_name) ?;
@@ -242,6 +258,16 @@ impl ButtonFileHandler {
242
258
Ok ( ( ) )
243
259
}
244
260
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 {
264
+ self . button_handlers . insert ( name. to_owned ( ) , listener) ;
265
+ } else {
266
+ self . button_handlers . remove ( name) ;
267
+ }
268
+ }
269
+
270
+ /// Gets a copy of the currently pressed buttons.
245
271
fn get_pressed_buttons ( & self ) -> HashSet < String > {
246
272
self . pressed_buttons . clone ( )
247
273
}
@@ -264,6 +290,7 @@ impl ButtonFileHandler {
264
290
}
265
291
}
266
292
293
+ let old_pressed_buttons = self . pressed_buttons . clone ( ) ;
267
294
self . pressed_buttons . clear ( ) ;
268
295
269
296
for (
@@ -280,6 +307,13 @@ impl ButtonFileHandler {
280
307
self . pressed_buttons . insert ( btn_name. to_owned ( ) ) ;
281
308
}
282
309
}
310
+
311
+ let difference = old_pressed_buttons. symmetric_difference ( & self . pressed_buttons ) ;
312
+ for button in difference {
313
+ if self . button_handlers . contains_key ( button) {
314
+ self . button_handlers [ button] ( self . get_button_state ( button) ) ;
315
+ }
316
+ }
283
317
}
284
318
}
285
319
@@ -297,6 +331,10 @@ impl ButtonFileHandler {
297
331
/// # fn main() -> ev3dev_lang_rust::Ev3Result<()> {
298
332
/// let button = Button::new()?;
299
333
///
334
+ /// button.set_down_handler(|is_pressed| {
335
+ /// println("Is 'down' pressed: {is_pressed}");
336
+ /// });
337
+ ///
300
338
/// loop {
301
339
/// button.process();
302
340
///
@@ -335,42 +373,57 @@ impl Button {
335
373
336
374
/// Check for currently pressed buttons. If the new state differs from the
337
375
/// old state, call the appropriate button event handlers.
376
+ /// ```no_run
377
+ /// use ev3dev_lang_rust::Button;
378
+ /// use std::thread;
379
+ /// use std::time::Duration;
380
+ ///
381
+ /// # fn main() -> ev3dev_lang_rust::Ev3Result<()> {
382
+ /// let button = Button::new()?;
383
+ ///
384
+ /// button.set_down_handler(|is_pressed| {
385
+ /// println("Is 'down' pressed: {is_pressed}");
386
+ /// });
387
+ ///
388
+ /// loop {
389
+ /// button.process();
390
+ ///
391
+ /// println!("Is 'up' pressed: {}", button.is_up());
392
+ /// println!("Pressed buttons: {:?}", button.get_pressed_buttons());
393
+ ///
394
+ /// thread::sleep(Duration::from_millis(100));
395
+ /// }
396
+ /// # }
397
+ /// ```
338
398
pub fn process ( & self ) {
339
399
self . button_handler . borrow_mut ( ) . process ( )
340
400
}
341
401
342
402
/// Get all pressed buttons by name.
403
+ ///
404
+ /// ```no_run
405
+ /// use ev3dev_lang_rust::Button;
406
+ /// use std::thread;
407
+ /// use std::time::Duration;
408
+ ///
409
+ /// # fn main() -> ev3dev_lang_rust::Ev3Result<()> {
410
+ /// let button = Button::new()?;
411
+ ///
412
+ /// loop {
413
+ /// button.process();
414
+ /// println!("Pressed buttons: {:?}", button.get_pressed_buttons());
415
+ /// thread::sleep(Duration::from_millis(100));
416
+ /// }
417
+ /// # }
418
+ /// ```
343
419
pub fn get_pressed_buttons ( & self ) -> HashSet < String > {
344
420
self . button_handler . borrow ( ) . get_pressed_buttons ( )
345
421
}
346
422
347
- /// Check if 'up' button is pressed.
348
- pub fn is_up ( & self ) -> bool {
349
- self . button_handler . borrow ( ) . get_button_state ( "up" )
350
- }
351
-
352
- /// Check if 'down' button is pressed.
353
- pub fn is_down ( & self ) -> bool {
354
- self . button_handler . borrow ( ) . get_button_state ( "down" )
355
- }
356
-
357
- /// Check if 'left' button is pressed.
358
- pub fn is_left ( & self ) -> bool {
359
- self . button_handler . borrow ( ) . get_button_state ( "left" )
360
- }
361
-
362
- /// Check if 'right' button is pressed.
363
- pub fn is_right ( & self ) -> bool {
364
- self . button_handler . borrow ( ) . get_button_state ( "right" )
365
- }
366
-
367
- /// Check if 'enter' button is pressed.
368
- pub fn is_enter ( & self ) -> bool {
369
- self . button_handler . borrow ( ) . get_button_state ( "enter" )
370
- }
371
-
372
- /// Check if 'backspace' button is pressed.
373
- pub fn is_backspace ( & self ) -> bool {
374
- self . button_handler . borrow ( ) . get_button_state ( "backspace" )
375
- }
423
+ ev3_button_functions ! ( up) ;
424
+ ev3_button_functions ! ( down) ;
425
+ ev3_button_functions ! ( left) ;
426
+ ev3_button_functions ! ( right) ;
427
+ ev3_button_functions ! ( enter) ;
428
+ ev3_button_functions ! ( backspace) ;
376
429
}
0 commit comments