mirror of
https://git.planet-casio.com/Lephenixnoir/JustUI.git
synced 2024-12-29 13:03:40 +01:00
remove inheritance from jwidget API
This is the first step in improving the widget definition process. By forcing the default behavior to be the widget behavior (thus discouraging inheritance that doesn't work in C anyway), the default of jwidget_poly_event() is exposed to the contract. This will allow further features in using events, specifically for more complex focus cases.
This commit is contained in:
parent
a2129f1ed2
commit
216918123f
12 changed files with 85 additions and 66 deletions
|
@ -125,20 +125,13 @@ static jwidget_poly type_jcounter = {
|
|||
|
||||
static int jcounter_type_id;
|
||||
|
||||
__attribute__((constructor(2001)))
|
||||
__attribute__((constructor))
|
||||
static void j_register_jcounter(void)
|
||||
{
|
||||
jcounter_type_id = j_register_widget(&type_jcounter, "jwidget");
|
||||
jcounter_type_id = j_register_widget(&type_jcounter);
|
||||
}
|
||||
```
|
||||
|
||||
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
|
||||
|
|
|
@ -28,7 +28,13 @@
|
|||
|
||||
Implementations of this function should use jwidget_msize() on the children
|
||||
to position their margin box within the widget's content box. The size set
|
||||
by this function needs not be in the minimum/maximum range of the widget. */
|
||||
by this function needs not be in the minimum/maximum range of the widget,
|
||||
which is handled later.
|
||||
|
||||
If not overloaded (i.e. NULL in the poly structure), the default behavior is
|
||||
to compute the smallest size that fits all children (based on their own
|
||||
natural content size), which only makes sense if the children are at fixed
|
||||
positions. */
|
||||
typedef void jwidget_poly_csize_t(void *w);
|
||||
|
||||
/* jwidget_poly_layout_t: Layout a widget after its size has been set
|
||||
|
@ -37,25 +43,45 @@ typedef void jwidget_poly_csize_t(void *w);
|
|||
the widget has no layout. The margin-box size allocated to the widget has
|
||||
been set in (w->w) and (w->h); the widget must now position its contents and
|
||||
children. If the widget has a layout, the layout's specialized function is
|
||||
called instead of this one. */
|
||||
called instead of this one.
|
||||
|
||||
Custom positioning for children is only relevant for widgets that use custom
|
||||
layouts, which is fairly rare. Most often, this function is used to position
|
||||
internal elements of the widget after the size has been set (e.g. jlabel
|
||||
computes line breaks here).
|
||||
|
||||
If not overloaded (i.e. NULL in the poly structure), the default behavior is
|
||||
to leave children's positions unchanged, assuming they are fixed. */
|
||||
typedef void jwidget_poly_layout_t(void *w);
|
||||
|
||||
/* jwidget_poly_render_t: Render a widget
|
||||
|
||||
This function is called during rendering after the widget's geometry is
|
||||
drawn. (x,y) are the coordinates of the content box. This function must
|
||||
render widget-specific visuals; there is no clipping, so the widget should
|
||||
honor its width and height.
|
||||
render widget-specific visuals. If the widget is clipped (as specified by
|
||||
`jwidget_set_clipped()`), this function can specify any drawing coordinates
|
||||
and all drawing will automatically be restricted with the widget's box.
|
||||
However, if the widget is not clipped, drawing beyond the widget's width and
|
||||
height will overflow to other widgets.
|
||||
|
||||
This function should call jwidget_render() for all children that need to be
|
||||
rendered. jwidget_render() handles the geometry and takes as parameters the
|
||||
coordinates of the margin box, so it can be called as:
|
||||
This function should render its children. In the simple case where all
|
||||
children can be rendered at the same time, you can simply call
|
||||
`jwidget_poly_render(w)` which will do that.
|
||||
|
||||
If for any reason children need to be rendered separately, this function can
|
||||
also called `jwidget_render()` on individual children. `jwidget_render()`
|
||||
handles the geometry and takes as parameters the coordinates of the margin
|
||||
box, so it can be called as:
|
||||
|
||||
jwidget_render(child, x + child->x, y + child->y).
|
||||
|
||||
It will draw the geometry and call the polymorphic renderer of the child at
|
||||
its content-box coordinates. Normally you can ignore geometry altogether. */
|
||||
its content-box coordinates. Normally you can ignore geometry altogether.
|
||||
|
||||
If not overloaded, the behavior is `jwidget_poly_render(w)`, i.e. just
|
||||
render the children if there are any. */
|
||||
typedef void jwidget_poly_render_t(void *w, int x, int y);
|
||||
extern jwidget_poly_render_t jwidget_poly_render;
|
||||
|
||||
/* jwidget_poly_event_t: Handle an event
|
||||
|
||||
|
@ -63,22 +89,32 @@ typedef void jwidget_poly_render_t(void *w, int x, int y);
|
|||
key events. This function is somewhat of a catch-all function for dynamic
|
||||
occurrences. The widget should either accept the event, do something with
|
||||
it, and return true, or refuse the event, do nothing and return false. This
|
||||
influences events that propagate, such as key events. */
|
||||
influences events that propagate, such as key events.
|
||||
|
||||
This function should always default to
|
||||
|
||||
return jwidget_poly_event(w, e);
|
||||
|
||||
to allow default/generic behaviors to propagate, unless the widget
|
||||
explicitly wants to interfere with them. */
|
||||
typedef bool jwidget_poly_event_t(void *w, jevent e);
|
||||
extern jwidget_poly_event_t jwidget_poly_event;
|
||||
|
||||
/* jwidget_poly_destroy_t: Destroy a widget's specific resources
|
||||
|
||||
This function must destroy the widget-specific resources. It is called by
|
||||
jwidget_destroy(), which follows it by freeing the widget's standard data
|
||||
and destroying the children. This function can be NULL if there are no
|
||||
widget-specific resources to free. */
|
||||
widget-specific resources to free. It should not call the "base" version of
|
||||
the function. */
|
||||
typedef void jwidget_poly_destroy_t(void *w);
|
||||
|
||||
/* jwidget_poly: Polymorphic interface for a widget type */
|
||||
typedef struct {
|
||||
/* Type name, used for display and inheritance */
|
||||
char const *name;
|
||||
/* Polymorphic functions */
|
||||
/* Polymorphic functions. If unused for custom widgets, should be set to
|
||||
NULL and the default behavior (described above) will apply. */
|
||||
jwidget_poly_csize_t *csize;
|
||||
jwidget_poly_layout_t *layout;
|
||||
jwidget_poly_render_t *render;
|
||||
|
@ -95,13 +131,8 @@ typedef struct {
|
|||
|
||||
This function returns a new widget type ID to pass to jwidget_init() when
|
||||
creating widgets of the custom type. Returns -1 if registration fails. The
|
||||
polymorphic structure must outlive all widgets of the custom type.
|
||||
|
||||
If (inherits) is non-NULL, the new type will inherit from the widget type
|
||||
with the provided name. All NULL functions in (poly) will be replaced by the
|
||||
parent type's functions. This mechanism only works if widgets are declared
|
||||
in inheritance order, which is normally enforced by constructor priority. */
|
||||
int j_register_widget(jwidget_poly *poly, char const *inherits);
|
||||
polymorphic structure must outlive all widgets of the custom type. */
|
||||
int j_register_widget(jwidget_poly *poly);
|
||||
|
||||
/* j_register_event(): Register a new event type
|
||||
|
||||
|
|
|
@ -589,10 +589,10 @@ static jwidget_poly type_jfileselect = {
|
|||
.destroy = jfileselect_poly_destroy,
|
||||
};
|
||||
|
||||
__attribute__((constructor(1003)))
|
||||
__attribute__((constructor))
|
||||
static void j_register_jfileselect(void)
|
||||
{
|
||||
jfileselect_type_id = j_register_widget(&type_jfileselect, "jwidget");
|
||||
jfileselect_type_id = j_register_widget(&type_jfileselect);
|
||||
JFILESELECT_LOADED = j_register_event();
|
||||
JFILESELECT_VALIDATED = j_register_event();
|
||||
JFILESELECT_CANCELED = j_register_event();
|
||||
|
|
|
@ -205,8 +205,8 @@ static jwidget_poly type_jfkeys = {
|
|||
};
|
||||
|
||||
/* Type registration */
|
||||
__attribute__((constructor(1005)))
|
||||
__attribute__((constructor))
|
||||
static void j_register_jfkeys(void)
|
||||
{
|
||||
jfkeys_type_id = j_register_widget(&type_jfkeys, "jwidget");
|
||||
jfkeys_type_id = j_register_widget(&type_jfkeys);
|
||||
}
|
||||
|
|
|
@ -391,8 +391,8 @@ static jwidget_poly type_jframe = {
|
|||
.event = jframe_poly_event,
|
||||
};
|
||||
|
||||
__attribute__((constructor(1001)))
|
||||
__attribute__((constructor))
|
||||
static void j_register_jframe(void)
|
||||
{
|
||||
jframe_type_id = j_register_widget(&type_jframe, "jwidget");
|
||||
jframe_type_id = j_register_widget(&type_jframe);
|
||||
}
|
||||
|
|
|
@ -351,10 +351,10 @@ static jwidget_poly type_jinput = {
|
|||
.destroy = jinput_poly_destroy,
|
||||
};
|
||||
|
||||
__attribute__((constructor(1003)))
|
||||
__attribute__((constructor))
|
||||
static void j_register_jinput(void)
|
||||
{
|
||||
jinput_type_id = j_register_widget(&type_jinput, "jwidget");
|
||||
jinput_type_id = j_register_widget(&type_jinput);
|
||||
JINPUT_VALIDATED = j_register_event();
|
||||
JINPUT_CANCELED = j_register_event();
|
||||
}
|
||||
|
|
|
@ -354,8 +354,8 @@ static jwidget_poly type_jlabel = {
|
|||
};
|
||||
|
||||
/* Type registration */
|
||||
__attribute__((constructor(1002)))
|
||||
__attribute__((constructor))
|
||||
static void j_register_jlabel(void)
|
||||
{
|
||||
jlabel_type_id = j_register_widget(&type_jlabel, "jwidget");
|
||||
jlabel_type_id = j_register_widget(&type_jlabel);
|
||||
}
|
||||
|
|
|
@ -277,10 +277,10 @@ static jwidget_poly type_jlist = {
|
|||
.destroy = jlist_poly_destroy,
|
||||
};
|
||||
|
||||
__attribute__((constructor(1001)))
|
||||
__attribute__((constructor))
|
||||
static void j_register_jlist(void)
|
||||
{
|
||||
jlist_type_id = j_register_widget(&type_jlist, "jwidget");
|
||||
jlist_type_id = j_register_widget(&type_jlist);
|
||||
JLIST_ITEM_TRIGGERED = j_register_event();
|
||||
JLIST_SELECTION_MOVED = j_register_event();
|
||||
JLIST_MODEL_UPDATED = j_register_event();
|
||||
|
|
|
@ -48,8 +48,8 @@ static jwidget_poly type_jpainted = {
|
|||
};
|
||||
|
||||
/* Type registration */
|
||||
__attribute__((constructor(1004)))
|
||||
__attribute__((constructor))
|
||||
static void j_register_jpainted(void)
|
||||
{
|
||||
jpainted_type_id = j_register_widget(&type_jpainted, "jwidget");
|
||||
jpainted_type_id = j_register_widget(&type_jpainted);
|
||||
}
|
||||
|
|
|
@ -297,10 +297,10 @@ static jwidget_poly type_jscene = {
|
|||
.destroy = NULL,
|
||||
};
|
||||
|
||||
__attribute__((constructor(1001)))
|
||||
__attribute__((constructor))
|
||||
static void j_register_jscene(void)
|
||||
{
|
||||
jscene_type_id = j_register_widget(&type_jscene, "jwidget");
|
||||
jscene_type_id = j_register_widget(&type_jscene);
|
||||
JSCENE_NONE = j_register_event();
|
||||
JSCENE_PAINT = j_register_event();
|
||||
JSCENE_KEY = JWIDGET_KEY;
|
||||
|
|
|
@ -79,8 +79,8 @@ static jwidget_poly type_jscrolledlist = {
|
|||
.event = jscrolledlist_poly_event,
|
||||
};
|
||||
|
||||
__attribute__((constructor(1002)))
|
||||
__attribute__((constructor))
|
||||
static void j_register_jscrolledlist(void)
|
||||
{
|
||||
jscrolledlist_type_id = j_register_widget(&type_jscrolledlist, "jwidget");
|
||||
jscrolledlist_type_id = j_register_widget(&type_jscrolledlist);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#define WIDGET_TYPES_MAX 32
|
||||
|
||||
/* Polymorphic functions for jwidget */
|
||||
static jwidget_poly_render_t jwidget_poly_render;
|
||||
static jwidget_poly_csize_t jwidget_poly_csize;
|
||||
|
||||
/* jwidget type definition */
|
||||
|
@ -21,7 +20,7 @@ static jwidget_poly type_jwidget = {
|
|||
.csize = jwidget_poly_csize,
|
||||
.layout = NULL,
|
||||
.render = jwidget_poly_render,
|
||||
.event = NULL,
|
||||
.event = jwidget_poly_event,
|
||||
.destroy = NULL,
|
||||
};
|
||||
|
||||
|
@ -40,7 +39,7 @@ uint16_t JWIDGET_FOCUS_OUT;
|
|||
// Polymorphic functions for widgets
|
||||
//---
|
||||
|
||||
static void jwidget_poly_render(void *w0, int x, int y)
|
||||
void jwidget_poly_render(void *w0, int x, int y)
|
||||
{
|
||||
J_CAST(w)
|
||||
jlayout_stack *l;
|
||||
|
@ -86,6 +85,13 @@ static void jwidget_poly_csize(void *w0)
|
|||
}
|
||||
}
|
||||
|
||||
bool jwidget_poly_event(void *w0, jevent e)
|
||||
{
|
||||
J_CAST(w)
|
||||
(void)w;
|
||||
return false;
|
||||
}
|
||||
|
||||
//---
|
||||
// Initialization
|
||||
//---
|
||||
|
@ -721,25 +727,14 @@ char const *jwidget_type(void *w0)
|
|||
return widget_types[w->type]->name;
|
||||
}
|
||||
|
||||
int j_register_widget(jwidget_poly *poly, char const *inherits)
|
||||
int j_register_widget(jwidget_poly *poly)
|
||||
{
|
||||
/* Resolve inheritance */
|
||||
if(inherits) {
|
||||
jwidget_poly const *base = NULL;
|
||||
|
||||
for(int i = 0; i < WIDGET_TYPES_MAX && !base; i++) {
|
||||
if(widget_types[i] && !strcmp(widget_types[i]->name, inherits))
|
||||
base = widget_types[i];
|
||||
}
|
||||
|
||||
if(!base) return -1;
|
||||
|
||||
if(!poly->csize) poly->csize = base->csize;
|
||||
if(!poly->layout) poly->layout = base->layout;
|
||||
if(!poly->render) poly->render = base->render;
|
||||
if(!poly->event) poly->event = base->event;
|
||||
if(!poly->destroy) poly->destroy = base->destroy;
|
||||
}
|
||||
/* Resolve default behaviors */
|
||||
if(!poly->csize) poly->csize = jwidget_poly_csize;
|
||||
if(!poly->layout) poly->layout = NULL;
|
||||
if(!poly->render) poly->render = jwidget_poly_render;
|
||||
if(!poly->event) poly->event = jwidget_poly_event;
|
||||
if(!poly->destroy) poly->destroy = NULL;
|
||||
|
||||
for(int i = 0; i < WIDGET_TYPES_MAX; i++) {
|
||||
if(widget_types[i] == NULL) {
|
||||
|
|
Loading…
Reference in a new issue