• allegro5.a5_display
  • allegro5.a5_file
  • allegro5.a5_font
  • allegro5.a5_image
  • allegro5.a5_joystick
  • allegro5.a5_main
  • allegro5.a5_misc
  • allegro5.a5_opengl
  • allegro5.a5_shader
  • allegro5.a5_sound
  • allegro5.a5_thread
  • allegro5.a5_triangles
  • animation
  • array
  • atlas
  • buffer
  • color
  • common
  • csg.csg_aabb
  • csg.csg
  • csg.csg_octree
  • csg.csg_shapes
  • csg.csg_test
  • data
  • display
  • exception
  • file
  • font
  • glsl
  • grid
  • hash
  • image
  • image_op
  • index
  • ini
  • isometric
  • joystick
  • keyboard
  • land
  • layer
  • list
  • log
  • main
  • map
  • mem
  • mouse
  • net
  • noise
  • openglutil
  • perlin
  • pixelmask
  • plasma
  • pool
  • protobuf
  • queue
  • random
  • runner
  • shader
  • sound
  • sprite
  • thread
  • tilegrid
  • triangles
  • util2d
  • util3d
  • util
  • view
  • voronoi
  • widget.base
  • widget.board
  • widget.book
  • widget.box
  • widget.button
  • widget.checkbox
  • widget.container
  • widget.edit
  • widget.gul
  • widget.hbox
  • widget.layout
  • widget
  • widget.menu
  • widget.mover
  • widget.panel
  • widget.scrollbar
  • widget.scrolling
  • widget.sizer
  • widget.slider
  • widget.spin
  • widget.text
  • widget.theme
  • widget.vbox
  • widget.widget_list
  • yaml.external
  • yaml.internal
  • yaml
  • yaml.xml

land.widget.base

Simple themeable widgets to use for in-game user interface elements.

This module implements a simple graphical user interface on top of Land.

= Some Features =

  • Simple. This is intended to be used in-game, so no advanced features.
  • A widget is basically a box. It can contain other boxes, to which mouse and keyboard input is dispatched.
  • Themeable, either with custom drawing, or bitmap themes.

= Mouse Focus =

Mouse focus is given to the window under the mouse, if the left button is not being held. Else the focused window retains focus as long as the left mouse button is being held pressed, even if the mouse leaves the window.

= Keyboard Focus =

Keyboard focus is only given to widgets requesting it. A focused window retains keyboard focus, unless focus is transferred to another window.

A widget will normally ask for keyboard focus being transferred to it, when the mouse is clicked over it, or when the TAB key is pressed and it is the next in the widget cycle. This cycle is constructed by walking all widgets in order, starting with the parent, then the children, recursively.

= Layout =

About using the auto layout:

  • Each widget has an outer box, which is how much space it takes up inside its parent.

  • Additionally, it has an inner box, which is the space available to children. The inner box is 6 values: il, it, ir, ib, hgap, vgap. The first 4 are for a border all around the widget, the last 2 are gaps between multiple children.

  • The space between outer and inner box is usually filled with some kind of border by the themeing.

  • The layout allows layers, so child windows can share the same space.

  • By default, container widgets try to fill up as much space as they can, so if you place e.g. a VBox onto the desktop, it fills it up completely when using auto layout. Non-container widgets on the other hand usually try to be as small as possible, e.g. a button will try to fit around the text/image inside it. You can of course change for each widget how it behaves.

= Themeing =

Each widget has a pointer to a theme. On creation, a widget inherits this theme from its parent. So usually is is enough to set a theme for the desktop, then all widgets spawned from it will inherit the theme. And it’s also easy to have per-widget themes, either for a single widget, or for a window or menu. In the latter case, simply set the theme before creating children.

Themes are built from bitmaps. This keeps them very simple, and should be enough in most cases. And of course, if you absolutely don’t want to, you don’t have to use themes. Simply override the draw method of all widgets which you want to draw yourself.

= Polymorphism =

The widgets are organized in a class hierarchy. To use polymorphism, you need to convert pointers to one class to pointers to a base or specialized class. This is done using land_widget_check, which will use the widgets vtable to assert that the conversion is possible and generate a runtime error otherwise.

= Reference counting =

The widgets use reference counting to handle deletion. This is a cheap way out of dealing with stale references/dangling pointers. A GUI without either reference counting or garbage collection is possible, it just needs some more design work. In our case here, following a KISS principle, we do simple naive reference counting, and leave the user to deal with possible problems like circular references.

In the normal case, it works like this: You create a widget, and have to pass along a parent widget to the constructor. Now, the parent will hold a reference to the new widget. There is no reference from the child to the parent, despite the parent field referencing the parent. This is done to avoid complications with cyclic references. If your own widgets contain cyclic references in another way, you should understand how the reference counting works.

The first consequence of the above is, you always should manually reference the top level window, since it has no parent it is referenced by.

The apparent problem is the possible dangling pointer of a child to its parent. But it should be save, since whenever the parent is deleted, it will delete all its children anyway.

= An example =

desktop = desktop_new() reference(desktop) child = window_new(desktop) unreference(desktop)

This does what is expected. The only reference to desktop is removed manually, therefore it gets destroyed. The destructor will detach all children. The only child in this case will therefore drop its reference count to zero, and get destroyed as well.

desktop = desktop_new() reference(desktop) child = window_new(desktop) reference(child) unreference(desktop)

Here, a reference is kept to child. Maybe it is the window with keyboard focus, and the focus handler holds a reference to it. So, when the desktop is destroyed, first all childs are detached again. This means, the parent member of child is set to NULL, and its reference is decreased. Since there is still the manual reference, nothing else will be done. The desktop itself however is destroyed. Also note that any other childs without a reference would be destroyed correctly, and it also would work recursively down for their childs. Only the child window stays, and the focus handler won’t crash.

unreference(child)

If the focus handler is done, the reference of child will now drop to zero, and it is destroyed as well.

Now, about cyclic references, just either don’t use them, or else take care to resolve them before dropping the last reference into the cycle. As an example, you make a watchdog window, which somehow watches another window. So, you play good, and along with storing a reference to that other window, you increase the reference count of the other window, just so you never get a dangling pointer. In your destructor, you release the reference again, so everything seems to work out. But consider this:

desktop = new_widget(NULL) reference(desktop) watchdog = new_widget(desktop) watchdog_watch(desktop) unreference(desktop)

Yikes. Now you see the problem. Although nobody holds a reference to watchdog, and we remove the only real reference to desktop, neither of them gets deleted. Worse, neither of them can ever be deleted again, since the only reference to either is from each other.

Simple rule here would be: The watchdog only ever should watch a sibling or unrelated widget, never a parent. Of course, in practice, widgets could get reparented and whatever, so things like this need watching out for. And there are many other cases. Also, you never have to use the reference counting. You just need to understand that Land provides no way to directly and forcefully delete one of its widgets, and why it is like that.

LandWidgetInterface

LandWidget

The base widget class.

Even the most basic widget already is a quite heavy object:
* It has a parent.
* It has an on-screen position.
* It has layout parameters.
* It has various flags (like keyboard focus, hidden, ...).
* Each widget can have arbitrary string-keyed properties attached to it.
* Each widget is reference counted.
* Each widget has a theme pointer.

LandWidgetProperty

land_widget_is

Parameters: LandWidget const * self, int id

Returns: int

Return true if the widget has the given type (or one derived from it).

land_widget_check

Parameters: void const * ptr, int id, char const * file, int linenum

Returns: void*

land_widget_info_string

Parameters: LandWidget * w

Returns: char const*

land_widget_set_property

Parameters: LandWidget * self, char const * property, void * data, void(* destroy)(void * data)

land_widget_del_property

Parameters: LandWidget * self, char const * property

land_widget_get_property

Parameters: LandWidget * self, char const * property

Returns: void*

land_widget_remove_all_properties

Parameters: LandWidget * self

land_widget_base_initialize

Parameters: LandWidget * self, LandWidget * parent, int x, int y, int w, int h

land_widget_base_new

Parameters: LandWidget * parent, int x, int y, int w, int h

Returns: LandWidget*

land_widget_remove

Parameters: LandWidget * self

Remove a widget from its parent. Note: If the reference held by the parent was the last this will also destroy the widget.

land_widget_interfaces_destroy_all

no parameters

land_widget_interface_register

Parameters: LandWidgetInterface * vt

Register a new widget interface with Land. The interface is then owned by Land, and you should not try to free the passed pointer. Land will automatically free it when you call land_quit().

land_widget_copy_interface

Parameters: LandWidgetInterface * basevt, char const * name

Returns: LandWidgetInterface*

land_widget_create_interface

Parameters: LandWidget * widget, char const * name

land_widget_base_destroy

Parameters: LandWidget * self

land_widget_unreference

Parameters: LandWidget * self

land_widget_reference

Parameters: LandWidget * self

land_widget_base_mouse_enter

Parameters: LandWidget * self, LandWidget * focus

land_widget_base_mouse_leave

Parameters: LandWidget * self, LandWidget * focus

land_widget_base_move

Parameters: LandWidget * self, float dx, float dy

land_widget_move

Parameters: LandWidget * self, float dx, float dy

Moves the widget.

land_widget_move_to

Parameters: LandWidget * self, float x, float y

land_widget_center

Parameters: LandWidget * self

land_widget_align

Parameters: LandWidget * self, int align

land_widget_base_size

Parameters: LandWidget * self, float dx, float dy

land_widget_size

Parameters: LandWidget * self, float dx, float dy

Resizes a widget.

land_widget_resize

Parameters: LandWidget * self, float dx, float dy

Changes the minimum size of the widget to its current size modified by the given offset.

land_widget_set_size_permanent

Parameters: LandWidget * self, float w, float h

land_widget_set_size

Parameters: LandWidget * self, float w, float h

land_widget_set_height

Parameters: LandWidget * self, float h

land_widget_retain_mouse_focus

Parameters: LandWidget * self

Called inside mouse_leave, will keep the mouse focus, and no other widget can get highlighted.

land_widget_refuse_mouse_focus

Parameters: LandWidget * self

Called inside mouse_enter, inhibits highlighting of the widget.

land_widget_request_keyboard_focus

Parameters: LandWidget * self

Called in mouse_tick (or elsewhere), will cause the widget to receive the keyboard focus.

land_widget_retain_keyboard_focus

Parameters: LandWidget * self

Called in keyboard_leave to keep the focus. Doesn’t usually make sense.

land_widget_tick

Parameters: LandWidget * self

Call this regularly on your desktop widget. It’s the base function which is needed in any widgets application to handle input to the widgets. The other important function is land_widget_draw, which handles display of widgets.

land_widget_draw

Parameters: LandWidget * self

Draw a widget on its current position. Call this on your desktop widget to display all of your widgets. This function and land_widget_tick are the two functions you should call on your desktop widget in each widgets using application.

land_widget_hide

Parameters: LandWidget * self

Hide the widget. It will not be displayed anymore, and also not take up any more space.

land_widget_unhide

Parameters: LandWidget * self

Unhide the widget.

land_widget_set_hidden

Parameters: LandWidget * self, bool hidden

land_widget_is_hidden

Parameters: LandWidget * self

Returns: bool

land_widget_outer

Parameters: LandWidget * self, float * x, float * y, float * w, float * h

land_widget_inner

Parameters: LandWidget * self, float * x, float * y, float * w, float * h

land_widget_inner_extents

Parameters: LandWidget * self, float * l, float * t, float * r, float * b

land_widget_get_inner_size

Parameters: LandWidget * self, float * w, float * h

land_widget_base_interface_initialize

no parameters

land_widget_debug

Parameters: LandWidget * w, int indentation

land_widget_keyboard_leave

Parameters: LandWidget * self

land_widget_keyboard_focus

Parameters: LandWidget * self

land_widget_flags_string

Parameters: LandWidget * w

Returns: str


Generated: Thu 27 Feb 2020 10:49:37 PM EST