diff --git a/include/QF/ui/view.h b/include/QF/ui/view.h index 3d1865ae6..ed3d09776 100644 --- a/include/QF/ui/view.h +++ b/include/QF/ui/view.h @@ -98,6 +98,7 @@ struct view_s { unsigned resize_x:1; ///< If true, view's width follows parent's. unsigned resize_y:1; ///< If true, view's height follows parent's. unsigned bol_suppress:1; ///< If true, view_flow skips at start of line. + unsigned flow_size:1; ///< If true, view's size is adjusted to flow. view_t *parent; ///< The parent view. view_t **children; ///< The child views. int num_children; ///< Number of child views in view. @@ -271,6 +272,10 @@ void view_setgravity (view_t *view, grav_t grav); A child view with bol_suppress set will not contribute to a flow-line's length when that child view is the first view on the line, otherwise it behaves as if bol_suppress is not set. + + If the view's flow_size is set, then its secondary axis size is adjusted + so the child views fill the view along that axis. The primary axis size is + never adjusted. */ ///@{ diff --git a/libs/ui/test/Makemodule.am b/libs/ui/test/Makemodule.am index fb4b93c7d..d1475be63 100644 --- a/libs/ui/test/Makemodule.am +++ b/libs/ui/test/Makemodule.am @@ -1,5 +1,6 @@ libs_ui_tests = \ libs/ui/test/test-flow \ + libs/ui/test/test-flow-size \ libs/ui/test/test-txtbuffer \ libs/ui/test/test-vrect @@ -11,6 +12,10 @@ libs_ui_test_test_flow_SOURCES=libs/ui/test/test-flow.c libs_ui_test_test_flow_LDADD=libs/ui/libQFui.la libs_ui_test_test_flow_DEPENDENCIES=libs/ui/libQFui.la +libs_ui_test_test_flow_size_SOURCES=libs/ui/test/test-flow-size.c +libs_ui_test_test_flow_size_LDADD=libs/ui/libQFui.la +libs_ui_test_test_flow_size_DEPENDENCIES=libs/ui/libQFui.la + libs_ui_test_test_txtbuffer_SOURCES=libs/ui/test/test-txtbuffer.c libs_ui_test_test_txtbuffer_LDADD=libs/ui/libQFui.la libs_ui_test_test_txtbuffer_DEPENDENCIES=libs/ui/libQFui.la diff --git a/libs/ui/test/test-flow-size.c b/libs/ui/test/test-flow-size.c new file mode 100644 index 000000000..e37a2d44d --- /dev/null +++ b/libs/ui/test/test-flow-size.c @@ -0,0 +1,285 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include + +#include "QF/ui/view.h" + +typedef struct { + struct { + int xlen, ylen; + }; + int bol_suppress; + struct { + struct { + int xpos, ypos; + }; + struct { + int xrel, yrel; + }; + struct { + int xabs, yabs; + }; + } expect; +} testdata_t; + +#define array_size(array) (sizeof (array) / sizeof(array[0])) + +static testdata_t right_down_views[] = { + {{ 48, 8}, 0, { { 0, 0}, { 0, 0}, { 8, 16} }}, // 0 + {{128, 8}, 0, { { 48, 0}, { 48, 0}, { 56, 16} }}, + {{ 64, 8}, 0, { {176, 0}, {176, 0}, {184, 16} }}, + + {{ 32, 8}, 0, { { 0, 0}, { 0, 8}, { 8, 24} }}, // 3 + {{224, 8}, 0, { { 32, 0}, { 32, 8}, { 40, 24} }}, + + {{ 64, 8}, 0, { { 0, 0}, { 0, 16}, { 8, 32} }}, // 5 + {{ 64, 8}, 0, { { 64, 0}, { 64, 16}, { 72, 32} }}, + {{ 64, 8}, 0, { {128, 0}, {128, 16}, {136, 32} }}, + {{ 32, 8}, 0, { {192, 0}, {192, 16}, {200, 32} }}, + + {{288, 8}, 0, { { 0, 0}, { 0, 24}, { 8, 40} }}, // 9 + + {{ 48, 8}, 0, { { 0, 0}, { 0, 32}, { 8, 48} }}, // 10 + {{128, 8}, 0, { { 48, 0}, { 48, 32}, { 56, 48} }}, + {{ 64, 8}, 0, { {176, 0}, {176, 32}, {184, 48} }}, +}; +#define right_down_count array_size(right_down_views) + +static testdata_t right_up_views[] = { + {{ 48, 8}, 0, { { 0, 0}, { 0, 32}, { 8, 48} }}, // 0 + {{128, 8}, 0, { { 48, 0}, { 48, 32}, { 56, 48} }}, + {{ 64, 8}, 0, { {176, 0}, {176, 32}, {184, 48} }}, + + {{ 32, 8}, 0, { { 0, 0}, { 0, 24}, { 8, 40} }}, // 3 + {{224, 8}, 0, { { 32, 0}, { 32, 24}, { 40, 40} }}, + + {{ 64, 8}, 0, { { 0, 0}, { 0, 16}, { 8, 32} }}, // 5 + {{ 64, 8}, 0, { { 64, 0}, { 64, 16}, { 72, 32} }}, + {{ 64, 8}, 0, { {128, 0}, {128, 16}, {136, 32} }}, + {{ 32, 8}, 0, { {192, 0}, {192, 16}, {200, 32} }}, + + {{288, 8}, 0, { { 0, 0}, { 0, 8}, { 8, 24} }}, // 9 + + {{ 48, 8}, 0, { { 0, 0}, { 0, 0}, { 8, 16} }}, // 10 + {{128, 8}, 0, { { 48, 0}, { 48, 0}, { 56, 16} }}, + {{ 64, 8}, 0, { {176, 0}, {176, 0}, {184, 16} }}, +}; +#define right_up_count array_size(right_up_views) + +static testdata_t left_down_views[] = { + {{ 48, 8}, 0, { {208, 0}, {208, 0}, {216, 16} }}, // 0 + {{128, 8}, 0, { { 80, 0}, { 80, 0}, { 88, 16} }}, + {{ 64, 8}, 0, { { 16, 0}, { 16, 0}, { 24, 16} }}, + + {{ 32, 8}, 0, { {224, 0}, {224, 8}, {232, 24} }}, // 3 + {{224, 8}, 0, { { 0, 0}, { 0, 8}, { 8, 24} }}, + + {{ 64, 8}, 0, { {192, 0}, {192, 16}, {200, 32} }}, // 5 + {{ 64, 8}, 0, { {128, 0}, {128, 16}, {136, 32} }}, + {{ 64, 8}, 0, { { 64, 0}, { 64, 16}, { 72, 32} }}, + {{ 32, 8}, 0, { { 32, 0}, { 32, 16}, { 40, 32} }}, + + {{288, 8}, 0, { {-32, 0}, {-32, 24}, {-24, 40} }}, // 9 + + {{ 48, 8}, 0, { {208, 0}, {208, 32}, {216, 48} }}, // 10 + {{128, 8}, 0, { { 80, 0}, { 80, 32}, { 88, 48} }}, + {{ 64, 8}, 0, { { 16, 0}, { 16, 32}, { 24, 48} }}, +}; +#define left_down_count array_size(left_down_views) + +static testdata_t left_up_views[] = { + {{ 48, 8}, 0, { {208, 0}, {208, 32}, {216, 48} }}, // 0 + {{128, 8}, 0, { { 80, 0}, { 80, 32}, { 88, 48} }}, + {{ 64, 8}, 0, { { 16, 0}, { 16, 32}, { 24, 48} }}, + + {{ 32, 8}, 0, { {224, 0}, {224, 24}, {232, 40} }}, // 3 + {{224, 8}, 0, { { 0, 0}, { 0, 24}, { 8, 40} }}, + + {{ 64, 8}, 0, { {192, 0}, {192, 16}, {200, 32} }}, // 5 + {{ 64, 8}, 0, { {128, 0}, {128, 16}, {136, 32} }}, + {{ 64, 8}, 0, { { 64, 0}, { 64, 16}, { 72, 32} }}, + {{ 32, 8}, 0, { { 32, 0}, { 32, 16}, { 40, 32} }}, + + {{288, 8}, 0, { {-32, 0}, {-32, 8}, {-24, 24} }}, // 9 + + {{ 48, 8}, 0, { {208, 0}, {208, 0}, {216, 16} }}, // 10 + {{128, 8}, 0, { { 80, 0}, { 80, 0}, { 88, 16} }}, + {{ 64, 8}, 0, { { 16, 0}, { 16, 0}, { 24, 16} }}, +}; +#define left_up_count array_size(left_up_views) + +static testdata_t down_right_views[] = { + {{ 8, 48}, 0, { { 0, 0}, { 0, 0}, { 8, 16} }}, // 0 + {{ 8,128}, 0, { { 0, 48}, { 0, 48}, { 8, 64} }}, + {{ 8, 64}, 0, { { 0,176}, { 0,176}, { 8,192} }}, + + {{ 8, 32}, 0, { { 0, 0}, { 8, 0}, { 16, 16} }}, // 3 + {{ 8,224}, 0, { { 0, 32}, { 8, 32}, { 16, 48} }}, + + {{ 8, 64}, 0, { { 0, 0}, { 16, 0}, { 24, 16} }}, // 5 + {{ 8, 64}, 0, { { 0, 64}, { 16, 64}, { 24, 80} }}, + {{ 8, 64}, 0, { { 0,128}, { 16,128}, { 24,144} }}, + {{ 8, 32}, 0, { { 0,192}, { 16,192}, { 24,208} }}, + + {{ 8,288}, 0, { { 0, 0}, { 24, 0}, { 32, 16} }}, // 9 + + {{ 8, 48}, 0, { { 0, 0}, { 32, 0}, { 40, 16} }}, // 10 + {{ 8,128}, 0, { { 0, 48}, { 32, 48}, { 40, 64} }}, + {{ 8, 64}, 0, { { 0,176}, { 32,176}, { 40,192} }}, +}; +#define down_right_count array_size(down_right_views) + +static testdata_t up_right_views[] = { + {{ 8, 48}, 0, { { 0,208}, { 0,208}, { 8,224} }}, // 0 + {{ 8,128}, 0, { { 0, 80}, { 0, 80}, { 8, 96} }}, + {{ 8, 64}, 0, { { 0, 16}, { 0, 16}, { 8, 32} }}, + + {{ 8, 32}, 0, { { 0,224}, { 8,224}, { 16,240} }}, // 3 + {{ 8,224}, 0, { { 0, 0}, { 8, 0}, { 16, 16} }}, + + {{ 8, 64}, 0, { { 0,192}, { 16,192}, { 24,208} }}, // 5 + {{ 8, 64}, 0, { { 0,128}, { 16,128}, { 24,144} }}, + {{ 8, 64}, 0, { { 0, 64}, { 16, 64}, { 24, 80} }}, + {{ 8, 32}, 0, { { 0, 32}, { 16, 32}, { 24, 48} }}, + + {{ 8,288}, 0, { { 0,-32}, { 24,-32}, { 32,-16} }}, // 9 + + {{ 8, 48}, 0, { { 0,208}, { 32,208}, { 40,224} }}, // 10 + {{ 8,128}, 0, { { 0, 80}, { 32, 80}, { 40, 96} }}, + {{ 8, 64}, 0, { { 0, 16}, { 32, 16}, { 40, 32} }}, +}; +#define up_right_count array_size(up_right_views) + +static testdata_t down_left_views[] = { + {{ 8, 48}, 0, { { 0, 0}, { 32, 0}, { 40, 16} }}, // 0 + {{ 8,128}, 0, { { 0, 48}, { 32, 48}, { 40, 64} }}, + {{ 8, 64}, 0, { { 0,176}, { 32,176}, { 40,192} }}, + + {{ 8, 32}, 0, { { 0, 0}, { 24, 0}, { 32, 16} }}, // 3 + {{ 8,224}, 0, { { 0, 32}, { 24, 32}, { 32, 48} }}, + + {{ 8, 64}, 0, { { 0, 0}, { 16, 0}, { 24, 16} }}, // 5 + {{ 8, 64}, 0, { { 0, 64}, { 16, 64}, { 24, 80} }}, + {{ 8, 64}, 0, { { 0,128}, { 16,128}, { 24,144} }}, + {{ 8, 32}, 0, { { 0,192}, { 16,192}, { 24,208} }}, + + {{ 8,288}, 0, { { 0, 0}, { 8, 0}, { 16, 16} }}, // 9 + + {{ 8, 48}, 0, { { 0, 0}, { 0, 0}, { 8, 16} }}, // 10 + {{ 8,128}, 0, { { 0, 48}, { 0, 48}, { 8, 64} }}, + {{ 8, 64}, 0, { { 0,176}, { 0,176}, { 8,192} }}, +}; +#define down_left_count array_size(down_left_views) + +static testdata_t up_left_views[] = { + {{ 8, 48}, 0, { { 0,208}, { 32,208}, { 40,224} }}, // 0 + {{ 8,128}, 0, { { 0, 80}, { 32, 80}, { 40, 96} }}, + {{ 8, 64}, 0, { { 0, 16}, { 32, 16}, { 40, 32} }}, + + {{ 8, 32}, 0, { { 0,224}, { 24,224}, { 32,240} }}, // 3 + {{ 8,224}, 0, { { 0, 0}, { 24, 0}, { 32, 16} }}, + + {{ 8, 64}, 0, { { 0,192}, { 16,192}, { 24,208} }}, // 5 + {{ 8, 64}, 0, { { 0,128}, { 16,128}, { 24,144} }}, + {{ 8, 64}, 0, { { 0, 64}, { 16, 64}, { 24, 80} }}, + {{ 8, 32}, 0, { { 0, 32}, { 16, 32}, { 24, 48} }}, + + {{ 8,288}, 0, { { 0,-32}, { 8,-32}, { 16,-16} }}, // 9 + + {{ 8, 48}, 0, { { 0,208}, { 0,208}, { 8,224} }}, // 10 + {{ 8,128}, 0, { { 0, 80}, { 0, 80}, { 8, 96} }}, + {{ 8, 64}, 0, { { 0, 16}, { 0, 16}, { 8, 32} }}, +}; +#define up_left_count array_size(up_left_views) + +static void +print_view (view_t *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); +} + +static int +test_flow (testdata_t *child_views, int count, void (*flow) (view_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; + + 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_move (flow_view, 8, 16); + int ret = 0; + + for (int i = 0; i < flow_view->num_children; 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) { + 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); + } + } + return ret; +} + +int +main (void) +{ + int ret = 0; + + if (test_flow (right_down_views, right_down_count, view_flow_right_down)) { + printf ("right-down failed\n"); + ret = 1; + } + if (test_flow (right_up_views, right_up_count, view_flow_right_up)) { + printf ("right-up failed\n"); + ret = 1; + } + if (test_flow (left_down_views, left_down_count, view_flow_left_down)) { + printf ("left-down failed\n"); + ret = 1; + } + if (test_flow (left_up_views, left_up_count, view_flow_left_up)) { + printf ("left-up failed\n"); + ret = 1; + } + + if (test_flow (down_right_views, down_right_count, view_flow_down_right)) { + printf ("down-right failed\n"); + ret = 1; + } + if (test_flow (up_right_views, up_right_count, view_flow_up_right)) { + printf ("up-right failed\n"); + ret = 1; + } + if (test_flow (down_left_views, down_left_count, view_flow_down_left)) { + printf ("down-left failed\n"); + ret = 1; + } + if (test_flow (up_left_views, up_left_count, view_flow_up_left)) { + printf ("up-left failed\n"); + ret = 1; + } + return ret; +} diff --git a/libs/ui/view.c b/libs/ui/view.c index 198463fd3..411d13802 100644 --- a/libs/ui/view.c +++ b/libs/ui/view.c @@ -388,9 +388,33 @@ flow_up (view_t *view, void (*set_rows) (view_t *, flowline_t *)) set_rows (view, &flowline); } +static void +flow_view_height (view_t *view, flowline_t *flowlines) +{ + if (view->flow_size) { + view->ylen = 0; + for (flowline_t *line = flowlines; line; line = line->next) { + view->ylen += line->height; + } + } +} + +static void +flow_view_width (view_t *view, flowline_t *flowlines) +{ + if (view->flow_size) { + view->xlen = 0; + for (flowline_t *line = flowlines; line; line = line->next) { + view->xlen += line->height; + } + } +} + static void set_rows_down (view_t *view, flowline_t *flowlines) { + flow_view_height (view, flowlines); + int cursor = 0; for (flowline_t *line = flowlines; line; line = line->next) { cursor += line->height; @@ -406,6 +430,8 @@ set_rows_down (view_t *view, flowline_t *flowlines) static void set_rows_up (view_t *view, flowline_t *flowlines) { + flow_view_height (view, flowlines); + int cursor = view->ylen; for (flowline_t *line = flowlines; line; line = line->next) { for (int i = 0; i < line->child_count; i++) { @@ -421,6 +447,8 @@ set_rows_up (view_t *view, flowline_t *flowlines) static void set_columns_right (view_t *view, flowline_t *flowlines) { + flow_view_width (view, flowlines); + int cursor = 0; for (flowline_t *line = flowlines; line; line = line->next) { for (int i = 0; i < line->child_count; i++) { @@ -436,6 +464,8 @@ set_columns_right (view_t *view, flowline_t *flowlines) static void set_columns_left (view_t *view, flowline_t *flowlines) { + flow_view_width (view, flowlines); + int cursor = view->xlen; for (flowline_t *line = flowlines; line; line = line->next) { cursor -= line->height;