File: uisystem.rst

package info (click to toggle)
pysdl2 0.9.17%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,328 kB
  • sloc: python: 24,685; makefile: 36; sh: 8
file content (289 lines) | stat: -rw-r--r-- 10,995 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
.. currentmodule:: sdl2.ext

Designing component-oriented user interfaces
============================================

.. warning::
   This module is deprecated, and may be removed in a future release of PySDL2.

User interface elements within :mod:`sdl2.ext` are simple
:class:`Sprite` objects, which are enhanced by certain input hooks; as such,
they are not classes on their own, but implemented as mixins. The user input
itself is handled by an :class:`UIProcessor` object, which takes care of
delegating input events, such as mouse movements, clicks and keyboard input,
to the correct UI element.

Depending on the event type (e.g. pressing a mouse button), the UIProcessor
will execute its matching method (e.g. ``mousedown()``) with only those UI
elements, which support the event type.

.. image:: images/uiprocessing.png

.. _ui-elem-types:


UI element types
----------------
Every :class:`sdl2.ext` UI element is a simple :class:`Sprite` object, to
which additional attributes and methods are bound.

Every UI element features the following attributes

``element.uitype``

   The ``uitype`` attribute can have one of the following values,
   identifying the UI element:

   * ``BUTTON`` - a UI element, which can react on mouse input
   * ``CHECKBUTTON`` - as ``BUTTON``, but it retains its state on clicks
   * ``TEXTENTRY`` - a UI element that reacts on keyboard input

``element.events``

   A dictionary containing the SDL2 event mappings. Each supported SDL2 event
   (e.g. ``SDL_MOUSEMOTION``) is associated with a bound
   :class:`EventHandler` acting as callback for user code
   (e.g. ``mousemotion()``).

Depending on the exact type of the element, it will feature additional methods
and attributes explained below.

Button elements
^^^^^^^^^^^^^^^
``BUTTON`` UI elements feature a ``state`` attribute, which can be one of the
following values.

======== =====================================================================
state    Description
======== =====================================================================
RELEASED Indicates that the UI element is not pressed.
HOVERED  Indicates that the mouse cursor is currently hovering the UI element.
PRESSED  Indicates that a mouse button is pressed on the UI element.
======== =====================================================================

``BUTTON`` UI elements react with the following event handlers on events:

``button.motion(event : sdl2.events.SDL_Event)``

  An :class:`EventHandler` that is invoked, if the mouse moves around while
  being over the ``BUTTON``.

``button.pressed(event : sdl2.events.SDL_Event)``

  An :class:`EventHandler` that is invoked, if a mouse button is pressed on
  the ``BUTTON``.

``button.released(event : sdl2.events.SDL_Event)``

  An :class:`EventHandler` that is invoked, if a mouse button is released on
  the ``BUTTON``.

``button.click(event : sdl2.events.SDL_Event)``

  An :class:`EventHandler` that is invoked, if a mouse button is pressed and
  released on the ``BUTTON``.

Besides the ``BUTTON`` a special ``CHECKBUTTON`` UI element type exists,
which enhances the ``BUTTON`` bindings by an additional ``checked`` attribute.
The ``checked`` attribute switches its status (``False`` to ``True`` and
``True``  to ``False``) every time the UI element is clicked.

Text input elements
^^^^^^^^^^^^^^^^^^^
``TEXTENTRY`` elements react on text input, once they are activated. Text being
input, once a ``TEXTENTRY`` has been activated, is stored in its ``text``
attribute.

The ``TEXTENTRY`` reacts with the following event handlers on events:

``textentry.motion(event : sdl2.events.SDL_Event)``

  An :class:`EventHandler` that is invoked, if the mouse moves around while
  being over the ``TEXTENTRY``.

``textentry.pressed(event : sdl2.events.SDL_Event)``

  An :class:`EventHandler` that is invoked, if a mouse button is pressed on
  the ``TEXTENTRY``.

``textentry.released(event : sdl2.events.SDL_Event)``

  An :class:`EventHandler` that is invoked, if a mouse button is released on
  the ``TEXTENTRY``.

``textentry.keydown(event : sdl2.events.SDL_Event)``

  An :class:`EventHandler` that is invoked on pressing a key.

``textentry.keyup(event : sdl2.events.SDL_Event)``

  An :class:`EventHandler` that is invoked on releasing a key.

``textentry.input(event : sdl2.events.SDL_Event)``

  An :class:`EventHandler` that is invoked on text input events.
  Text input events are automatically created, once the :class:`UIProcessor`
  activates a ``TEXTENTRY`` UI element.

``textentry.editing(event : sdl2.events.SDL_Event)``

  An :class:`EventHandler` that is invoked on text editing events. Text
  editing events are automatically created, once the :class:`UIProcessor`
  activates a ``TEXTENTRY`` UI element.

  Text editing events are however only raised, if an IME system is involved,
  which combines glyphs and symbols to characters or word fragments.

API
---

.. class:: UIFactory(spritefactory : SpriteFactory[, **kwargs])

   A factory class for creating UI elements. The :class:`UIFactory`
   allows you to create UI elements based on the
   :class:`Sprite` class. To do this, it requires a :class:`SpriteFactory`,
   which will create the sprites, to which the :class:`UIFactory` then binds
   the additional methods and attributes.

   The additional *kwargs* are used as default arguments for creating
   **sprites** within the factory methods.

   .. attribute:: default_args

      A dictionary containing the default arguments to be passed to the
      sprite creation methods of the bound :class:`SpriteFactory`.

   .. attribute:: spritefactory

      The :class:`SpriteFactory` being used for creating new :class:`Sprite`
      objects.

   .. method:: create_button(**kwargs) -> Sprite

      Creates a new button UI element.

      *kwargs* are the arguments to be passed for the sprite
      construction and can vary depending on the sprite type.
      See :meth:`SpriteFactory.create_sprite()` for further details.

   .. method:: create_check_button(**kwargs) -> Sprite

      Creates a new checkbutton UI element.

      *kwargs* are the arguments to be passed for the sprite
      construction and can vary depending on the sprite type.
      See :meth:`SpriteFactory.create_sprite()` for further details.

   .. method:: create_text_entry(**kwargs) -> Sprite

      Creates a new textentry UI element.

      *kwargs* are the arguments to be passed for the sprite
      construction and can vary depending on the sprite type.
      See :meth:`SpriteFactory.create_sprite()` for further details.

   .. method:: from_color(color : object , size) -> Sprite

      Creates a UI element with a specific color.

      *uitype* must be one of the supported :ref:`ui-elem-types` classifying
      the type of UI element to be created.

   .. method:: from_image(uitype : int, fname : str) -> Sprite

      Creates a UI element from an image file. The image must be
      loadable via :func:`load_image()`.

      *uitype* must be one of the supported :ref:`ui-elem-types` classifying
      the type of UI element to be created.

   .. method:: from_object(uitype : int, obj: object) -> Sprite

      Creates a UI element from an object. The object will be passed through
      :func:`sdl2.rwops_from_object()` in order to try to load image data from
      it.

      *uitype* must be one of the supported :ref:`ui-elem-types` classifying
      the type of UI element to be created.

   .. method:: from_surface(uitype : int,  surface : SDL_Surface[, free=False]) -> Sprite

      Creates a UI element from the passed
      :class:`sdl2.surface.SDL_Surface`. If *free* is set to
      ``True``, the passed *surface* will be freed automatically.

      *uitype* must be one of the supported :ref:`ui-elem-types` classifying
      the type of UI element to be created.

.. class:: UIProcessor()

   A processing system for user interface elements and events.

   .. attribute:: handlers

      A dict containing the mapping of SDL2 events to the available
      :class:`EventHandler` bindings of the :class:`UIProcessor`.

   .. method:: activate(component : object) -> None

      Activates a UI control to receive text input.

   .. method:: deactivate(component : object) -> None

      Deactivate the currently active UI control.

   .. method:: passevent(component : object, event : SDL_Event) -> None

      Passes the *event* to a *component* without any additional checks or
      restrictions.

   .. method:: mousemotion(component : object, event : SDL_Event) -> None

      Checks, if the event's motion position is on the *component* and
      executes the component's event handlers on demand. If the motion event
      position is not within the area of the *component*, nothing will be
      done. In case the component is a ``BUTTON``, its :attr:`state` will be
      adjusted to reflect, if it is currently hovered or not.

   .. method:: mousedown(component : object, event : SDL_Event) -> None

      Checks, if the event's button press position is on the *component* and
      executes the component's event handlers on demand. If the button press
      position is not within the area of the component, nothing will be done.

      In case the component is a ``BUTTON``, its :attr:`state`
      will be adjusted to reflect, if it is currently pressed or not.

      In case the component is a ``TEXTENTRY`` and the pressed button is
      the primary mouse button, the component will be marked as the next
      control to activate for text input.

   .. method:: mouseup(self, component, event) -> None

      Checks, if the event's button release position is on the *component* and
      executes the component's event handlers on demand. If the button release
      position is not within the area of the component, nothing will be done.

      In case the component is a ``BUTTON``, its :attr:`state`
      will be adjusted to reflect, whether it is hovered or not.

      If the button release followed a button press on the same component and
      if the button is the primary button, the ``click()`` event handler is
      invoked, if the component is a ``BUTTON``.

   .. method:: dispatch(obj : object, event : SDL_Event) -> None

      Passes an event to the given object. If *obj* is a
      :class:`World` object, UI relevant components will receive
      the event, if they support the event type. If *obj* is a single object,
      ``obj.events`` **must** be a dict consisting of SDL event type
      identifiers and :class:`EventHandler` instances bound
      to the object. If *obj* is a iterable, such as a list or set, every
      item within *obj* **must** feature an ``events`` attribute as
      described above.

   .. method:: process(world : World, components : iterable) -> None

      The :class:`UIProcessor` class does not implement the `process()`
      method by default. Instead it uses :meth:`dispatch()` to send events
      around to components. :meth:`process()` does nothing.