58 lines
1.7 KiB
Python
58 lines
1.7 KiB
Python
|
__all__ = ('event', )
|
||
|
|
||
|
import typing as T
|
||
|
import types
|
||
|
from functools import partial
|
||
|
from asyncgui import _current_task, _sleep_forever
|
||
|
|
||
|
|
||
|
@types.coroutine
|
||
|
def event(event_dispatcher, event_name, *, filter=None, stop_dispatching=False) -> T.Awaitable[tuple]:
|
||
|
'''
|
||
|
Returns an awaitable that can be used to wait for:
|
||
|
|
||
|
* a Kivy event to occur.
|
||
|
* a Kivy property's value to change.
|
||
|
|
||
|
.. code-block::
|
||
|
|
||
|
# Wait for a button to be pressed.
|
||
|
await event(button, 'on_press')
|
||
|
|
||
|
# Wait for an 'on_touch_down' event to occur.
|
||
|
__, touch = await event(widget, 'on_touch_down')
|
||
|
|
||
|
# Wait for 'widget.x' to change.
|
||
|
__, x = await ak.event(widget, 'x')
|
||
|
|
||
|
|
||
|
The ``filter`` parameter:
|
||
|
|
||
|
.. code-block::
|
||
|
|
||
|
# Wait for an 'on_touch_down' event to occur inside a widget.
|
||
|
__, touch = await event(widget, 'on_touch_down', filter=lambda w, t: w.collide_point(*t.opos))
|
||
|
|
||
|
# Wait for 'widget.x' to become greater than 100.
|
||
|
if widget.x <= 100:
|
||
|
await event(widget, 'x', filter=lambda __, x: x > 100)
|
||
|
|
||
|
The ``stop_dispatching`` parameter:
|
||
|
|
||
|
It only works for events not for properties.
|
||
|
See :ref:`kivys-event-system` for details.
|
||
|
'''
|
||
|
task = (yield _current_task)[0][0]
|
||
|
bind_id = event_dispatcher.fbind(event_name, partial(_callback, filter, task, stop_dispatching))
|
||
|
assert bind_id # check if binding succeeded
|
||
|
try:
|
||
|
return (yield _sleep_forever)[0]
|
||
|
finally:
|
||
|
event_dispatcher.unbind_uid(event_name, bind_id)
|
||
|
|
||
|
|
||
|
def _callback(filter, task, stop_dispatching, *args, **kwargs):
|
||
|
if (filter is None) or filter(*args, **kwargs):
|
||
|
task._step(*args)
|
||
|
return stop_dispatching
|