# JustUI: Widget types ## General widgets and void types JustUI defines a base structure `jwidget` useful for containers, as well as a number of derived structures for content widgets. Because C does not support any type of polymorphism, JustUI uses `void *` pointers when referring to "any widget", which accepts pointers to any base or derived structure. This relaxed typing scheme mostly applies to the `jwidget_*()` functions that operate on the widget level. Widget-specific functions such as `jinput_value()` request exactly their type of widget as input (in this case, `jinput`). Essentially, this means that `jwidget` can be inherited from transparently, but the other types cannot (a structure attribute must be used). This is a compromise to work with polymorphic types in the C type system. ## Widget collection **`jwidget`** is the base type. It provides children/parent management (see [Widget hierarchy](hierarchy.md)), built-in layouts (see [Space distribution and layout](layout.md)) and size constraints, geometry (margin, border, padding, background), and automatic repaint/relayout mechanisms. **`jlabel`** is a content widget that shows a single-line or multi-line piece of text. It supports various text alignment options (left/right/center), line wrapping (letter and word level), and a couple of graphical options. **`jscene`** is a special widget designed to be at the root of the widget tree. It provides event dispatching, automatic repaint and layout, keyboard input, and a generic input loop that is suitable for most GUI programs. See [Scenes and events](scene.md). **`jinput`** is a one-line input field. It supports direct key input, delayed and instant SHIFT and ALPHA modifiers, as well as modifier locking, with visual hints. **`jpainted`** is a very simple wigdet that paints itself with a user-provided function. It is intended to make custom widgets with very little effort. A `jpainted` can be positioned, sized and managed by the widget tree while the user only provides a drawing function. **`jfkeys`** represents a function key bar, normally at the bottom of the screen. On fx-9860G, it uses an image to show keys; on fx-CG 50, it supports a string specification that looks like `"@JUMP;;#ROM;#RAM;#ILRAM;#ADDIN"`. It can change options dynamically. ## Custom widgets and polymorphic operations For custom widgets that just have custom rendering a no event management, one can simply use a `jpainted` instance with well-chosen options. However, for reusable widgets that have internal state or event handling, a new widget type should be created. A custom widget must be a structure that starts with a `jwidget`. The type itself should be register with `j_register_widget()`, and provide a couple of polymorphic functions. Here is an example with a very trivial widget that holds an integer counter. ```c typedef struct { jwidget widget; int counter; } jcounter; ``` To be registered in JustUI, a custom widget type must provide a couple of functions, in the form of a `jwidget_poly` structure. All of the following functions are detailed in ``, but here is a brief review of the requirements (the `type_poly_` prefix is customary). All of the functions receive pointers to `jcounter` structures, but the type is `void *` because of the limitations mentioned earlier. ```c /* Receives a (jcounter *). Should set its (w) and (h) attributes to the natural dimensions of the widget. Cannot be NULL. */ void jcounter_poly_csize(void *counter); /* Paint a jcounter at (x,y). */ void jcounter_poly_render(void *counter, int x, int y); /* Destroy the resources of a jcounter. (If there are not malloc'd pointers in the structure, this is generally not needed.) */ void jcounter_poly_destroy(void *counter); ``` The following functions should be implemented if the custom widget needs to receive events (such as keyboard input). Events are defined in ``. ```c /* Handle event (e) sent to a jcounter. Should return true if the event was accepted/used, false if it was ignored/unused. */ bool jcounter_poly_event(void *counter, jevent e); ``` The following function is used if (1) an instance of the custom widget has children, and (2) this instance does not have a layout. This is rarely needed. See [Space distribution and layout](layout.md) ```c /* Receives a (jcounter *) that has its full size set in the (w) and (h) attributes. Should determine the position and size of the children. */ void jcounter_poly_layout(void *counter); ``` In general, most of the work consists in specifying the `csize()` and `render()` functions. `destroy()` just has to release the resources allocated during widget creation, `event()` is straightforward, and `layout()` is very rarely needed at all. Once the required functions are implemented, a polymorphic widget structure can be defined and registered as a new type. A good way to do this is to register the widget in a constructor located in the same file as the widget creation function, so that it runs automatically if the widget is used. ```c static jwidget_poly type_jcounter = { .name = "jcounter", .csize = jcounter_poly_csize, .layout = NULL, .render = jcounter_poly_render, .event = NULL, .destroy = NULL, }; static int jcounter_type_id; __attribute__((constructor(2001))) static void j_register_jcounter(void) { jcounter_type_id = j_register_widget(&type_jcounter, "jwidget"); } ``` The second parameter to `j_register_widget()` specifies inheritance. `jcounter` inherits from `jwidget`, which means that the unspecified polymorphic functions (`layout`, `event` and `destroy`) will use the default behavior of `jwidget`. This is mostly useful if you don't specify `csize` (the default behavior is to select the smallest size where all children fit) or `render` (the default behavior is to render all visible children). The type ID returned by `j_register_widget()` is how JustUI differentiates labels from input fields from custom counters. When creating the widget, you should initialize the `jwidget` field with `jwidget_init()` and specify the type ID. Note how the parent is also passed at creation time so that the new widget can automatically be attached to the tree. ```c jcounter *jcounter_create(int initial_value, void *parent) { if(jcounter_type_id < 0) return NULL; jcounter *c = malloc(sizeof *c); jwidget_init(&c->widget, jcounter_type_id, parent); c->counter = initial_value; return c; } ``` That's pretty much it. There is a fair amount of boilerplate, but this part is the same for every widget. See `jpainted` for a simple example and `jinput` for a full-featured one.