[ui] Get flowed views working with ECS

I'm not particularly happy with the way onresize is handled, but at this
stage a better way of dealing with resizing views and getting the child
views to flow correctly hasn't come to mind. However, the system should
at least be usable.
This commit is contained in:
Bill Currie 2022-11-04 00:29:13 +09:00
parent bdbb8f1e0b
commit 6b99697e82
5 changed files with 307 additions and 372 deletions

View File

@ -127,6 +127,15 @@ view_t View_New (ecs_registry_t *reg, view_t parent);
void View_SetParent (view_t view, view_t parent);
void View_UpdateHierarchy (view_t view);
void view_flow_right_down (view_t view, view_pos_t len);
void view_flow_right_up (view_t view, view_pos_t len);
void view_flow_left_down (view_t view, view_pos_t len);
void view_flow_left_up (view_t view, view_pos_t len);
void view_flow_down_right (view_t view, view_pos_t len);
void view_flow_up_right (view_t view, view_pos_t len);
void view_flow_down_left (view_t view, view_pos_t len);
void view_flow_up_left (view_t view, view_pos_t len);
VIEWINLINE hierref_t *View_GetRef (view_t view);
VIEWINLINE int View_Valid (view_t view);
@ -140,6 +149,7 @@ VIEWINLINE view_pos_t View_GetAbs (view_t view);
VIEWINLINE view_pos_t View_GetRel (view_t view);
VIEWINLINE void View_SetLen (view_t view, int x, int y);
VIEWINLINE view_pos_t View_GetLen (view_t view);
VIEWINLINE viewcont_t* View_Control (view_t view);
VIEWINLINE void View_SetGravity (view_t view, grav_t grav);
VIEWINLINE grav_t View_GetGravity (view_t view);
VIEWINLINE void View_SetVisible (view_t view, int visible);
@ -279,6 +289,16 @@ View_GetLen (view_t view)
return len[ref->index];
}
VIEWINLINE
viewcont_t *
View_Control (view_t view)
{
__auto_type ref = View_GetRef (view);
hierarchy_t *h = ref->hierarchy;
viewcont_t *cont = h->components[view_control];
return &cont[ref->index];
}
VIEWINLINE
void
View_SetGravity (view_t view, grav_t grav)

View File

@ -1,13 +1,11 @@
libs_ui_tests = \
libs/ui/test/test-flow \
libs/ui/test/test-flow-size \
libs/ui/test/test-passage \
libs/ui/test/test-txtbuffer \
libs/ui/test/test-vrect
libs_ui_xfail_tests = \
libs/ui/test/test-flow \
libs/ui/test/test-flow-size
TESTS += $(libs_ui_tests) $(libs_ui_xfail_tests)
TESTS += $(libs_ui_tests)
XFAIL_TESTS += $(libs_ui_xfail_tests)

View File

@ -4,7 +4,21 @@
#include <stdio.h>
#include "QF/ui/view.h"
#if 0
static ecs_registry_t *test_reg;
enum {
test_href,
};
static const component_t test_components[] = {
[test_href] = {
.size = sizeof (hierref_t),
.create = 0,//create_href,
.name = "href",
},
};
typedef struct {
struct {
int xlen, ylen;
@ -194,50 +208,66 @@ static testdata_t up_left_views[] = {
#define up_left_count array_size(up_left_views)
static void
print_view (view_t *view)
print_view (view_t view)
{
view_t parent = View_GetParent (view);
view_pos_t pos = View_GetPos (view);
view_pos_t len = View_GetLen (view);
view_pos_t rel = View_GetRel (view);
view_pos_t abs = View_GetAbs (view);
printf ("%s[%3d %3d %3d %3d %3d %3d %3d %3d]\n",
view->parent ? " " : "****",
view->xpos, view->ypos, view->xlen, view->ylen,
view->xrel, view->yrel, view->xabs, view->yabs);
view_draw (view);
View_Valid (parent) ? " " : "****",
pos.x, pos.y, len.x, len.y, rel.x, rel.y, abs.x, abs.y);
}
static int
test_flow (testdata_t *child_views, int count, void (*flow) (view_t *))
test_flow (testdata_t *child_views, int count, void (flow) (view_t, view_pos_t))
{
view_t *flow_view = view_new (0, 0, 256, 256, grav_northwest);
flow_view->setgeometry = flow;
flow_view->flow_size = 1;
flow_view->draw = print_view;
view_t flow_view = View_New (test_reg, nullview);
View_SetPos (flow_view, 0, 0);
View_SetLen (flow_view, 256, 256);
View_SetGravity (flow_view, grav_northwest);
View_SetOnResize (flow_view, flow);
View_Control (flow_view)->flow_size = 1;
for (int i = 0; i < count; i++) {
testdata_t *td = &child_views[i];
view_t *child = view_new (0, 0, td->xlen, td->ylen, grav_flow);
child->bol_suppress = td->bol_suppress;
child->draw = print_view;
view_add (flow_view, child);
view_t child = View_New (test_reg, flow_view);
View_SetPos (child, 0, 0);
View_SetLen (child, td->xlen, td->ylen);
View_SetGravity (child, grav_flow);
View_Control (child)->bol_suppress = td->bol_suppress;
}
view_move (flow_view, 8, 16);
int ret = 0;
View_SetPos (flow_view, 8, 16);
View_UpdateHierarchy (flow_view);
for (int i = 0; i < flow_view->num_children; i++) {
int ret = 0;
__auto_type ref = View_GetRef (flow_view);
hierarchy_t *h = ref->hierarchy;
uint32_t *childIndex = h->childIndex;
uint32_t *childCount = h->childCount;
uint32_t *ent = h->ent;
view_pos_t *pos = h->components[view_pos];
view_pos_t *rel = h->components[view_rel];
view_pos_t *abs = h->components[view_abs];
for (uint32_t i = 0; i < childCount[ref->index]; i++) {
testdata_t *td = &child_views[i];
view_t *child = flow_view->children[i];
if (child->xpos != td->expect.xpos
|| child->ypos != td->expect.ypos
|| child->xrel != td->expect.xrel
|| child->yrel != td->expect.yrel
|| child->xabs != td->expect.xabs
|| child->yabs != td->expect.yabs) {
uint32_t child = childIndex[ref->index] + i;
if (pos[child].x != td->expect.xpos
|| pos[child].y != td->expect.ypos
|| rel[child].x != td->expect.xrel
|| rel[child].y != td->expect.yrel
|| abs[child].x != td->expect.xabs
|| abs[child].y != td->expect.yabs) {
ret = 1;
printf ("child %d misflowed:\n"
" [%3d %3d %3d %3d %3d %3d]\n", i,
td->expect.xpos, td->expect.ypos,
td->expect.xrel, td->expect.yrel,
td->expect.xabs, td->expect.yabs);
print_view (child);
print_view ((view_t) { .reg = test_reg, .id = ent[child],
.comp = flow_view.comp});
}
}
return ret;
@ -248,6 +278,10 @@ main (void)
{
int ret = 0;
test_reg = ECS_NewRegistry ();
ECS_RegisterComponents (test_reg, test_components, 1);
test_reg->href_comp = test_href;
if (test_flow (right_down_views, right_down_count, view_flow_right_down)) {
printf ("right-down failed\n");
ret = 1;
@ -283,11 +317,3 @@ main (void)
}
return ret;
}
#endif
int
main (void)
{
printf ("FIXME: redo for ECS\n");
return 1;
}

View File

@ -4,7 +4,21 @@
#include <stdio.h>
#include "QF/ui/view.h"
#if 0
static ecs_registry_t *test_reg;
enum {
test_href,
};
static const component_t test_components[] = {
[test_href] = {
.size = sizeof (hierref_t),
.create = 0,//create_href,
.name = "href",
},
};
typedef struct {
struct {
int xlen, ylen;
@ -194,49 +208,66 @@ static testdata_t up_left_views[] = {
#define up_left_count array_size(up_left_views)
static void
print_view (view_t *view)
print_view (view_t view)
{
view_t parent = View_GetParent (view);
view_pos_t pos = View_GetPos (view);
view_pos_t len = View_GetLen (view);
view_pos_t rel = View_GetRel (view);
view_pos_t abs = View_GetAbs (view);
printf ("%s[%3d %3d %3d %3d %3d %3d %3d %3d]\n",
view->parent ? " " : "****",
view->xpos, view->ypos, view->xlen, view->ylen,
view->xrel, view->yrel, view->xabs, view->yabs);
view_draw (view);
View_Valid (parent) ? " " : "****",
pos.x, pos.y, len.x, len.y, rel.x, rel.y, abs.x, abs.y);
}
static int
test_flow (testdata_t *child_views, int count, void (*flow) (view_t *))
test_flow (testdata_t *child_views, int count,
void (*flow) (view_t, view_pos_t))
{
view_t *flow_view = view_new (0, 0, 256, 256, grav_northwest);
flow_view->setgeometry = flow;
flow_view->draw = print_view;
view_t flow_view = View_New (test_reg, nullview);
View_SetPos (flow_view, 0, 0);
View_SetLen (flow_view, 256, 256);
View_SetGravity (flow_view, grav_northwest);
View_SetOnResize (flow_view, flow);
for (int i = 0; i < count; i++) {
testdata_t *td = &child_views[i];
view_t *child = view_new (0, 0, td->xlen, td->ylen, grav_flow);
child->bol_suppress = td->bol_suppress;
child->draw = print_view;
view_add (flow_view, child);
view_t child = View_New (test_reg, flow_view);
View_SetPos (child, 0, 0);
View_SetLen (child, td->xlen, td->ylen);
View_SetGravity (child, grav_flow);
View_Control (child)->bol_suppress = td->bol_suppress;
}
view_move (flow_view, 8, 16);
int ret = 0;
View_SetPos (flow_view, 8, 16);
View_UpdateHierarchy (flow_view);
for (int i = 0; i < flow_view->num_children; i++) {
int ret = 0;
__auto_type ref = View_GetRef (flow_view);
hierarchy_t *h = ref->hierarchy;
uint32_t *childIndex = h->childIndex;
uint32_t *childCount = h->childCount;
uint32_t *ent = h->ent;
view_pos_t *pos = h->components[view_pos];
view_pos_t *rel = h->components[view_rel];
view_pos_t *abs = h->components[view_abs];
for (uint32_t i = 0; i < childCount[ref->index]; i++) {
testdata_t *td = &child_views[i];
view_t *child = flow_view->children[i];
if (child->xpos != td->expect.xpos
|| child->ypos != td->expect.ypos
|| child->xrel != td->expect.xrel
|| child->yrel != td->expect.yrel
|| child->xabs != td->expect.xabs
|| child->yabs != td->expect.yabs) {
uint32_t child = childIndex[ref->index] + i;
if (pos[child].x != td->expect.xpos
|| pos[child].y != td->expect.ypos
|| rel[child].x != td->expect.xrel
|| rel[child].y != td->expect.yrel
|| abs[child].x != td->expect.xabs
|| abs[child].y != td->expect.yabs) {
ret = 1;
printf ("child %d misflowed:\n"
" [%3d %3d %3d %3d %3d %3d]\n", i,
td->expect.xpos, td->expect.ypos,
td->expect.xrel, td->expect.yrel,
td->expect.xabs, td->expect.yabs);
print_view (child);
print_view ((view_t) { .reg = test_reg, .id = ent[child],
.comp = flow_view.comp});
}
}
return ret;
@ -247,6 +278,10 @@ main (void)
{
int ret = 0;
test_reg = ECS_NewRegistry ();
ECS_RegisterComponents (test_reg, test_components, 1);
test_reg->href_comp = test_href;
if (test_flow (right_down_views, right_down_count, view_flow_right_down)) {
printf ("right-down failed\n");
ret = 1;
@ -282,11 +317,3 @@ main (void)
}
return ret;
}
#endif
int
main (void)
{
printf ("FIXME: redo for ECS\n");
return 1;
}

View File

@ -173,10 +173,17 @@ View_UpdateHierarchy (view_t view)
uint32_t *id = h->ent;
if (abs[0].x != pos[0].x || abs[0].y != pos[0].y) {
modified[0] = 1;
modified[0] |= 1;
abs[0] = pos[0];
rel[0] = pos[0];
}
if (oldlen[0].x != len[0].x || oldlen[0].y != len[0].y) {
modified[0] |= 2;
if (onresize[0]) {
view_t v = { .reg = view.reg, .id = id[0], .comp = view.comp };
onresize[0] (v, len[0]);
}
}
for (uint32_t i = 1; i < h->num_objects; i++) {
uint32_t par = parent[i];
if (!(modified[i] & 2) && (modified[par] & 2)
@ -191,6 +198,11 @@ View_UpdateHierarchy (view_t view)
if (cont[i].resize_y) {
len[i].y += dy;
}
if (onresize[i]) {
view_t v = { .reg = view.reg, .id = id[i],
.comp = view.comp };
onresize[i] (v, len[i]);
}
}
if (modified[i] || modified[par]) {
modified[i] |= 1; // propogate motion modifications
@ -239,16 +251,12 @@ View_UpdateHierarchy (view_t view)
}
}
for (uint32_t i = 0; i < h->num_objects; i++) {
if ((modified[i] & 2) && onresize[i]) {
view_t v = { .reg = view.reg, .id = id[i], .comp = view.comp };
onresize[i] (v, len[i]);
}
if (modified[i] & 2) {
oldlen[i] = len[i];
}
if ((modified[i] & 1) && onmove[i]) {
view_t v = { .reg = view.reg, .id = id[i], .comp = view.comp };
onresize[i] (v, abs[i]);
onmove[i] (v, abs[i]);
}
modified[i] = 0;
}
@ -289,213 +297,6 @@ View_SetParent (view_t view, view_t parent)
modified[ref->index] = 1;
View_UpdateHierarchy (view);
}
#if 0
static void
setgeometry (view_t *view)
{
int i;
view_t *par = view->parent;
if (!par) {
view->xabs = view->xrel = view->xpos;
view->yabs = view->yrel = view->ypos;
if (view->setgeometry)
view->setgeometry (view);
for (i = 0; i < view->num_children; i++)
setgeometry (view->children[i]);
return;
}
switch (view->gravity) {
case grav_center:
view->xrel = view->xpos + (par->xlen - view->xlen) / 2;
view->yrel = view->ypos + (par->ylen - view->ylen) / 2;
break;
case grav_north:
view->xrel = view->xpos + (par->xlen - view->xlen) / 2;
view->yrel = view->ypos;
break;
case grav_northeast:
view->xrel = par->xlen - view->xpos - view->xlen;
view->yrel = view->ypos;
break;
case grav_east:
view->xrel = par->xlen - view->xpos - view->xlen;
view->yrel = view->ypos + (par->ylen - view->ylen) / 2;
break;
case grav_southeast:
view->xrel = par->xlen - view->xpos - view->xlen;
view->yrel = par->ylen - view->ypos - view->ylen;
break;
case grav_south:
view->xrel = view->xpos + (par->xlen - view->xlen) / 2;
view->yrel = par->ylen - view->ypos - view->ylen;
break;
case grav_southwest:
view->xrel = view->xpos;
view->yrel = par->ylen - view->ypos - view->ylen;
break;
case grav_west:
view->xrel = view->xpos;
view->yrel = view->ypos + (par->ylen - view->ylen) / 2;
break;
case grav_northwest:
view->xrel = view->xpos;
view->yrel = view->ypos;
break;
case grav_flow:
break;
}
view->xabs = par->xabs + view->xrel;
view->yabs = par->yabs + view->yrel;
if (view->setgeometry)
view->setgeometry (view);
for (i = 0; i < view->num_children; i++)
setgeometry (view->children[i]);
}
VISIBLE view_t *
view_new_data (int xp, int yp, int xl, int yl, grav_t grav, void *data)
{
view_t *view = calloc (1, sizeof (view_t));
view->xpos = xp;
view->ypos = yp;
view->xlen = xl;
view->ylen = yl;
view->gravity = grav;
view->visible = 1;
view->draw = view_draw;
view->data = data;
setgeometry (view);
return view;
}
VISIBLE view_t *
view_new (int xp, int yp, int xl, int yl, grav_t grav)
{
return view_new_data (xp, yp, xl, yl, grav, 0);
}
VISIBLE void
view_insert (view_t *par, view_t *view, int pos)
{
view->parent = par;
if (pos < 0)
pos = par->num_children + 1 + pos;
if (pos < 0)
pos = 0;
if (pos > par->num_children)
pos = par->num_children;
if (par->num_children == par->max_children) {
par->max_children += 8;
par->children = realloc (par->children,
par->max_children * sizeof (view_t *));
memset (par->children + par->num_children, 0,
(par->max_children - par->num_children) * sizeof (view_t *));
}
memmove (par->children + pos + 1, par->children + pos,
(par->num_children - pos) * sizeof (view_t *));
par->num_children++;
par->children[pos] = view;
setgeometry (view);
}
VISIBLE void
view_add (view_t *par, view_t *view)
{
view_insert (par, view, -1);
}
VISIBLE void
view_remove (view_t *par, view_t *view)
{
int i;
for (i = 0; i < par->num_children; i++) {
if (par->children[i] == view) {
memmove (par->children + i, par->children + i + 1,
(par->num_children - i - 1) * sizeof (view_t *));
par->children [--par->num_children] = 0;
break;
}
}
}
VISIBLE void
view_delete (view_t *view)
{
if (view->parent)
view_remove (view->parent, view);
while (view->num_children)
view_delete (view->children[0]);
free (view->children);
free (view);
}
VISIBLE void
view_draw (view_t *view)
{
int i;
for (i = 0; i < view->num_children; i++) {
view_t *v = view->children[i];
if (v->visible && v->draw)
v->draw (v);
}
}
static void
_resize (view_t *view, int xl, int yl)
{
int i, xd, yd;
xd = xl - view->xlen;
yd = yl - view->ylen;
view->xlen = xl;
view->ylen = yl;
for (i = 0; i < view->num_children; i++) {
view_t *v = view->children[i];
if (v->resize_x && v->resize_y) {
_resize (v, v->xlen + xd, v->ylen + yd);
} else if (v->resize_x) {
_resize (v, v->xlen + xd, v->ylen);
} else if (v->resize_y) {
_resize (v, v->xlen, v->ylen + yd);
}
}
}
VISIBLE void
view_resize (view_t *view, int xl, int yl)
{
_resize (view, xl, yl);
setgeometry (view);
}
VISIBLE void
view_move (view_t *view, int xp, int yp)
{
view->xpos = xp;
view->ypos = yp;
setgeometry (view);
}
VISIBLE void
view_setgeometry (view_t *view, int xp, int yp, int xl, int yl)
{
view->xpos = xp;
view->ypos = yp;
_resize (view, xl, yl);
setgeometry (view);
}
VISIBLE void
view_setgravity (view_t *view, grav_t grav)
{
view->gravity = grav;
setgeometry (view);
}
typedef struct flowline_s {
struct flowline_s *next;
@ -514,224 +315,287 @@ typedef struct flowline_s {
} while (0)
static void
flow_right (view_t *view, void (*set_rows) (view_t *, flowline_t *))
flow_right (view_t view, void (*set_rows) (view_t, flowline_t *))
{
flowline_t flowline = {};
__auto_type ref = View_GetRef (view);
hierarchy_t *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 vind = ref->index;
flowline_t flowline = { .first_child = h->childIndex[ref->index] };
flowline_t *line = &flowline;
for (int i = 0; i < view->num_children; i++) {
view_t *child = view->children[i];
if (line->cursor && line->cursor + child->xlen > view->xlen) {
NEXT_LINE(line, i);
for (uint32_t i = 0; i < h->childCount[vind]; i++) {
uint32_t child = h->childIndex[vind] + i;
if (line->cursor && line->cursor + len[child].x > len[vind].x) {
NEXT_LINE(line, child);
}
child->xpos = line->cursor;
if (child->xpos || !child->bol_suppress) {
line->cursor += child->xlen;
pos[child].x = line->cursor;
if (pos[child].x || !cont[child].bol_suppress) {
line->cursor += len[child].x;
}
line->height = max (child->ylen, line->height);
line->height = max (len[child].y, line->height);
line->child_count++;
}
set_rows (view, &flowline);
}
static void
flow_left (view_t *view, void (*set_rows) (view_t *, flowline_t *))
flow_left (view_t view, void (*set_rows) (view_t, flowline_t *))
{
flowline_t flowline = {};
__auto_type ref = View_GetRef (view);
hierarchy_t *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 vind = ref->index;
flowline_t flowline = { .first_child = h->childIndex[ref->index] };
flowline_t *line = &flowline;
line->cursor = view->xlen;
for (int i = 0; i < view->num_children; i++) {
view_t *child = view->children[i];
if (line->cursor < view->xlen && line->cursor - child->xlen < 0) {
NEXT_LINE(line, i);
line->cursor = view->xlen;
line->cursor = len[vind].x;
for (uint32_t i = 0; i < h->childCount[vind]; i++) {
uint32_t child = h->childIndex[ref->index] + i;
if (line->cursor < len[vind].x && line->cursor - len[child].x < 0) {
NEXT_LINE(line, child);
line->cursor = len[vind].x;
}
if (child->xpos < view->xlen || !child->bol_suppress) {
line->cursor -= child->xlen;
if (pos[child].x < len[vind].x || !cont[child].bol_suppress) {
line->cursor -= len[child].x;
}
child->xpos = line->cursor;
line->height = max (child->ylen, line->height);
pos[child].x = line->cursor;
line->height = max (len[child].y, line->height);
line->child_count++;
}
set_rows (view, &flowline);
}
static void
flow_down (view_t *view, void (*set_rows) (view_t *, flowline_t *))
flow_down (view_t view, void (*set_rows) (view_t, flowline_t *))
{
flowline_t flowline = {};
__auto_type ref = View_GetRef (view);
hierarchy_t *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 vind = ref->index;
flowline_t flowline = { .first_child = h->childIndex[ref->index] };
flowline_t *line = &flowline;
for (int i = 0; i < view->num_children; i++) {
view_t *child = view->children[i];
if (line->cursor && line->cursor + child->ylen > view->ylen) {
NEXT_LINE(line, i);
for (uint32_t i = 0; i < h->childCount[vind]; i++) {
uint32_t child = h->childIndex[vind] + i;
if (line->cursor && line->cursor + len[child].y > len[vind].y) {
NEXT_LINE(line, child);
}
child->ypos = line->cursor;
if (child->ypos || !child->bol_suppress) {
line->cursor += child->ylen;
pos[child].y = line->cursor;
if (pos[child].y || !cont[child].bol_suppress) {
line->cursor += len[child].y;
}
line->height = max (child->xlen, line->height);
line->height = max (len[child].x, line->height);
line->child_count++;
}
set_rows (view, &flowline);
}
static void
flow_up (view_t *view, void (*set_rows) (view_t *, flowline_t *))
flow_up (view_t view, void (*set_rows) (view_t, flowline_t *))
{
flowline_t flowline = {};
__auto_type ref = View_GetRef (view);
hierarchy_t *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 vind = ref->index;
flowline_t flowline = { .first_child = h->childIndex[ref->index] };
flowline_t *line = &flowline;
line->cursor = view->ylen;
for (int i = 0; i < view->num_children; i++) {
view_t *child = view->children[i];
if (line->cursor < view->ylen && line->cursor - child->ylen < 0) {
NEXT_LINE(line, i);
line->cursor = view->ylen;
line->cursor = len[vind].y;
for (uint32_t i = 0; i < h->childCount[vind]; i++) {
uint32_t child = h->childIndex[ref->index] + i;
if (line->cursor < len[vind].y && line->cursor - len[child].y < 0) {
NEXT_LINE(line, child);
line->cursor = len[vind].y;
}
if (child->ypos < view->ylen || !child->bol_suppress) {
line->cursor -= child->ylen;
if (pos[child].y < len[vind].y || !cont[child].bol_suppress) {
line->cursor -= len[child].y;
}
child->ypos = line->cursor;
line->height = max (child->xlen, line->height);
pos[child].y = line->cursor;
line->height = max (len[child].x, line->height);
line->child_count++;
}
set_rows (view, &flowline);
}
static void
flow_view_height (view_t *view, flowline_t *flowlines)
flow_view_height (view_pos_t *len, flowline_t *flowlines)
{
if (view->flow_size) {
view->ylen = 0;
for (flowline_t *line = flowlines; line; line = line->next) {
view->ylen += line->height;
}
len->y = 0;
for (flowline_t *line = flowlines; line; line = line->next) {
len->y += line->height;
}
}
static void
flow_view_width (view_t *view, flowline_t *flowlines)
flow_view_width (view_pos_t *len, flowline_t *flowlines)
{
if (view->flow_size) {
view->xlen = 0;
for (flowline_t *line = flowlines; line; line = line->next) {
view->xlen += line->height;
}
len->x = 0;
for (flowline_t *line = flowlines; line; line = line->next) {
len->x += line->height;
}
}
static void
set_rows_down (view_t *view, flowline_t *flowlines)
set_rows_down (view_t view, flowline_t *flowlines)
{
flow_view_height (view, flowlines);
__auto_type ref = View_GetRef (view);
hierarchy_t *h = ref->hierarchy;
view_pos_t *pos = h->components[view_pos];
view_pos_t *rel = h->components[view_rel];
view_pos_t *len = h->components[view_len];
viewcont_t *cont = h->components[view_control];
uint32_t vind = ref->index;
if (cont[vind].flow_size) {
flow_view_height (&len[ref->index], flowlines);
}
int cursor = 0;
for (flowline_t *line = flowlines; line; line = line->next) {
cursor += line->height;
for (int i = 0; i < line->child_count; i++) {
view_t *child = view->children[line->first_child + i];
uint32_t child = line->first_child + i;
child->xrel = child->xpos;
child->yrel = cursor + child->ypos - child->ylen;
rel[child].x = pos[child].x;
rel[child].y = cursor + pos[child].y - len[child].y;
}
}
}
static void
set_rows_up (view_t *view, flowline_t *flowlines)
set_rows_up (view_t view, flowline_t *flowlines)
{
flow_view_height (view, flowlines);
__auto_type ref = View_GetRef (view);
hierarchy_t *h = ref->hierarchy;
view_pos_t *pos = h->components[view_pos];
view_pos_t *rel = h->components[view_rel];
view_pos_t *len = h->components[view_len];
viewcont_t *cont = h->components[view_control];
uint32_t vind = ref->index;
int cursor = view->ylen;
if (cont[vind].flow_size) {
flow_view_height (&len[ref->index], flowlines);
}
int cursor = len[vind].y;
for (flowline_t *line = flowlines; line; line = line->next) {
for (int i = 0; i < line->child_count; i++) {
view_t *child = view->children[line->first_child + i];
uint32_t child = line->first_child + i;
child->xrel = child->xpos;
child->yrel = cursor + child->ypos - child->ylen;
rel[child].x = pos[child].x;
rel[child].y = cursor + pos[child].y - len[child].y;
}
cursor -= line->height;
}
}
static void
set_columns_right (view_t *view, flowline_t *flowlines)
set_columns_right (view_t view, flowline_t *flowlines)
{
flow_view_width (view, flowlines);
__auto_type ref = View_GetRef (view);
hierarchy_t *h = ref->hierarchy;
view_pos_t *pos = h->components[view_pos];
view_pos_t *rel = h->components[view_rel];
view_pos_t *len = h->components[view_len];
viewcont_t *cont = h->components[view_control];
uint32_t vind = ref->index;
if (cont[vind].flow_size) {
flow_view_width (&len[ref->index], flowlines);
}
int cursor = 0;
for (flowline_t *line = flowlines; line; line = line->next) {
for (int i = 0; i < line->child_count; i++) {
view_t *child = view->children[line->first_child + i];
uint32_t child = line->first_child + i;
child->xrel = cursor + child->xpos;
child->yrel = child->ypos;
rel[child].x = cursor + pos[child].x;
rel[child].y = pos[child].y;
}
cursor += line->height;
}
}
static void
set_columns_left (view_t *view, flowline_t *flowlines)
set_columns_left (view_t view, flowline_t *flowlines)
{
flow_view_width (view, flowlines);
__auto_type ref = View_GetRef (view);
hierarchy_t *h = ref->hierarchy;
view_pos_t *pos = h->components[view_pos];
view_pos_t *rel = h->components[view_rel];
view_pos_t *len = h->components[view_len];
viewcont_t *cont = h->components[view_control];
uint32_t vind = ref->index;
int cursor = view->xlen;
if (cont[vind].flow_size) {
flow_view_width (&len[ref->index], flowlines);
}
int cursor = len[vind].x;
for (flowline_t *line = flowlines; line; line = line->next) {
cursor -= line->height;
for (int i = 0; i < line->child_count; i++) {
view_t *child = view->children[line->first_child + i];
uint32_t child = line->first_child + i;
child->xrel = cursor + child->xpos;
child->yrel = child->ypos;
rel[child].x = cursor + pos[child].x;
rel[child].y = pos[child].y;
}
}
}
VISIBLE void
view_flow_right_down (view_t *view)
view_flow_right_down (view_t view, view_pos_t len)
{
flow_right (view, set_rows_down);
}
VISIBLE void
view_flow_right_up (view_t *view)
view_flow_right_up (view_t view, view_pos_t len)
{
flow_right (view, set_rows_up);
}
VISIBLE void
view_flow_left_down (view_t *view)
view_flow_left_down (view_t view, view_pos_t len)
{
flow_left (view, set_rows_down);
}
VISIBLE void
view_flow_left_up (view_t *view)
view_flow_left_up (view_t view, view_pos_t len)
{
flow_left (view, set_rows_up);
}
VISIBLE void
view_flow_down_right (view_t *view)
view_flow_down_right (view_t view, view_pos_t len)
{
flow_down (view, set_columns_right);
}
VISIBLE void
view_flow_up_right (view_t *view)
view_flow_up_right (view_t view, view_pos_t len)
{
flow_up (view, set_columns_right);
}
VISIBLE void
view_flow_down_left (view_t *view)
view_flow_down_left (view_t view, view_pos_t len)
{
flow_down (view, set_columns_left);
}
VISIBLE void
view_flow_up_left (view_t *view)
view_flow_up_left (view_t view, view_pos_t len)
{
flow_up (view, set_columns_left);
}
#endif