mirror of
https://git.planet-casio.com/Lephenixnoir/JustUI.git
synced 2025-06-06 05:25:10 +02:00
jscene: basic touch support with "inspector"-like debug
This commit is contained in:
parent
0878c16182
commit
cd73b2ea6f
5 changed files with 177 additions and 3 deletions
|
@ -5,6 +5,17 @@
|
||||||
#ifndef _JUSTUI_CONFIG
|
#ifndef _JUSTUI_CONFIG
|
||||||
#define _JUSTUI_CONFIG
|
#define _JUSTUI_CONFIG
|
||||||
|
|
||||||
|
#include <gint/config.h>
|
||||||
|
|
||||||
#define J_VERSION "@JustUI_VERSION@"
|
#define J_VERSION "@JustUI_VERSION@"
|
||||||
|
|
||||||
|
#if GINT_HW_CP
|
||||||
|
#define J_CONFIG_TOUCH 1
|
||||||
|
#else
|
||||||
|
#define J_CONFIG_TOUCH 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Set to 1 to enable a touch-following widget inspector. */
|
||||||
|
#define J_CONFIG_TOUCH_INSPECTOR (J_CONFIG_TOUCH && 1)
|
||||||
|
|
||||||
#endif /* _JUSTUI_CONFIG */
|
#endif /* _JUSTUI_CONFIG */
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <justui/defs.h>
|
#include <justui/defs.h>
|
||||||
#include <justui/jwidget.h>
|
#include <justui/jwidget.h>
|
||||||
#include <justui/jevent.h>
|
#include <justui/jevent.h>
|
||||||
|
#include <justui/config.h>
|
||||||
|
|
||||||
#define JSCENE_QUEUE_SIZE 32
|
#define JSCENE_QUEUE_SIZE 32
|
||||||
|
|
||||||
|
@ -36,6 +37,9 @@ typedef struct {
|
||||||
/* Whether jscene_run() will autopaint */
|
/* Whether jscene_run() will autopaint */
|
||||||
bool autopaint;
|
bool autopaint;
|
||||||
|
|
||||||
|
/* Last coordinates a touch cursor was seen at */
|
||||||
|
int16_t touch_last_x, touch_last_y;
|
||||||
|
|
||||||
} jscene;
|
} jscene;
|
||||||
|
|
||||||
/* Events */
|
/* Events */
|
||||||
|
@ -65,6 +69,21 @@ jscene *jscene_owning(void *widget);
|
||||||
(x,y) point. */
|
(x,y) point. */
|
||||||
void jscene_render(jscene *scene);
|
void jscene_render(jscene *scene);
|
||||||
|
|
||||||
|
/* jscene_widget_at(): Find top-most widget at specified location
|
||||||
|
|
||||||
|
Returns the top-most widget at the given scene-local location.
|
||||||
|
* If there is no widget in the scene covering this location, returns NULL.
|
||||||
|
* If there is exactly one, returns it.
|
||||||
|
* If there are multiple, this function returns the first found by depth-
|
||||||
|
first search where children are enumerated floating first, non-floating
|
||||||
|
next, and increasing within child index order within each group.
|
||||||
|
* For widgets with a stacked layout, only the active child is considered.
|
||||||
|
|
||||||
|
If content_only is set, this function only intersects with the content box.
|
||||||
|
Otherwise, an intersection with the full box (padding, border and margin
|
||||||
|
included) is performed. */
|
||||||
|
jwidget *jscene_widget_at(jscene *scene, int x, int y, bool content_only);
|
||||||
|
|
||||||
//---
|
//---
|
||||||
// Events sent from the scene to the user
|
// Events sent from the scene to the user
|
||||||
//---
|
//---
|
||||||
|
|
|
@ -339,6 +339,18 @@ bool jwidget_layout_dirty(void *scene_root);
|
||||||
need to keep the layout up-to-date before doing it. */
|
need to keep the layout up-to-date before doing it. */
|
||||||
void jwidget_layout(void *scene_root);
|
void jwidget_layout(void *scene_root);
|
||||||
|
|
||||||
|
/* jwidget_absolute_x(): Absolute x-position of a widget
|
||||||
|
jwidget_absolute_y(): Absolute y-position of a widget
|
||||||
|
jwidget_absolute_content_x(): Absolute x-position of a widget's content box
|
||||||
|
jwidget_absolute_content_y(): Absolute y-position of a widget's content box
|
||||||
|
|
||||||
|
These are actually based on the root's coordinates, which are typically 0,0
|
||||||
|
with a full-screen scene. */
|
||||||
|
int jwidget_absolute_x(void *w);
|
||||||
|
int jwidget_absolute_y(void *w);
|
||||||
|
int jwidget_absolute_content_x(void *w);
|
||||||
|
int jwidget_absolute_content_y(void *w);
|
||||||
|
|
||||||
/* jwidget_width(): With of a widget's content box
|
/* jwidget_width(): With of a widget's content box
|
||||||
jwidget_height(): Height of a widget's content box
|
jwidget_height(): Height of a widget's content box
|
||||||
|
|
||||||
|
|
106
src/jscene.c
106
src/jscene.c
|
@ -62,6 +62,9 @@ jscene *jscene_create(int x, int y, int w, int h, void *parent)
|
||||||
s->poweroff = true;
|
s->poweroff = true;
|
||||||
s->autopaint = false;
|
s->autopaint = false;
|
||||||
|
|
||||||
|
s->touch_last_x = -1;
|
||||||
|
s->touch_last_y = -1;
|
||||||
|
|
||||||
/* Prepare first layout/paint operation */
|
/* Prepare first layout/paint operation */
|
||||||
s->widget.dirty = 1;
|
s->widget.dirty = 1;
|
||||||
|
|
||||||
|
@ -84,10 +87,94 @@ jscene *jscene_owning(void *w0)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void jscene_render(jscene *scene)
|
void jscene_render(jscene *s)
|
||||||
{
|
{
|
||||||
jwidget_layout(scene);
|
jwidget_layout(s);
|
||||||
jwidget_render(scene, scene->x, scene->y);
|
jwidget_render(s, s->x, s->y);
|
||||||
|
|
||||||
|
#if J_CONFIG_TOUCH_INSPECTOR
|
||||||
|
if(s->touch_last_x >= 0 && s->touch_last_y >= 0) {
|
||||||
|
jwidget *w =
|
||||||
|
jscene_widget_at(s, s->touch_last_x, s->touch_last_y, true);
|
||||||
|
if(w) {
|
||||||
|
int x1 = jwidget_absolute_content_x(w);
|
||||||
|
int y1 = jwidget_absolute_content_y(w);
|
||||||
|
int x2 = x1 + jwidget_content_width(w) - 1;
|
||||||
|
int y2 = y1 + jwidget_content_height(w) - 1;
|
||||||
|
drect_border(x1, y1, x2, y2, C_NONE, 1, C_RED);
|
||||||
|
|
||||||
|
dprint_opt(DWIDTH-1, 0, C_WHITE, C_RED, DTEXT_RIGHT, DTEXT_TOP,
|
||||||
|
"%s", jwidget_type(w));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find sub-widget based on w-local coordinates. */
|
||||||
|
static jwidget *jscene_widget_at_rec(
|
||||||
|
jwidget *w, int x, int y, bool content_only, bool visible_only)
|
||||||
|
{
|
||||||
|
if(!w)
|
||||||
|
return NULL;
|
||||||
|
jwidget *found;
|
||||||
|
|
||||||
|
jwidget_geometry const *g = jwidget_geometry_r(w);
|
||||||
|
int xC = g->margin.left + g->border.left + g->padding.left;
|
||||||
|
int yC = w->y + g->margin.top + g->border.top + g->padding.top;
|
||||||
|
uint wC = jwidget_content_width(w);
|
||||||
|
uint hC = jwidget_content_height(w);
|
||||||
|
uint wF = jwidget_full_width(w);
|
||||||
|
uint hF = jwidget_full_height(w);
|
||||||
|
|
||||||
|
/* Check if we intersect w at all */
|
||||||
|
bool intersects;
|
||||||
|
if(content_only)
|
||||||
|
intersects = ((uint)(x - xC) < wC) && ((uint)(y - yC) < hC);
|
||||||
|
else
|
||||||
|
intersects = (uint)x < wF && (uint)y < hF;
|
||||||
|
if(!intersects)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* If we have a stacked widget, only consider the visible child */
|
||||||
|
jlayout_stack *stack;
|
||||||
|
if((stack = jlayout_get_stack(w))) {
|
||||||
|
if(stack->active < 0)
|
||||||
|
return w;
|
||||||
|
jwidget *child = w->children[stack->active];
|
||||||
|
found = jscene_widget_at_rec(child, x - xC, y - yC, content_only,
|
||||||
|
visible_only);
|
||||||
|
return found ? found : w;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to find a descendant of a floating child that intersects... */
|
||||||
|
for(int k = 0; k < w->child_count; k++) {
|
||||||
|
jwidget *child = w->children[k];
|
||||||
|
if(child->visible >= visible_only && child->floating) {
|
||||||
|
found = jscene_widget_at_rec(child, x - xC, y - yC, content_only,
|
||||||
|
visible_only);
|
||||||
|
if(found)
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ... or a descendant of a non-floating child */
|
||||||
|
for(int k = 0; k < w->child_count; k++) {
|
||||||
|
jwidget *child = w->children[k];
|
||||||
|
if(child->visible >= visible_only && !child->floating) {
|
||||||
|
found = jscene_widget_at_rec(child, x - xC, y - yC, content_only,
|
||||||
|
visible_only);
|
||||||
|
if(found)
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If no descendants do, then the best match is w itself. */
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
jwidget *jscene_widget_at(jscene *scene, int x, int y, bool content_only)
|
||||||
|
{
|
||||||
|
return jscene_widget_at_rec(&scene->widget, x, y, content_only, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
@ -260,6 +347,19 @@ static jevent poll_next_unhandled_event(keydev_t *d, jscene *s)
|
||||||
|
|
||||||
/* Then try to dequeue keyboard events, if there are any. */
|
/* Then try to dequeue keyboard events, if there are any. */
|
||||||
while((k = keydev_read(d, false, NULL)).type != KEYEV_NONE) {
|
while((k = keydev_read(d, false, NULL)).type != KEYEV_NONE) {
|
||||||
|
/* Keep track of where the touch cursor was last seen. */
|
||||||
|
#if J_CONFIG_TOUCH_INSPECTOR
|
||||||
|
if(k.type == KEYEV_TOUCH_DOWN || k.type == KEYEV_TOUCH_DRAG) {
|
||||||
|
s->touch_last_x = k.x - s->x;
|
||||||
|
s->touch_last_y = k.y - s->y;
|
||||||
|
s->widget.update = true;
|
||||||
|
}
|
||||||
|
if(k.type == KEYEV_TOUCH_UP) {
|
||||||
|
s->touch_last_x = -1;
|
||||||
|
s->touch_last_y = -1;
|
||||||
|
s->widget.update = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* Auto return-to-menu */
|
/* Auto return-to-menu */
|
||||||
if(k.type == KEYEV_DOWN && k.key == KEY_MENU && !k.shift && !k.alpha) {
|
if(k.type == KEYEV_DOWN && k.key == KEY_MENU && !k.shift && !k.alpha) {
|
||||||
if(s->mainmenu) {
|
if(s->mainmenu) {
|
||||||
|
|
|
@ -567,6 +567,38 @@ void jwidget_layout(void *root0)
|
||||||
jwidget_layout_apply(root);
|
jwidget_layout_apply(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int jwidget_absolute_x(void *w0)
|
||||||
|
{
|
||||||
|
J_CAST(w)
|
||||||
|
return w ? w->x + jwidget_absolute_x(w->parent) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jwidget_absolute_y(void *w0)
|
||||||
|
{
|
||||||
|
J_CAST(w)
|
||||||
|
return w ? w->y + jwidget_absolute_y(w->parent) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jwidget_absolute_content_x(void *w0)
|
||||||
|
{
|
||||||
|
J_CAST(w)
|
||||||
|
if(!w)
|
||||||
|
return 0;
|
||||||
|
jwidget_geometry const *g = jwidget_geometry_r(w);
|
||||||
|
return jwidget_absolute_content_x(w->parent) +
|
||||||
|
w->x + g->margin.left + g->border.left + g->padding.left;
|
||||||
|
}
|
||||||
|
|
||||||
|
int jwidget_absolute_content_y(void *w0)
|
||||||
|
{
|
||||||
|
J_CAST(w)
|
||||||
|
if(!w)
|
||||||
|
return 0;
|
||||||
|
jwidget_geometry const *g = jwidget_geometry_r(w);
|
||||||
|
return jwidget_absolute_content_y(w->parent) +
|
||||||
|
w->y + g->margin.top + g->border.top + g->padding.top;
|
||||||
|
}
|
||||||
|
|
||||||
int jwidget_content_width(void *w0)
|
int jwidget_content_width(void *w0)
|
||||||
{
|
{
|
||||||
J_CAST(w)
|
J_CAST(w)
|
||||||
|
|
Loading…
Add table
Reference in a new issue