@@ -73,6 +73,11 @@ class FlipInput(Widget, Control):
7373 direction, set `False` for arrows in the vertical direction (default = `True`)
7474 :param float animation_time: duration for the animation during flipping between
7575 values, in seconds (default is 0.4 seconds), set to 0.0 or `None` for no animation.
76+ :param float cool_down: minimum duration between activations of the widget with a
77+ continuous pressing, this can be used to reduce the chance of accidental multiple
78+ activations, in seconds (default is 0.0 seconds, no delay). Set to -1.0 to require
79+ the button be released and pressed again for activation (Note: This requires calling
80+ the ``released`` function prior to the next call to ``selected``.)
7681
7782 """
7883
@@ -94,6 +99,7 @@ def __init__(
9499 alt_touch_padding = 0 , # touch padding on the non-arrow sides of the Widget
95100 horizontal = True ,
96101 animation_time = None ,
102+ cool_down = 0.0 ,
97103 ** kwargs ,
98104 ):
99105
@@ -124,6 +130,9 @@ def __init__(
124130 self ._display = display
125131
126132 self ._animation_time = animation_time
133+ self ._cool_down = cool_down
134+ self ._last_pressed = time .monotonic ()
135+ self ._pressed = False # state variable
127136
128137 # Find the maximum bounding box of the text and determine the
129138 # baseline (x,y) start point (top, left)
@@ -412,6 +421,15 @@ def _update_value(self, new_value, animate=True):
412421 self ._display .auto_refresh = True
413422 self ._update_position () # call Widget superclass function to reposition
414423
424+ def _ok_to_change (self ): # checks state variable and timers to determine
425+ # if an update is allowed
426+ if self ._cool_down < 0 : # if cool_down is negative, require ``released``
427+ # to be called before next change
428+ return not self ._pressed
429+ if (time .monotonic () - self ._last_pressed ) < self ._cool_down :
430+ return False # cool_down time has not transpired
431+ return True
432+
415433 def contains (self , touch_point ): # overrides, then calls Control.contains(x,y)
416434 """Returns True if the touch_point is within the widget's touch_boundary."""
417435
@@ -429,34 +447,50 @@ def contains(self, touch_point): # overrides, then calls Control.contains(x,y)
429447 return super ().contains ((touch_x , touch_y , 0 ))
430448
431449 def selected (self , touch_point ):
432- """Response function when Control is selected. Increases value when upper half is pressed
433- and decreases value when lower half is pressed."""
450+ """Response function when the Control is selected. Increases value when upper half
451+ is pressed and decreases value when lower half is pressed."""
434452
435453 # Adjust for local position of the widget using self.x and self.y
436454
437- t_b = self .touch_boundary
455+ if self ._ok_to_change ():
456+ t_b = self .touch_boundary
438457
439- if self ._horizontal :
440- if (
441- t_b [0 ] <= (touch_point [0 ] - self .x ) < (t_b [0 ] + t_b [2 ] // 2 )
442- ): # in left half of touch_boundary
443- self .value = self .value - 1
458+ if self ._horizontal :
459+ if (
460+ t_b [0 ] <= (touch_point [0 ] - self .x ) < (t_b [0 ] + t_b [2 ] // 2 )
461+ ): # in left half of touch_boundary
462+ self .value = self .value - 1
444463
445- elif (
446- (t_b [0 ] + t_b [2 ] // 2 ) <= (touch_point [0 ] - self .x ) <= (t_b [0 ] + t_b [2 ])
447- ): # in right half of touch_boundary
448- self .value = self .value + 1
464+ elif (
465+ (t_b [0 ] + t_b [2 ] // 2 )
466+ <= (touch_point [0 ] - self .x )
467+ <= (t_b [0 ] + t_b [2 ])
468+ ): # in right half of touch_boundary
469+ self .value = self .value + 1
449470
450- else :
451- if (
452- t_b [1 ] <= (touch_point [1 ] - self .y ) < (t_b [1 ] + t_b [3 ] // 2 )
453- ): # in upper half of touch_boundary
454- self .value = self .value + 1
455-
456- elif (
457- (t_b [1 ] + t_b [3 ] // 2 ) <= (touch_point [1 ] - self .y ) <= (t_b [1 ] + t_b [3 ])
458- ): # in lower half of touch_boundary
459- self .value = self .value - 1
471+ else :
472+ if (
473+ t_b [1 ] <= (touch_point [1 ] - self .y ) < (t_b [1 ] + t_b [3 ] // 2 )
474+ ): # in upper half of touch_boundary
475+ self .value = self .value + 1
476+
477+ elif (
478+ (t_b [1 ] + t_b [3 ] // 2 )
479+ <= (touch_point [1 ] - self .y )
480+ <= (t_b [1 ] + t_b [3 ])
481+ ): # in lower half of touch_boundary
482+ self .value = self .value - 1
483+
484+ self ._pressed = True # update the state variable
485+ self ._last_pressed = (
486+ time .monotonic ()
487+ ) # value changed, so update cool_down timer
488+
489+ def released (self ):
490+ """Response function when the Control is released. Resets the state variables
491+ for handling situation when ``cool_down`` is < 0 that requires `released()` before
492+ reacting another another `selected()`."""
493+ self ._pressed = False
460494
461495 @property
462496 def value (self ):
0 commit comments