# User interface elements

User interface elements within `sdl2.ext` are simple `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 `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.

## UI element types

Every `sdl2.ext` UI element is a simple `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 `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 `EventHandler` that is invoked, if the mouse moves around while being over the `BUTTON`.

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

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

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

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

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

> An `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 `EventHandler` that is invoked, if the mouse moves around while being over the `TEXTENTRY`.

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

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

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

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

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

> An `EventHandler` that is invoked on pressing a key.

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

> An `EventHandler` that is invoked on releasing a key.

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

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

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

> An `EventHandler` that is invoked on text editing events. Text editing events are automatically created, once the `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 `sdl2.ext.``UIFactory`(spritefactory : SpriteFactory[, **kwargs])

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

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

  `default_args`

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

  `spritefactory`

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

  `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 `SpriteFactory.create_sprite()` for further details.

  `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 `SpriteFactory.create_sprite()` for further details.

  `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 `SpriteFactory.create_sprite()` for further details.

  `from_color`(color : object, size) → Sprite

    Creates a UI element with a specific color.

    uitype must be one of the supported UI element types classifying the type of UI element to be created.

  `from_image`(uitype : int, fname : str) → Sprite

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

    uitype must be one of the supported UI element types classifying the type of UI element to be created.

  `from_object`(uitype : int, obj: object) → Sprite

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

    uitype must be one of the supported UI element types classifying the type of UI element to be created.

  `from_surface`(uitype : int, surface : SDL_Surface[, free=False]) → Sprite

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

    uitype must be one of the supported UI element types classifying the type of UI element to be created.

class `sdl2.ext.``UIProcessor`

  A processing system for user interface elements and events.

  `handlers`

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

  `activate`(component : object) → None

    Activates a UI control to receive text input.

  `deactivate`(component : object) → None

    Deactivate the currently active UI control.

  `passevent`(component : object, event : SDL_Event) → None

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

  `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 `state` will be adjusted to reflect, if it is currently hovered or not.

  `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 `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.

  `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 `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`.

  `dispatch`(obj : object, event : SDL_Event) → None

    Passes an event to the given object. If obj is a `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 `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.

  `process`(world : World, components : iterable) → None

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