mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-05 17:01:25 +00:00
[ui] Implement auto-expand layout
By default, horizontal and vertical layouts expand to fill their parent in their on-axis direction (horizontally for horizontal layouts), but fit to their child views in their off-axis. Flexible space views take advantage of auto-expansion, pushing sibling views such that the grandparent view is filled on the parent view's on-axis, and the parent view is filled by the space in the parent view's off-axis. Flexible views currently have a background fill, allowing them to provide background filling of the overall view with minimal overdraw (ancestor views don't need to have any fill at all).
This commit is contained in:
parent
a92754caf1
commit
0fab830be6
5 changed files with 278 additions and 44 deletions
|
@ -68,6 +68,7 @@ typedef struct canvas_system_s {
|
||||||
uint32_t base;
|
uint32_t base;
|
||||||
uint32_t view_base;
|
uint32_t view_base;
|
||||||
uint32_t text_base;
|
uint32_t text_base;
|
||||||
|
uint32_t imui_base;
|
||||||
} canvas_system_t;
|
} canvas_system_t;
|
||||||
|
|
||||||
struct view_s;
|
struct view_s;
|
||||||
|
|
|
@ -35,12 +35,22 @@ typedef struct imui_ctx_s imui_ctx_t;
|
||||||
struct canvas_system_s;
|
struct canvas_system_s;
|
||||||
struct IE_event_s;
|
struct IE_event_s;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
imui_percent_x, ///< int
|
||||||
|
imui_percent_y, ///< int
|
||||||
|
|
||||||
|
imui_comp_count
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const struct component_s imui_components[imui_comp_count];
|
||||||
|
|
||||||
typedef enum IMUI_SizeKind {
|
typedef enum IMUI_SizeKind {
|
||||||
IMUI_SizeKind_Null,
|
IMUI_SizeKind_Null,
|
||||||
IMUI_SizeKind_Pixels,
|
IMUI_SizeKind_Pixels,
|
||||||
IMUI_SizeKind_TextContent,
|
IMUI_SizeKind_TextContent,
|
||||||
IMUI_SizeKind_PercentOfParent,
|
IMUI_SizeKind_PercentOfParent,
|
||||||
IMUI_SizeKind_ChildrenSum,
|
IMUI_SizeKind_ChildrenSum,
|
||||||
|
IMUI_SizeKind_Expand,
|
||||||
} IMUI_SizeKind;
|
} IMUI_SizeKind;
|
||||||
|
|
||||||
imui_ctx_t *IMUI_NewContext (struct canvas_system_s canvas_sys,
|
imui_ctx_t *IMUI_NewContext (struct canvas_system_s canvas_sys,
|
||||||
|
@ -61,6 +71,7 @@ bool IMUI_Checkbox (imui_ctx_t *ctx, bool *flag, const char *label);
|
||||||
void IMUI_Radio (imui_ctx_t *ctx, int *curvalue, int value, const char *label);
|
void IMUI_Radio (imui_ctx_t *ctx, int *curvalue, int value, const char *label);
|
||||||
void IMUI_Slider (imui_ctx_t *ctx, float *value, float minval, float maxval,
|
void IMUI_Slider (imui_ctx_t *ctx, float *value, float minval, float maxval,
|
||||||
const char *label);
|
const char *label);
|
||||||
|
void IMUI_FlexibleSpace (imui_ctx_t *ctx);
|
||||||
|
|
||||||
#define IMUI_DeferLoop(begin, end) \
|
#define IMUI_DeferLoop(begin, end) \
|
||||||
for (int _i_ = ((begin), 0); !_i_; _i_++, (end))
|
for (int _i_ = ((begin), 0); !_i_; _i_++, (end))
|
||||||
|
@ -79,8 +90,14 @@ void IMUI_Slider (imui_ctx_t *ctx, float *value, float minval, float maxval,
|
||||||
#define UI_Slider(value, minval, maxval, label) \
|
#define UI_Slider(value, minval, maxval, label) \
|
||||||
IMUI_Slider(IMUI_context, value, minval, maxval, label)
|
IMUI_Slider(IMUI_context, value, minval, maxval, label)
|
||||||
|
|
||||||
|
#define UI_FlexibleSpace() \
|
||||||
|
IMUI_FlexibleSpace(IMUI_context)
|
||||||
|
|
||||||
#define UI_Layout(vertical) \
|
#define UI_Layout(vertical) \
|
||||||
IMUI_DeferLoop (IMUI_PushLayout (IMUI_context, vertical), \
|
IMUI_DeferLoop (IMUI_PushLayout (IMUI_context, vertical), \
|
||||||
IMUI_PopLayout (IMUI_context ))
|
IMUI_PopLayout (IMUI_context ))
|
||||||
|
|
||||||
|
#define UI_Horizontal UI_Layout(false)
|
||||||
|
#define UI_Vertical UI_Layout(true)
|
||||||
|
|
||||||
#endif//__QF_ui_imui_h
|
#endif//__QF_ui_imui_h
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "QF/cvar.h"
|
#include "QF/cvar.h"
|
||||||
#include "QF/keys.h"
|
#include "QF/keys.h"
|
||||||
#include "QF/sys.h"
|
#include "QF/sys.h"
|
||||||
|
#include "QF/va.h"
|
||||||
|
|
||||||
#include "QF/input/event.h"
|
#include "QF/input/event.h"
|
||||||
|
|
||||||
|
@ -52,6 +53,9 @@ static cvar_t deb_fontsize_cvar = {
|
||||||
.value = { .type = &cexpr_float, .value = &deb_fontsize },
|
.value = { .type = &cexpr_float, .value = &deb_fontsize },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int deb_xlen = -1;
|
||||||
|
static int deb_ylen = -1;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
con_debug_f (void *data, const cvar_t *cvar)
|
con_debug_f (void *data, const cvar_t *cvar)
|
||||||
{
|
{
|
||||||
|
@ -61,12 +65,12 @@ con_debug_f (void *data, const cvar_t *cvar)
|
||||||
debug_enable_time = Sys_LongTime ();
|
debug_enable_time = Sys_LongTime ();
|
||||||
if (!con_debug) {
|
if (!con_debug) {
|
||||||
IE_Set_Focus (debug_saved_focus);
|
IE_Set_Focus (debug_saved_focus);
|
||||||
|
} else {
|
||||||
|
IMUI_SetSize (debug_imui, deb_xlen, deb_ylen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int deb_xlen = -1;
|
|
||||||
static int deb_ylen = -1;
|
|
||||||
static void
|
static void
|
||||||
debug_app_window (const IE_event_t *ie_event)
|
debug_app_window (const IE_event_t *ie_event)
|
||||||
{
|
{
|
||||||
|
@ -152,26 +156,34 @@ Con_Debug_Draw (void)
|
||||||
IMUI_BeginFrame (debug_imui);
|
IMUI_BeginFrame (debug_imui);
|
||||||
static int state;
|
static int state;
|
||||||
static bool flag = true;
|
static bool flag = true;
|
||||||
UI_Layout(true) {
|
UI_Vertical {
|
||||||
UI_Layout(false) {
|
UI_Horizontal {
|
||||||
if (UI_Button ("Close Debug")) {
|
if (UI_Button ("Close Debug")) {
|
||||||
close_debug ();
|
close_debug ();
|
||||||
}
|
}
|
||||||
if (flag) {
|
if (flag) {
|
||||||
UI_Button ("_##1");
|
UI_FlexibleSpace ();
|
||||||
|
UI_Button ("abcdefghijklmnopqrstuvwxyza##1");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UI_Layout(false) {
|
UI_Horizontal {
|
||||||
UI_Checkbox (&flag, "hi there");
|
UI_Checkbox (&flag, "hi there");
|
||||||
if (flag) {
|
if (flag) {
|
||||||
UI_Button ("_##2");
|
UI_FlexibleSpace ();
|
||||||
|
UI_Button ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst##2");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UI_Layout(false) {
|
UI_Horizontal {
|
||||||
UI_Radio (&state, 0, "A");
|
UI_Radio (&state, 0, "A");
|
||||||
UI_Radio (&state, 1, "B");
|
UI_Radio (&state, 1, "B");
|
||||||
UI_Radio (&state, 2, "C");
|
UI_Radio (&state, 2, "C");
|
||||||
|
UI_FlexibleSpace ();
|
||||||
}
|
}
|
||||||
|
UI_Horizontal {
|
||||||
|
UI_Button (va(0, "mem: %zd", Sys_CurrentRSS ()));
|
||||||
|
UI_FlexibleSpace ();
|
||||||
|
}
|
||||||
|
UI_FlexibleSpace ();
|
||||||
}
|
}
|
||||||
|
|
||||||
IMUI_Draw (debug_imui);
|
IMUI_Draw (debug_imui);
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
#define IMPLEMENT_CANVAS_Funcs
|
#define IMPLEMENT_CANVAS_Funcs
|
||||||
#include "QF/ui/canvas.h"
|
#include "QF/ui/canvas.h"
|
||||||
|
#include "QF/ui/imui.h"
|
||||||
#include "QF/ui/text.h"
|
#include "QF/ui/text.h"
|
||||||
#include "QF/ui/view.h"
|
#include "QF/ui/view.h"
|
||||||
|
|
||||||
|
@ -498,6 +499,8 @@ Canvas_InitSys (canvas_system_t *canvas_sys, ecs_registry_t *reg)
|
||||||
view_comp_count),
|
view_comp_count),
|
||||||
.text_base = ECS_RegisterComponents (reg, text_components,
|
.text_base = ECS_RegisterComponents (reg, text_components,
|
||||||
text_comp_count),
|
text_comp_count),
|
||||||
|
.imui_base = ECS_RegisterComponents (reg, imui_components,
|
||||||
|
imui_comp_count),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
273
libs/ui/imui.c
273
libs/ui/imui.c
|
@ -47,6 +47,17 @@
|
||||||
#include "QF/ui/imui.h"
|
#include "QF/ui/imui.h"
|
||||||
#include "QF/ui/text.h"
|
#include "QF/ui/text.h"
|
||||||
|
|
||||||
|
const component_t imui_components[imui_comp_count] = {
|
||||||
|
[imui_percent_x] = {
|
||||||
|
.size = sizeof (int),
|
||||||
|
.name = "percent x",
|
||||||
|
},
|
||||||
|
[imui_percent_y] = {
|
||||||
|
.size = sizeof (int),
|
||||||
|
.name = "percent y",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct imui_state_s {
|
typedef struct imui_state_s {
|
||||||
struct imui_state_s *next;
|
struct imui_state_s *next;
|
||||||
struct imui_state_s **prev;
|
struct imui_state_s **prev;
|
||||||
|
@ -234,8 +245,10 @@ void
|
||||||
IMUI_BeginFrame (imui_ctx_t *ctx)
|
IMUI_BeginFrame (imui_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
uint32_t root_ent = ctx->root_view.id;
|
uint32_t root_ent = ctx->root_view.id;
|
||||||
|
auto root_size = View_GetLen (ctx->root_view);
|
||||||
Ent_RemoveComponent (root_ent, ctx->root_view.comp, ctx->root_view.reg);
|
Ent_RemoveComponent (root_ent, ctx->root_view.comp, ctx->root_view.reg);
|
||||||
ctx->root_view = View_AddToEntity (root_ent, ctx->vsys, nullview);
|
ctx->root_view = View_AddToEntity (root_ent, ctx->vsys, nullview);
|
||||||
|
View_SetLen (ctx->root_view, root_size.x, root_size.y);
|
||||||
ctx->frame_start = Sys_LongTime ();
|
ctx->frame_start = Sys_LongTime ();
|
||||||
ctx->frame_count++;
|
ctx->frame_count++;
|
||||||
ctx->current_parent = ctx->root_view;
|
ctx->current_parent = ctx->root_view;
|
||||||
|
@ -256,47 +269,118 @@ prune_objects (imui_ctx_t *ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//FIXME currently works properly only for grav_northwest
|
#define DFL "\e[39;49m"
|
||||||
static void
|
#define BLK "\e[30;40m"
|
||||||
layout_objects (imui_ctx_t *ctx)
|
#define RED "\e[31;40m"
|
||||||
{
|
#define GRN "\e[32;40m"
|
||||||
auto ref = View_GetRef (ctx->root_view);
|
#define ONG "\e[33;40m"
|
||||||
auto h = ref->hierarchy;
|
#define BLU "\e[34;40m"
|
||||||
|
#define MAG "\e[35;40m"
|
||||||
|
#define CYN "\e[36;40m"
|
||||||
|
#define WHT "\e[37;40m"
|
||||||
|
|
||||||
byte *modified = h->components[view_modified];
|
static const char *
|
||||||
view_pos_t *pos = h->components[view_pos];
|
view_color (hierarchy_t *h, uint32_t ind, imui_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
auto reg = h->reg;
|
||||||
|
uint32_t e = h->ent[ind];
|
||||||
|
viewcont_t *cont = h->components[view_control];
|
||||||
|
|
||||||
|
switch (cont[ind].semantic_x) {
|
||||||
|
case IMUI_SizeKind_Null:
|
||||||
|
if (Ent_HasComponent (e, ctx->csys.base + canvas_glyphs, reg)) {
|
||||||
|
return CYN;
|
||||||
|
}
|
||||||
|
return DFL;
|
||||||
|
case IMUI_SizeKind_Pixels: return WHT;
|
||||||
|
case IMUI_SizeKind_TextContent: return CYN;
|
||||||
|
case IMUI_SizeKind_PercentOfParent: return ONG;
|
||||||
|
case IMUI_SizeKind_ChildrenSum: return MAG;
|
||||||
|
case IMUI_SizeKind_Expand: return RED;
|
||||||
|
}
|
||||||
|
return DFL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __attribute__((used))
|
||||||
|
dump_tree (hierarchy_t *h, uint32_t ind, int level, imui_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
view_pos_t *len = h->components[view_len];
|
||||||
|
auto c = ((viewcont_t *)h->components[view_control])[ind];
|
||||||
|
uint32_t e = h->ent[ind];
|
||||||
|
printf ("%2d: %*s%s[%d %d] %c %d %d", ind,
|
||||||
|
level * 3, "", view_color (h, ind, ctx),
|
||||||
|
len[ind].x, len[ind].y,
|
||||||
|
c.vertical ? 'v' : 'h', c.semantic_x, c.semantic_y);
|
||||||
|
for (uint32_t j = 0; j < h->reg->components.size; j++) {
|
||||||
|
if (Ent_HasComponent (e, j, h->reg)) {
|
||||||
|
printf (", %s", h->reg->components.a[j].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf (DFL"\n");
|
||||||
|
|
||||||
|
if (h->childIndex[ind] > ind) {
|
||||||
|
for (uint32_t i = 0; i < h->childCount[ind]; i++) {
|
||||||
|
if (h->childIndex[ind] + i >= h->num_objects) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dump_tree (h, h->childIndex[ind] + i, level + 1, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!level) {
|
||||||
|
puts ("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool x, y;
|
||||||
|
} boolpair_t;
|
||||||
|
|
||||||
|
static void
|
||||||
|
calc_upwards_dependent (imui_ctx_t *ctx, hierarchy_t *h,
|
||||||
|
boolpair_t *down_depend)
|
||||||
|
{
|
||||||
|
auto reg = ctx->csys.reg;
|
||||||
|
uint32_t *ent = h->ent;
|
||||||
view_pos_t *len = h->components[view_len];
|
view_pos_t *len = h->components[view_len];
|
||||||
viewcont_t *cont = h->components[view_control];
|
viewcont_t *cont = h->components[view_control];
|
||||||
uint32_t *parent = h->parentIndex;
|
uint32_t *parent = h->parentIndex;
|
||||||
struct boolpair {
|
uint32_t c_percent_x = ctx->csys.imui_base + imui_percent_x;
|
||||||
bool x, y;
|
uint32_t c_percent_y = ctx->csys.imui_base + imui_percent_y;
|
||||||
} down_depend[h->num_objects];
|
|
||||||
|
|
||||||
// the root view size is always explicity
|
|
||||||
down_depend[0] = (struct boolpair) { false, false };
|
|
||||||
for (uint32_t i = 1; i < h->num_objects; i++) {
|
for (uint32_t i = 1; i < h->num_objects; i++) {
|
||||||
// printf ("%d %d %d [%d %d] [%d %d]\n", i, parent[i], h->childCount[i],
|
if (down_depend
|
||||||
// pos[i].x, pos[i].y, len[i].x, len[i].y);
|
&& (cont[i].semantic_x == IMUI_SizeKind_ChildrenSum
|
||||||
if (cont[i].semantic_x == IMUI_SizeKind_ChildrenSum) {
|
|| cont[i].semantic_x == IMUI_SizeKind_Expand)) {
|
||||||
down_depend[i].x = 1;
|
down_depend[i].x = true;
|
||||||
} else if (!(down_depend[i].x = down_depend[parent[i]].x)
|
} else if ((!down_depend
|
||||||
|
|| !(down_depend[i].x = down_depend[parent[i]].x))
|
||||||
&& cont[i].semantic_x == IMUI_SizeKind_PercentOfParent) {
|
&& cont[i].semantic_x == IMUI_SizeKind_PercentOfParent) {
|
||||||
int x = (len[parent[i]].x * 100) / 100; //FIXME precent
|
int *percent = Ent_GetComponent (ent[i], c_percent_x, reg);
|
||||||
modified[i] |= len[i].x != x;
|
int x = (len[parent[i]].x * *percent) / 100;
|
||||||
len[i].x = x;
|
len[i].x = x;
|
||||||
}
|
}
|
||||||
if (cont[i].semantic_y == IMUI_SizeKind_ChildrenSum) {
|
if (down_depend
|
||||||
down_depend[i].y = 1;
|
&& (cont[i].semantic_y == IMUI_SizeKind_ChildrenSum
|
||||||
} else if (!(down_depend[i].y = down_depend[parent[i]].y)
|
|| cont[i].semantic_y == IMUI_SizeKind_Expand)) {
|
||||||
|
down_depend[i].y = true;
|
||||||
|
} else if ((!down_depend
|
||||||
|
|| !(down_depend[i].y = down_depend[parent[i]].y))
|
||||||
&& cont[i].semantic_y == IMUI_SizeKind_PercentOfParent) {
|
&& cont[i].semantic_y == IMUI_SizeKind_PercentOfParent) {
|
||||||
int y = (len[parent[i]].y * 100) / 100; //FIXME precent
|
int *percent = Ent_GetComponent (ent[i], c_percent_y, reg);
|
||||||
modified[i] |= len[i].y != y;
|
int y = (len[parent[i]].y * *percent) / 100;
|
||||||
len[i].y = y;
|
len[i].y = y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calc_downwards_dependent (hierarchy_t *h)
|
||||||
|
{
|
||||||
|
view_pos_t *len = h->components[view_len];
|
||||||
|
viewcont_t *cont = h->components[view_control];
|
||||||
for (uint32_t i = h->num_objects; --i > 0; ) {
|
for (uint32_t i = h->num_objects; --i > 0; ) {
|
||||||
view_pos_t clen = len[i];
|
view_pos_t clen = len[i];
|
||||||
if (cont[i].semantic_x == IMUI_SizeKind_ChildrenSum) {
|
if (cont[i].semantic_x == IMUI_SizeKind_ChildrenSum
|
||||||
|
|| cont[i].semantic_x == IMUI_SizeKind_Expand) {
|
||||||
clen.x = 0;
|
clen.x = 0;
|
||||||
if (cont[i].vertical) {
|
if (cont[i].vertical) {
|
||||||
for (uint32_t j = 0; j < h->childCount[i]; j++) {
|
for (uint32_t j = 0; j < h->childCount[i]; j++) {
|
||||||
|
@ -310,7 +394,8 @@ layout_objects (imui_ctx_t *ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cont[i].semantic_y == IMUI_SizeKind_ChildrenSum) {
|
if (cont[i].semantic_y == IMUI_SizeKind_ChildrenSum
|
||||||
|
|| cont[i].semantic_y == IMUI_SizeKind_Expand) {
|
||||||
clen.y = 0;
|
clen.y = 0;
|
||||||
if (!cont[i].vertical) {
|
if (!cont[i].vertical) {
|
||||||
for (uint32_t j = 0; j < h->childCount[i]; j++) {
|
for (uint32_t j = 0; j < h->childCount[i]; j++) {
|
||||||
|
@ -324,9 +409,98 @@ layout_objects (imui_ctx_t *ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
modified[i] |= (len[i].x != clen.x) | (len[i].y != clen.y);
|
|
||||||
len[i] = clen;
|
len[i] = clen;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calc_expansions (imui_ctx_t *ctx, hierarchy_t *h)
|
||||||
|
{
|
||||||
|
auto reg = ctx->csys.reg;
|
||||||
|
|
||||||
|
uint32_t *ent = h->ent;
|
||||||
|
view_pos_t *len = h->components[view_len];
|
||||||
|
viewcont_t *cont = h->components[view_control];
|
||||||
|
uint32_t c_percent_x = ctx->csys.imui_base + imui_percent_x;
|
||||||
|
uint32_t c_percent_y = ctx->csys.imui_base + imui_percent_y;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < h->num_objects; i++) {
|
||||||
|
view_pos_t tlen = {};
|
||||||
|
view_pos_t elen = {};
|
||||||
|
view_pos_t ecount = {};
|
||||||
|
for (uint32_t j = 0; j < h->childCount[i]; j++) {
|
||||||
|
uint32_t child = h->childIndex[i] + j;
|
||||||
|
tlen.x += len[child].x;
|
||||||
|
tlen.y += len[child].y;
|
||||||
|
if (cont[child].semantic_x == IMUI_SizeKind_Expand) {
|
||||||
|
int *p = Ent_GetComponent (ent[child], c_percent_x, reg);
|
||||||
|
elen.x += *p;
|
||||||
|
ecount.x++;
|
||||||
|
}
|
||||||
|
if (cont[child].semantic_y == IMUI_SizeKind_Expand) {
|
||||||
|
int *p = Ent_GetComponent (ent[child], c_percent_y, reg);
|
||||||
|
elen.y += *p;
|
||||||
|
ecount.y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// printf ("i:%d t:[%d %d] e:[%d %d] ec:[%d %d]\n", i, tlen.x, tlen.y,
|
||||||
|
// elen.x, elen.y, ecount.x, ecount.y);
|
||||||
|
for (uint32_t j = 0; ecount.x && j < h->childCount[i]; j++) {
|
||||||
|
uint32_t child = h->childIndex[i] + j;
|
||||||
|
if (cont[child].semantic_x != IMUI_SizeKind_Expand) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cont[i].vertical) {
|
||||||
|
len[child].x = len[i].x;
|
||||||
|
// printf ("xc:%d p:%d l:%d\n", child, len[i].x, len[child].x);
|
||||||
|
} else {
|
||||||
|
uint32_t space = len[i].x - tlen.x;
|
||||||
|
int *p = Ent_GetComponent (ent[child], c_percent_x, reg);
|
||||||
|
len[child].x += *p * space / elen.x;
|
||||||
|
// printf ("xc:%d p:%d s:%d e:%d: l:%d\n", child, *p, space,
|
||||||
|
// elen.x, len[child].x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (uint32_t j = 0; ecount.y && j < h->childCount[i]; j++) {
|
||||||
|
uint32_t child = h->childIndex[i] + j;
|
||||||
|
if (cont[child].semantic_y != IMUI_SizeKind_Expand) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cont[i].vertical) {
|
||||||
|
uint32_t space = len[i].y - tlen.y;
|
||||||
|
int *p = Ent_GetComponent (ent[child], c_percent_y, reg);
|
||||||
|
len[child].y += *p * space / elen.y;
|
||||||
|
// printf ("yc:%d p:%d s:%d e:%d: l:%d\n", child, *p, space,
|
||||||
|
// elen.y, len[child].y);
|
||||||
|
} else {
|
||||||
|
len[child].y = len[i].y;
|
||||||
|
// printf ("yc:%d p:%d l:%d\n", child, len[i].y, len[child].y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//FIXME currently works properly only for grav_northwest
|
||||||
|
static void
|
||||||
|
layout_objects (imui_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
auto ref = View_GetRef (ctx->root_view);
|
||||||
|
auto h = ref->hierarchy;
|
||||||
|
|
||||||
|
view_pos_t *pos = h->components[view_pos];
|
||||||
|
view_pos_t *len = h->components[view_len];
|
||||||
|
viewcont_t *cont = h->components[view_control];
|
||||||
|
uint32_t *parent = h->parentIndex;
|
||||||
|
boolpair_t down_depend[h->num_objects];
|
||||||
|
|
||||||
|
// the root view size is always explicit
|
||||||
|
down_depend[0] = (boolpair_t) { false, false };
|
||||||
|
calc_upwards_dependent (ctx, h, down_depend);
|
||||||
|
calc_downwards_dependent (h);
|
||||||
|
calc_expansions (ctx, h);
|
||||||
|
//dump_tree (h, 0, 0, ctx);
|
||||||
|
// resolve conflicts
|
||||||
|
//fflush (stdout);
|
||||||
|
|
||||||
view_pos_t cpos = {};
|
view_pos_t cpos = {};
|
||||||
uint32_t cur_parent = 0;
|
uint32_t cur_parent = 0;
|
||||||
|
@ -337,13 +511,10 @@ layout_objects (imui_ctx_t *ctx)
|
||||||
}
|
}
|
||||||
if (cont[i].semantic_x != IMUI_SizeKind_Null
|
if (cont[i].semantic_x != IMUI_SizeKind_Null
|
||||||
&& cont[i].semantic_y != IMUI_SizeKind_Null) {
|
&& cont[i].semantic_y != IMUI_SizeKind_Null) {
|
||||||
modified[i] |= (pos[i].x != cpos.x) | (pos[i].y != cpos.y);
|
|
||||||
pos[i] = cpos;
|
pos[i] = cpos;
|
||||||
} else if (cont[i].semantic_x != IMUI_SizeKind_Null) {
|
} else if (cont[i].semantic_x != IMUI_SizeKind_Null) {
|
||||||
modified[i] |= pos[i].x != cpos.x;
|
|
||||||
pos[i].x = cpos.x;
|
pos[i].x = cpos.x;
|
||||||
} else if (cont[i].semantic_y != IMUI_SizeKind_Null) {
|
} else if (cont[i].semantic_y != IMUI_SizeKind_Null) {
|
||||||
modified[i] |= pos[i].y != cpos.y;
|
|
||||||
pos[i].y = cpos.y;
|
pos[i].y = cpos.y;
|
||||||
}
|
}
|
||||||
if (cont[parent[i]].vertical) {
|
if (cont[parent[i]].vertical) {
|
||||||
|
@ -397,14 +568,25 @@ void
|
||||||
IMUI_PushLayout (imui_ctx_t *ctx, bool vertical)
|
IMUI_PushLayout (imui_ctx_t *ctx, bool vertical)
|
||||||
{
|
{
|
||||||
DARRAY_APPEND (&ctx->parent_stack, ctx->current_parent);
|
DARRAY_APPEND (&ctx->parent_stack, ctx->current_parent);
|
||||||
ctx->current_parent = View_New (ctx->vsys, ctx->current_parent);
|
auto view = View_New (ctx->vsys, ctx->current_parent);
|
||||||
*View_Control (ctx->current_parent) = (viewcont_t) {
|
auto pcont = View_Control (ctx->current_parent);
|
||||||
|
ctx->current_parent = view;
|
||||||
|
auto x_size = pcont->vertical ? IMUI_SizeKind_Expand
|
||||||
|
: IMUI_SizeKind_ChildrenSum;
|
||||||
|
auto y_size = pcont->vertical ? IMUI_SizeKind_ChildrenSum
|
||||||
|
: IMUI_SizeKind_Expand;
|
||||||
|
*View_Control (view) = (viewcont_t) {
|
||||||
.gravity = grav_northwest,
|
.gravity = grav_northwest,
|
||||||
.visible = 1,
|
.visible = 1,
|
||||||
.semantic_x = IMUI_SizeKind_ChildrenSum,
|
.semantic_x = x_size,
|
||||||
.semantic_y = IMUI_SizeKind_ChildrenSum,
|
.semantic_y = y_size,
|
||||||
.vertical = vertical,
|
.vertical = vertical,
|
||||||
};
|
};
|
||||||
|
View_SetLen (view, 0, 0);
|
||||||
|
uint32_t c_percent_x = ctx->csys.imui_base + imui_percent_x;
|
||||||
|
uint32_t c_percent_y = ctx->csys.imui_base + imui_percent_y;
|
||||||
|
*(int*) Ent_AddComponent (view.id, c_percent_x, ctx->csys.reg) = 100;
|
||||||
|
*(int*) Ent_AddComponent (view.id, c_percent_y, ctx->csys.reg) = 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -542,6 +724,8 @@ IMUI_Checkbox (imui_ctx_t *ctx, bool *flag, const char *label)
|
||||||
auto text = View_New (ctx->vsys, view);
|
auto text = View_New (ctx->vsys, view);
|
||||||
set_control (ctx, text, false);
|
set_control (ctx, text, false);
|
||||||
add_text (text, state, ctx);
|
add_text (text, state, ctx);
|
||||||
|
auto c = View_GetChild (text, 0);
|
||||||
|
*(uint32_t *)Ent_AddComponent (c.id, ctx->tsys.text_base + text_color, c.reg) = 0xfb;
|
||||||
|
|
||||||
if (check_button_state (ctx, state->entity)) {
|
if (check_button_state (ctx, state->entity)) {
|
||||||
*flag = !*flag;
|
*flag = !*flag;
|
||||||
|
@ -591,3 +775,20 @@ IMUI_Slider (imui_ctx_t *ctx, float *value, float minval, float maxval,
|
||||||
const char *label)
|
const char *label)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMUI_FlexibleSpace (imui_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
auto view = View_New (ctx->vsys, ctx->current_parent);
|
||||||
|
View_SetLen (ctx->current_parent, 0, 0);
|
||||||
|
|
||||||
|
set_control (ctx, view, false);
|
||||||
|
View_Control (view)->semantic_x = IMUI_SizeKind_Expand;
|
||||||
|
View_Control (view)->semantic_y = IMUI_SizeKind_Expand;
|
||||||
|
uint32_t c_percent_x = ctx->csys.imui_base + imui_percent_x;
|
||||||
|
uint32_t c_percent_y = ctx->csys.imui_base + imui_percent_y;
|
||||||
|
*(int*) Ent_AddComponent (view.id, c_percent_x, ctx->csys.reg) = 100;
|
||||||
|
*(int*) Ent_AddComponent (view.id, c_percent_y, ctx->csys.reg) = 100;
|
||||||
|
|
||||||
|
set_fill (ctx, view, 0xfb);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue