1************************ 2Mouse and keyboard input 3************************ 4 5Input handling in glooey is built on the pyglet event framework. You can read 6all about this framework `here`__, but the basic idea is that events are 7triggered when input occurs, and your code can react to these events however it 8likes. Glooey works the same way, but events are triggered by every widget 9that's affected by the input in question. Another way to say this is that 10every widget is an `EventDispatcher`. So while pyglet lets you react when the 11mouse is clicked, glooey lets you react when the mouse is clicked on a 12particular widget. 13 14__ https://pyglet.readthedocs.io/en/latest/programming_guide/events.html 15 16The following sections will describe the user-input-related events that widgets 17can trigger, but the first thing to know is how to react to an event. You do 18this by attaching a handler (which is a function with the same name and 19signature as the event) to a widget. There are two prominent ways to do this. 20The first is to use the `~Widget.event()` decorator:: 21 22 @widget.event 23 def on_click(widget): 24 print(f"{widget} was clicked!") 25 26The second is to use the `~Widget.push_handlers()` method:: 27 28 def on_click(widget): 29 print(f"{widget} was clicked!") 30 widget.push_handlers(on_click) 31 32Handlers that have been pushed can also be popped, which is sometimes useful:: 33 34 widget.pop_handlers() 35 36Mouse input 37=========== 38Every widget can dispatch the following events in response to mouse input: 39 40``on_click(widget)`` 41 Triggered when the user clicks on a widget. This is pretty similar to 42 ``on_mouse_release()``, but there are a few differences. First, a widget 43 cannot be clicked if it's not "enabled", i.e. via `~Widget.enable()` and 44 `~Widget.disable()`. (You can think of a disabled widget as being 45 "greyed-out", although it's up to the widget itself to actually change it's 46 appearance when it's been disabled.) Second, a widget cannot be clicked if 47 the click didn't begin within the widget. In other words, if you were to 48 drag the mouse over a widget and then release it, that would not be a click. 49 50``on_double_click(widget)`` 51 Triggered when the user clicks the same widget twice within 500 ms. The 52 second click triggers both ``on_click()`` and ``on_double_click()`` events. 53 54``on_rollover(widget, current_state, previous_state)`` 55 Triggered whenever a widget's rollover state changes. There are three 56 possible states: 'base' (the mouse is not interacting with the widget), 57 'over' (the mouse is currently hovering over the widget), and 'down' (the 58 mouse is in the middle of clicking on the widget). 59 60``on_mouse_press(x, y, button, modifiers)`` 61 Triggered when the mouse is pressed while over a widget. 62 63``on_mouse_release(x, y, button, modifiers)`` 64 Triggered when the mouse is released while over a widget. 65 66``on_mouse_hold(dt)`` 67 Triggered 60 times a second whenever the mouse is being pressed on a widget 68 (if the press began on the widget). The ``dt`` argument gives the amount of 69 time that passed between triggers. 70 71``on_mouse_motion(x, y, dx, dy)`` 72 Triggered when the mouse moves around inside a widget. 73 74``on_mouse_enter(x, y)`` 75 Triggered when the mouse moves into a widget. Note that pyglet only uses 76 this event to indicate when the mouse enters the window, so in this sense 77 glooey treats each widget like its own window. 78 79``on_mouse_leave(x, y)`` 80 Triggered when the mouse moves out of a widget. Note that pyglet only uses 81 this event to indicate when the mouse leaves the window, so in this sense 82 glooey treats each widget like its own window. 83 84``on_mouse_drag(x, y, dx, dy, buttons, modifiers)`` 85 Triggered when the mouse is dragged around inside a widget. 86 87``on_mouse_drag_enter(x, y)`` 88 Triggered when the mouse is dragged into a widget. Note that pyglet only 89 uses this event to indicate when the mouse leaves the window, so in this 90 sense glooey treats each widget like its own window. 91 92``on_mouse_drag_leave(x, y)`` 93 Triggered when the mouse is dragged out of a widget. Note that pyglet only 94 uses this event to indicate when the mouse leaves the window, so in this 95 sense glooey treats each widget like its own window. 96 97``on_mouse_scroll(x, y, scroll_x, scroll_y)`` 98 Triggered when the scroll wheel is turned while the mouse is over a widget. 99 100In addition to the above events that can be triggered by any widget, the 101following events can be triggered only by certain widgets: 102 103``on_toggle(widget)`` 104 Triggered by Checkbox and RadioButton when the state of the button is 105 changed. This can happen programmatically, but usually happens because the 106 user clicked on it. 107 108``on_mouse_pan(direction, dt)`` 109 Triggered by PanningGui when the mouse is at the edge of the screen. The 110 Viewport widget can listen for these events and use them to pan around a 111 larger widget, so together these widgets are useful for making fullscreen 112 games. 113 114Keyboard input 115============== 116This section should really be empty; glooey doesn't affect how keyboard events 117are handled at all. If you want to react to keyboard input (e.g. to make a 118hotkey), just attach a ``on_key_press`` and/or ``on_key_release`` handlers to 119the window just like you would in any pyglet program. Certain widgets (like 120`Form`) do interact with the keyboard, but they do so by directly interacting 121with the window themselves, and they don't re-dispatch keyboard related events. 122 123