diff --git a/README.md b/README.md
index 5946d43f5..65682954d 100755
--- a/README.md
+++ b/README.md
@@ -87,7 +87,8 @@ demos\demo1
* 2018/03/11
* 增加XML界面描述文件预览工具。
* 支持极速模式(定义FAST_MODE启用),只绘制顶层的窗口中变化的控件,绘制效率非常高,但不支持透明背景。
-
+ * 支持基本的layout功能。
+
* 2018/03/10
* lua绑定及相关示例完成。
* 支持从UI描述文件创建界面。
diff --git a/TODO.md b/TODO.md
index 3421b3fff..ab2bfc1a6 100644
--- a/TODO.md
+++ b/TODO.md
@@ -20,9 +20,10 @@
* binarry ui loader
* xml ui loader
* api doc
+* 基本layout功能
+* 极速模式
## 短期计划(顺序不定)
-* 基本layout功能
* Qt界面文件转换器
* 微软Rc界面文件转换器
* API doc到PDF转换工具
diff --git a/demos/layouts/demo1.xml b/demos/layouts/demo1.xml
new file mode 100644
index 000000000..6507fb4ed
--- /dev/null
+++ b/demos/layouts/demo1.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/demos/layouts/demo2.xml b/demos/layouts/demo2.xml
new file mode 100644
index 000000000..688330be6
--- /dev/null
+++ b/demos/layouts/demo2.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/base/check_button.c b/src/base/check_button.c
index 5914621c4..180efd009 100644
--- a/src/base/check_button.c
+++ b/src/base/check_button.c
@@ -65,7 +65,7 @@ static ret_t check_button_on_paint_self(widget_t* widget, canvas_t* c) {
canvas_set_fill_color(c, style_get_color(style, STYLE_ID_BG_COLOR, color));
#ifdef FAST_MODE
canvas_fill_rect(c, 0, 0, widget->w, widget->h);
-#endif/*FAST_MODE*/
+#endif /*FAST_MODE*/
if (bitmap.data != NULL) {
rect_t src;
rect_t dst;
diff --git a/src/base/layout.c b/src/base/layout.c
index 4689fe794..9c8ef32dc 100644
--- a/src/base/layout.c
+++ b/src/base/layout.c
@@ -19,6 +19,7 @@
*
*/
+#include "base/mem.h"
#include "base/layout.h"
widget_layout_t* widget_layout_parse(widget_layout_t* layout, const char* x, const char* y,
@@ -72,10 +73,13 @@ widget_layout_t* widget_layout_parse(widget_layout_t* layout, const char* x, con
if (w != NULL) {
layout->w = atoi(w);
- if (w != NULL && strchr(w, '%') != NULL) {
- layout->w_attr = W_ATTR_PERCENT;
- } else {
- layout->w_attr = W_ATTR_PIXEL;
+ layout->w_attr = W_ATTR_PIXEL;
+ if (w != NULL) {
+ if(strchr(w, '%') != NULL) {
+ layout->w_attr = W_ATTR_PERCENT;
+ } else if(strstr(w, "fill") != NULL) {
+ layout->w_attr = W_ATTR_FILL;
+ }
}
} else {
layout->h_attr = H_ATTR_PIXEL;
@@ -83,10 +87,13 @@ widget_layout_t* widget_layout_parse(widget_layout_t* layout, const char* x, con
if (h != NULL) {
layout->h = atoi(h);
- if (strchr(h, '%') != NULL) {
- layout->h_attr = H_ATTR_PERCENT;
- } else {
- layout->h_attr = H_ATTR_PIXEL;
+ layout->h_attr = H_ATTR_PIXEL;
+ if(h != NULL) {
+ if (strchr(h, '%') != NULL) {
+ layout->h_attr = H_ATTR_PERCENT;
+ } else if(strstr(h, "fill") != NULL) {
+ layout->h_attr = H_ATTR_FILL;
+ }
}
} else {
layout->h_attr = H_ATTR_PIXEL;
@@ -152,28 +159,252 @@ ret_t widget_layout_calc(const widget_layout_t* layout, rect_t* r, wh_t parent_w
}
ret_t widget_set_self_layout_params(widget_t* widget, const widget_layout_t* layout) {
- /*TODO*/
+ return_value_if_fail(widget != NULL && layout != NULL, RET_BAD_PARAMS);
+ if (widget->layout_params == NULL) {
+ widget->layout_params = MEM_ZALLOC(layout_params_t);
+ }
+ return_value_if_fail(widget->layout_params != NULL, RET_OOM);
+ memcpy(&(widget->layout_params->self), layout, sizeof(*layout));
+
return RET_OK;
}
ret_t widget_set_children_layout_params(widget_t* widget, uint8_t rows, uint8_t cols,
- uint8_t margin, uint8_t cell_h_margin,
- uint8_t cell_v_margin) {
- /*TODO*/
+ uint8_t margin,
+ uint8_t cell_spacing) {
+ children_layout_t* layout = NULL;
+ return_value_if_fail(widget != NULL, RET_BAD_PARAMS);
+
+ if (widget->layout_params == NULL) {
+ widget->layout_params = MEM_ZALLOC(layout_params_t);
+ }
+ return_value_if_fail(widget->layout_params != NULL, RET_OOM);
+ layout = &(widget->layout_params->children);
+ layout->rows = rows;
+ layout->cols = cols;
+ layout->margin = margin;
+ layout->cell_spacing = cell_spacing;
+
return RET_OK;
}
ret_t widget_layout(widget_t* widget) {
- /*TODO*/
- return RET_OK;
+ return_value_if_fail(widget != NULL, RET_BAD_PARAMS);
+ widget_layout_self(widget);
+
+ return widget_layout_children(widget);
}
ret_t widget_layout_self(widget_t* widget) {
- /*TODO*/
+ rect_t r;
+ return_value_if_fail(widget != NULL, RET_BAD_PARAMS);
+
+ if (widget->parent != NULL && widget->layout_params != NULL) {
+ widget_layout_t* layout = &(widget->layout_params->self);
+ widget_layout_calc(layout, &r, widget->parent->w, widget->parent->h);
+ widget_move_resize(widget, r.x, r.y, r.w, r.h);
+ }
+
return RET_OK;
}
ret_t widget_layout_children(widget_t* widget) {
- /*TODO*/
+ wh_t w = 0;
+ wh_t h = 0;
+ xy_t x = 0;
+ xy_t y = 0;
+ uint32_t i = 0;
+ uint32_t n = 0;
+ uint8_t margin = 0;
+ widget_t* iter = NULL;
+ uint8_t cell_spacing = 0;
+ widget_t** children = NULL;
+ return_value_if_fail(widget != NULL, RET_BAD_PARAMS);
+
+ if (widget->children == NULL) {
+ return RET_OK;
+ }
+
+ n = widget->children->size;
+ children = (widget_t**)(widget->children->elms);
+
+ if (widget->layout_params) {
+ children_layout_t* layout = &(widget->layout_params->children);
+ uint8_t rows = layout->rows;
+ uint8_t cols = layout->cols;
+
+ x = layout->margin;
+ y = layout->margin;
+ margin = layout->margin;
+ cell_spacing = layout->cell_spacing;
+
+ if (rows == 1 && cols == 0) { /*hbox*/
+ h = widget->h - 2 * margin;
+ return_value_if_fail(h > 0, RET_BAD_PARAMS);
+
+ for (i = 0; i < n; i++) {
+ iter = children[i];
+ widget_layout_self(iter);
+ }
+
+ for (i = 0; i < n; i++) {
+ iter = children[i];
+ widget_move_resize(iter, x, y, iter->w, h);
+ x += iter->w + cell_spacing;
+ return_value_if_fail(x < widget->w, RET_BAD_PARAMS);
+ }
+
+ for (i = 0; i < n; i++) {
+ widget_layout_children(children[i]);
+ }
+
+ return RET_OK;
+ } else if (cols == 1 && rows == 0) { /*vbox*/
+ w = widget->w - 2 * margin;
+ return_value_if_fail(w > 0, RET_BAD_PARAMS);
+
+ for (i = 0; i < n; i++) {
+ iter = children[i];
+ widget_layout_self(iter);
+ }
+
+ for (i = 0; i < n; i++) {
+ iter = children[i];
+ widget_move_resize(iter, x, y, w, iter->h);
+ y += iter->h + cell_spacing;
+ return_value_if_fail(y < widget->h, RET_BAD_PARAMS);
+ }
+
+ for (i = 0; i < n; i++) {
+ widget_layout_children(children[i]);
+ }
+
+ return RET_OK;
+ } else if (cols > 0 && rows > 0) { /*grid|vlist|hlist*/
+ uint8_t r = 0;
+ uint8_t c = 0;
+ wh_t item_w = 0;
+ wh_t item_h = 0;
+ w = widget->w - 2 * margin - (cols - 1) * cell_spacing;
+ h = widget->h - 2 * margin - (rows - 1) * cell_spacing;
+ item_w = w / cols;
+ item_h = h / rows;
+ return_value_if_fail(item_w > 0 && item_h > 0, RET_BAD_PARAMS);
+
+ for (i = 0; i < n; i++) {
+ iter = children[i];
+ widget_move_resize(iter, x, y, item_w, item_h);
+ c++;
+ if (c == cols) {
+ r++;
+ y += item_h + cell_spacing;
+ c = 0;
+ x = margin;
+ } else {
+ x += item_w + cell_spacing;
+ }
+ return_value_if_fail(y < widget->h, RET_BAD_PARAMS);
+ }
+
+ for (i = 0; i < n; i++) {
+ widget_layout_children(children[i]);
+ }
+
+ return RET_OK;
+ } else if (rows == 0 && cols == 0) { /*free layout*/
+ /*fall through*/
+ } else { /*not support*/
+ log_debug("not supported(rows=%d, cols=%d)\n", rows, cols);
+ return RET_OK;
+ }
+ }
+
+ for (i = 0; i < n; i++) {
+ iter = children[i];
+ widget_layout_self(iter);
+ }
+
+ for (i = 0; i < n; i++) {
+ iter = children[i];
+ x = iter->x;
+ y = iter->y;
+ w = iter->w;
+ h = iter->h;
+ if (iter->layout_params) {
+ widget_layout_t* l = &(iter->layout_params->self);
+ if (l->w_attr == W_ATTR_FILL || l->h_attr == H_ATTR_FILL) {
+ widget_t* prev = i > 0 ? widget_get_child(widget, i - 1) : NULL;
+ widget_t* next = (i + 1) == widget->children->size ? NULL : widget_get_child(widget, i + 1);
+ if (l->w_attr == W_ATTR_FILL) {
+ if (prev) {
+ x = prev->x + prev->w + cell_spacing;
+ } else {
+ x = margin;
+ }
+ if (next) {
+ w = (next->x - cell_spacing) - x;
+ } else {
+ w = widget->w - margin - x;
+ }
+ }
+
+ if (l->h_attr == H_ATTR_FILL) {
+ if (prev != NULL) {
+ y = prev->y + prev->h + cell_spacing;
+ } else {
+ y = margin;
+ }
+
+ if (next != NULL) {
+ h = next->y - cell_spacing - y;
+ } else {
+ h = widget->h - margin - y;
+ }
+ }
+
+ return_value_if_fail(w > 0 && h > 0, RET_BAD_PARAMS);
+ widget_move_resize(iter, x, y, w, h);
+ }
+ }
+ }
+
+ for (i = 0; i < n; i++) {
+ widget_layout_children(children[i]);
+ }
+
return RET_OK;
}
+
+children_layout_t* children_layout_parser(children_layout_t* layout, const char* params) {
+ const char* p = params;
+ return_value_if_fail(layout != NULL && params != NULL, NULL);
+
+ memset(layout, 0x00, sizeof(*layout));
+
+ layout->rows = atoi(p);
+ p = strchr(p, ' ');
+ if(p != NULL) {
+ while(*p == ' ') p++;
+ if(*p) {
+ layout->cols = atoi(p);
+ }
+
+ p = strchr(p, ' ');
+ if(p != NULL) {
+ while(*p == ' ') p++;
+ if(*p) {
+ layout->margin = atoi(p);
+ }
+
+ p = strchr(p, ' ');
+ if(p != NULL) {
+ while(*p == ' ') p++;
+ if(*p) {
+ layout->cell_spacing = atoi(p);
+ }
+ }
+ }
+ }
+
+ return layout;
+}
diff --git a/src/base/layout.h b/src/base/layout.h
index a6f36e4f5..f42b26a13 100755
--- a/src/base/layout.h
+++ b/src/base/layout.h
@@ -22,64 +22,18 @@
#ifndef LFTK_LAYOUT_H
#define LFTK_LAYOUT_H
+#include "base/rect.h"
#include "base/widget.h"
+#include "base/layout_def.h"
BEGIN_C_DECLS
-
-typedef enum _x_attr_t {
- X_ATTR_DEFAULT = 0,
- X_ATTR_PERCENT,
- X_ATTR_CENTER,
- X_ATTR_RIGHT
-}x_attr_t;
-
-typedef enum _y_attr_t {
- Y_ATTR_DEFAULT = 0,
- Y_ATTR_PERCENT,
- Y_ATTR_MIDDLE,
- Y_ATTR_BOTTOM
-}y_attr_t;
-
-typedef enum _w_attr_t {
- W_ATTR_PIXEL = 0,
- W_ATTR_PERCENT
-}w_attr_t;
-
-typedef enum _h_attr_t {
- H_ATTR_PIXEL = 0,
- H_ATTR_PERCENT
-}h_attr_t;
-
-typedef struct _widget_layout_t {
- uint8_t x_attr;
- uint8_t y_attr;
- uint8_t w_attr;
- uint8_t h_attr;
- xy_t x;
- xy_t y;
- wh_t w;
- wh_t h;
-}widget_layout_t;
-
-typedef struct _children_layout_t {
- uint8_t rows;
- uint8_t cols;
- uint8_t margin;
- uint8_t cell_h_margin;
- uint8_t cell_v_margin;
-}children_layout_t;
-
-typedef struct _layout_params_t {
- widget_layout_t self;
- children_layout_t children;
-}layout_params_t;
-
ret_t widget_layout_calc(const widget_layout_t* layout, rect_t* r, wh_t parent_w, wh_t parent_h);
widget_layout_t* widget_layout_parse(widget_layout_t* layout, const char* x, const char* y, const char* w, const char* h);
+children_layout_t* children_layout_parser(children_layout_t* layout, const char* params);
ret_t widget_set_self_layout_params(widget_t* widget, const widget_layout_t* layout);
-ret_t widget_set_children_layout_params(widget_t* widget, uint8_t rows, uint8_t cols, uint8_t margin, uint8_t cell_h_margin, uint8_t cell_v_margin);
+ret_t widget_set_children_layout_params(widget_t* widget, uint8_t rows, uint8_t cols, uint8_t margin, uint8_t cell_spacing);
ret_t widget_layout(widget_t* widget);
ret_t widget_layout_self(widget_t* widget);
diff --git a/src/base/layout_def.h b/src/base/layout_def.h
new file mode 100755
index 000000000..58f6722d0
--- /dev/null
+++ b/src/base/layout_def.h
@@ -0,0 +1,81 @@
+/**
+ * File: layout_def.h
+ * Author: Li XianJing
+ * Brief: layout type def
+ *
+ * Copyright (c) 2018 - 2018 Li XianJing
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * License file for more details.
+ *
+ */
+
+/**
+ * History:
+ * ================================================================
+ * 2018-03-10 Li XianJing created
+ *
+ */
+
+#ifndef LFTK_LAYOUT_DEF_H
+#define LFTK_LAYOUT_DEF_H
+
+#include "base/types_def.h"
+
+BEGIN_C_DECLS
+
+typedef enum _x_attr_t {
+ X_ATTR_DEFAULT = 0,
+ X_ATTR_PERCENT,
+ X_ATTR_CENTER,
+ X_ATTR_RIGHT
+}x_attr_t;
+
+typedef enum _y_attr_t {
+ Y_ATTR_DEFAULT = 0,
+ Y_ATTR_PERCENT,
+ Y_ATTR_MIDDLE,
+ Y_ATTR_BOTTOM
+}y_attr_t;
+
+typedef enum _w_attr_t {
+ W_ATTR_PIXEL = 0,
+ W_ATTR_PERCENT,
+ W_ATTR_FILL
+}w_attr_t;
+
+typedef enum _h_attr_t {
+ H_ATTR_PIXEL = 0,
+ H_ATTR_PERCENT,
+ H_ATTR_FILL
+}h_attr_t;
+
+typedef struct _widget_layout_t {
+ uint8_t x_attr;
+ uint8_t y_attr;
+ uint8_t w_attr;
+ uint8_t h_attr;
+ xy_t x;
+ xy_t y;
+ wh_t w;
+ wh_t h;
+}widget_layout_t;
+
+typedef struct _children_layout_t {
+ uint8_t rows;
+ uint8_t cols;
+ uint8_t margin;
+ uint8_t cell_spacing;
+}children_layout_t;
+
+typedef struct _layout_params_t {
+ widget_layout_t self;
+ children_layout_t children;
+}layout_params_t;
+
+END_C_DECLS
+
+#endif/*LFTK_LAYOUT_DEF_H*/
+
diff --git a/src/base/lftk.c b/src/base/lftk.c
index eae80a1c2..83cc50ec7 100644
--- a/src/base/lftk.c
+++ b/src/base/lftk.c
@@ -44,7 +44,7 @@ static ret_t lftk_quit_idle(const timer_info_t* timer) {
return main_loop_quit(main_loop_get_default());
}
-ret_t lftk_quit() {
- timer_add(lftk_quit_idle, NULL, 0);
- return RET_OK;
+ret_t lftk_quit() {
+ timer_add(lftk_quit_idle, NULL, 0);
+ return RET_OK;
}
diff --git a/src/base/widget.c b/src/base/widget.c
index ad580b2e3..9e322a364 100644
--- a/src/base/widget.c
+++ b/src/base/widget.c
@@ -621,6 +621,10 @@ ret_t widget_destroy(widget_t* widget) {
widget->vt->destroy(widget);
}
+ if (widget->layout_params != NULL) {
+ MEM_FREE(widget->layout_params);
+ }
+
memset(widget, 0x00, sizeof(widget_t));
MEM_FREE(widget);
diff --git a/src/base/widget.h b/src/base/widget.h
index 045bfc44a..f115cc9ff 100755
--- a/src/base/widget.h
+++ b/src/base/widget.h
@@ -28,6 +28,7 @@
#include "base/emitter.h"
#include "base/canvas.h"
#include "base/theme.h"
+#include "base/layout_def.h"
BEGIN_C_DECLS
@@ -332,6 +333,12 @@ struct _widget_t {
* Style数据。
*/
style_t style;
+ /**
+ * @property {layout_params_t*} layout_params
+ * @private
+ * 布局参数。
+ */
+ layout_params_t* layout_params;
/**
* @property {widget_vtable_t} vt
* @private
diff --git a/src/base/window_manager.c b/src/base/window_manager.c
index d368cb8be..af83c405a 100644
--- a/src/base/window_manager.c
+++ b/src/base/window_manager.c
@@ -200,7 +200,7 @@ ret_t window_manager_on_paint_children(widget_t* widget, canvas_t* c) {
widget_paint(iter, c);
}
}
-#endif/*FAST_MODE*/
+#endif /*FAST_MODE*/
}
return RET_OK;
diff --git a/src/ui_loader/ui_builder_default.c b/src/ui_loader/ui_builder_default.c
index 7245fbae0..0f0cf62c7 100644
--- a/src/ui_loader/ui_builder_default.c
+++ b/src/ui_loader/ui_builder_default.c
@@ -36,16 +36,18 @@
static ret_t ui_builder_default_on_widget_start(ui_builder_t* b, const widget_desc_t* desc) {
rect_t r;
- xy_t x = desc->layout.x;
- xy_t y = desc->layout.y;
- wh_t w = desc->layout.w;
- wh_t h = desc->layout.h;
+ const widget_layout_t* layout = &(desc->layout);
+
+ xy_t x = layout->x;
+ xy_t y = layout->y;
+ wh_t w = layout->w;
+ wh_t h = layout->h;
widget_t* widget = NULL;
uint16_t type = desc->type;
widget_t* parent = b->widget;
if (parent != NULL) {
- widget_layout_calc(&desc->layout, &r, parent->w, parent->h);
+ widget_layout_calc(layout, &r, parent->w, parent->h);
x = r.x;
y = r.y;
w = r.w;
@@ -90,6 +92,10 @@ static ret_t ui_builder_default_on_widget_start(ui_builder_t* b, const widget_de
break;
}
+ if(layout->x_attr != X_ATTR_DEFAULT || layout->y_attr != Y_ATTR_DEFAULT || layout->w_attr == W_ATTR_PIXEL || layout->h_attr == H_ATTR_PIXEL) {
+ widget_set_self_layout_params(widget, layout);
+ }
+
b->widget = widget;
if (b->root == NULL) {
b->root = widget;
@@ -126,6 +132,11 @@ static ret_t ui_builder_default_on_widget_prop(ui_builder_t* b, const char* name
} else {
log_debug("%s %s is invalid.\n", __func__, value);
}
+ } else if (strcmp(name, "layout") == 0) {
+ /*2 2 5 10 10*/
+ children_layout_t cl;
+ children_layout_parser(&cl, value);
+ widget_set_children_layout_params(b->widget, cl.rows, cl.cols, cl.margin, cl.cell_spacing);
} else {
value_set_str(&v, value);
widget_set_prop(b->widget, name, &v);
@@ -166,6 +177,7 @@ widget_t* window_open(const char* name) {
ui_loader_load(loader, ui->data, ui->size, builder);
resource_manager_unref(ui);
+ widget_layout(builder->root);
return builder->root;
}
diff --git a/tests/layout_test.cc b/tests/layout_test.cc
index 2fe4a574f..494de618c 100644
--- a/tests/layout_test.cc
+++ b/tests/layout_test.cc
@@ -1,4 +1,5 @@
#include "base/layout.h"
+#include "base/group_box.h"
#include "gtest/gtest.h"
TEST(Layuout, basic) {
@@ -21,6 +22,14 @@ TEST(Layuout, basic) {
ASSERT_EQ(r.h, 4);
}
+TEST(Layuout, fill) {
+ rect_t r;
+ widget_layout_t layout;
+ ASSERT_EQ(widget_layout_parse(&layout, "1", "2", "fill", "fill"), &layout);
+ ASSERT_EQ(layout.w_attr, W_ATTR_FILL);
+ ASSERT_EQ(layout.h_attr, H_ATTR_FILL);
+}
+
TEST(Layuout, percent) {
rect_t r;
widget_layout_t layout;
@@ -104,3 +113,261 @@ TEST(Layuout, right_bottom1) {
ASSERT_EQ(r.w, 30);
ASSERT_EQ(r.h, 80);
}
+
+TEST(Layuout, layout_children_null) {
+ widget_layout_t layout;
+ widget_t* win = group_box_create(NULL, 0, 0, 200, 200);
+ widget_t* g1 = group_box_create(win, 0, 0, 0, 0);
+ widget_t* g2 = group_box_create(win, 0, 0, 0, 0);
+ widget_t* g3 = group_box_create(win, 0, 0, 0, 0);
+
+ widget_set_self_layout_params(g1, widget_layout_parse(&layout, "1", "2", "3", "4"));
+ widget_layout(win);
+ ASSERT_EQ(g1->x, 1);
+ ASSERT_EQ(g1->y, 2);
+ ASSERT_EQ(g1->w, 3);
+ ASSERT_EQ(g1->h, 4);
+
+ widget_set_self_layout_params(g1, widget_layout_parse(&layout, "0", "0", "10", "4"));
+ widget_set_self_layout_params(g2, widget_layout_parse(&layout, "0", "0", "fill", "4"));
+ widget_set_self_layout_params(g3, widget_layout_parse(&layout, "100", "0", "3", "4"));
+ widget_layout(win);
+ ASSERT_EQ(g2->x, 10);
+ ASSERT_EQ(g2->w, 90);
+
+ widget_set_self_layout_params(g1, widget_layout_parse(&layout, "0", "0", "10", "20"));
+ widget_set_self_layout_params(g2, widget_layout_parse(&layout, "0", "0", "4", "fill"));
+ widget_set_self_layout_params(g3, widget_layout_parse(&layout, "100", "160", "3", "4"));
+ widget_layout(win);
+ ASSERT_EQ(g2->y, 20);
+ ASSERT_EQ(g2->h, 140);
+
+ widget_destroy(win);
+}
+
+TEST(Layuout, layout_children_00) {
+ widget_layout_t layout;
+ widget_t* win = group_box_create(NULL, 0, 0, 200, 200);
+ widget_t* g1 = group_box_create(win, 0, 0, 0, 0);
+ widget_t* g2 = group_box_create(win, 0, 0, 0, 0);
+ widget_t* g3 = group_box_create(win, 0, 0, 0, 0);
+
+ widget_set_children_layout_params(win, 0, 0, 10, 10);
+ widget_set_self_layout_params(g1, widget_layout_parse(&layout, "0", "0", "10", "4"));
+ widget_set_self_layout_params(g2, widget_layout_parse(&layout, "0", "0", "fill", "4"));
+ widget_set_self_layout_params(g3, widget_layout_parse(&layout, "100", "0", "3", "4"));
+ widget_layout(win);
+ ASSERT_EQ(g2->x, 20);
+ ASSERT_EQ(g2->w, 70);
+
+ widget_set_self_layout_params(g1, widget_layout_parse(&layout, "0", "0", "10", "20"));
+ widget_set_self_layout_params(g2, widget_layout_parse(&layout, "0", "0", "4", "fill"));
+ widget_set_self_layout_params(g3, widget_layout_parse(&layout, "100", "160", "3", "4"));
+ widget_layout(win);
+ ASSERT_EQ(g2->y, 30);
+ ASSERT_EQ(g2->h, 120);
+
+ widget_destroy(win);
+}
+
+TEST(Layuout, layout_children_10) {
+ widget_layout_t layout;
+ widget_t* win = group_box_create(NULL, 0, 0, 200, 200);
+ widget_t* g1 = group_box_create(win, 0, 0, 0, 0);
+ widget_t* g2 = group_box_create(win, 0, 0, 0, 0);
+ widget_t* g3 = group_box_create(win, 0, 0, 0, 0);
+
+ widget_set_children_layout_params(win, 1, 0, 10, 5);
+ widget_set_self_layout_params(g1, widget_layout_parse(&layout, "0", "0", "20", "4"));
+ widget_set_self_layout_params(g2, widget_layout_parse(&layout, "0", "0", "30", "4"));
+ widget_set_self_layout_params(g3, widget_layout_parse(&layout, "100", "0", "20%", "4"));
+ widget_layout(win);
+ ASSERT_EQ(g1->x, 10);
+ ASSERT_EQ(g1->y, 10);
+ ASSERT_EQ(g1->w, 20);
+ ASSERT_EQ(g1->h, 180);
+
+ ASSERT_EQ(g2->x, 35);
+ ASSERT_EQ(g2->y, 10);
+ ASSERT_EQ(g2->w, 30);
+ ASSERT_EQ(g2->h, 180);
+
+ ASSERT_EQ(g3->x, 70);
+ ASSERT_EQ(g3->y, 10);
+ ASSERT_EQ(g3->w, 40);
+ ASSERT_EQ(g3->h, 180);
+
+ widget_destroy(win);
+}
+
+TEST(Layuout, layout_children_01) {
+ widget_layout_t layout;
+ widget_t* win = group_box_create(NULL, 0, 0, 200, 200);
+ widget_t* g1 = group_box_create(win, 0, 0, 0, 0);
+ widget_t* g2 = group_box_create(win, 0, 0, 0, 0);
+ widget_t* g3 = group_box_create(win, 0, 0, 0, 0);
+
+ widget_set_children_layout_params(win, 0, 1, 10, 10);
+ widget_set_self_layout_params(g1, widget_layout_parse(&layout, "0", "0", "20", "20"));
+ widget_set_self_layout_params(g2, widget_layout_parse(&layout, "0", "0", "30", "30"));
+ widget_set_self_layout_params(g3, widget_layout_parse(&layout, "100", "100", "20%", "20%"));
+ widget_layout(win);
+ ASSERT_EQ(g1->x, 10);
+ ASSERT_EQ(g1->y, 10);
+ ASSERT_EQ(g1->w, 180);
+ ASSERT_EQ(g1->h, 20);
+
+ ASSERT_EQ(g2->x, 10);
+ ASSERT_EQ(g2->y, 40);
+ ASSERT_EQ(g2->w, 180);
+ ASSERT_EQ(g2->h, 30);
+
+ ASSERT_EQ(g3->x, 10);
+ ASSERT_EQ(g3->y, 80);
+ ASSERT_EQ(g3->w, 180);
+ ASSERT_EQ(g3->h, 40);
+
+ widget_destroy(win);
+}
+
+TEST(Layuout, layout_children_11) {
+ widget_layout_t layout;
+ widget_t* win = group_box_create(NULL, 0, 0, 200, 200);
+ widget_t* g1 = group_box_create(win, 0, 0, 0, 0);
+
+ widget_set_children_layout_params(win, 1, 1, 10, 5);
+ widget_set_self_layout_params(g1, widget_layout_parse(&layout, "0", "0", "20%", "20%"));
+ widget_layout(win);
+ ASSERT_EQ(g1->x, 10);
+ ASSERT_EQ(g1->y, 10);
+ ASSERT_EQ(g1->w, 180);
+ ASSERT_EQ(g1->h, 180);
+
+ widget_destroy(win);
+}
+
+TEST(Layuout, layout_children_14) {
+ widget_layout_t layout;
+ widget_t* win = group_box_create(NULL, 0, 0, 200, 200);
+ widget_t* g1 = group_box_create(win, 0, 0, 0, 0);
+ widget_t* g2 = group_box_create(win, 0, 0, 0, 0);
+ widget_t* g3 = group_box_create(win, 0, 0, 0, 0);
+ widget_t* g4 = group_box_create(win, 0, 0, 0, 0);
+
+ widget_set_children_layout_params(win, 1, 4, 5, 10);
+ widget_layout(win);
+ ASSERT_EQ(g1->x, 5);
+ ASSERT_EQ(g1->y, 5);
+ ASSERT_EQ(g1->w, 40);
+ ASSERT_EQ(g1->h, 190);
+
+ ASSERT_EQ(g2->x, 55);
+ ASSERT_EQ(g2->y, 5);
+ ASSERT_EQ(g2->w, 40);
+ ASSERT_EQ(g2->h, 190);
+
+ ASSERT_EQ(g3->x, 105);
+ ASSERT_EQ(g3->y, 5);
+ ASSERT_EQ(g3->w, 40);
+ ASSERT_EQ(g3->h, 190);
+
+ ASSERT_EQ(g4->x, 155);
+ ASSERT_EQ(g4->y, 5);
+ ASSERT_EQ(g4->w, 40);
+ ASSERT_EQ(g4->h, 190);
+
+ widget_destroy(win);
+}
+
+TEST(Layuout, layout_children_41) {
+ widget_layout_t layout;
+ widget_t* win = group_box_create(NULL, 0, 0, 200, 200);
+ widget_t* g1 = group_box_create(win, 0, 0, 0, 0);
+ widget_t* g2 = group_box_create(win, 0, 0, 0, 0);
+ widget_t* g3 = group_box_create(win, 0, 0, 0, 0);
+ widget_t* g4 = group_box_create(win, 0, 0, 0, 0);
+
+ widget_set_children_layout_params(win, 4, 1, 5, 10);
+ widget_layout(win);
+ ASSERT_EQ(g1->x, 5);
+ ASSERT_EQ(g1->y, 5);
+ ASSERT_EQ(g1->h, 40);
+ ASSERT_EQ(g1->w, 190);
+
+ ASSERT_EQ(g2->y, 55);
+ ASSERT_EQ(g2->x, 5);
+ ASSERT_EQ(g2->h, 40);
+ ASSERT_EQ(g2->w, 190);
+
+ ASSERT_EQ(g3->y, 105);
+ ASSERT_EQ(g3->x, 5);
+ ASSERT_EQ(g3->h, 40);
+ ASSERT_EQ(g3->w, 190);
+
+ ASSERT_EQ(g4->y, 155);
+ ASSERT_EQ(g4->x, 5);
+ ASSERT_EQ(g4->h, 40);
+ ASSERT_EQ(g4->w, 190);
+
+ widget_destroy(win);
+}
+
+TEST(Layuout, layout_children_22) {
+ widget_layout_t layout;
+ widget_t* win = group_box_create(NULL, 0, 0, 200, 200);
+ widget_t* g1 = group_box_create(win, 0, 0, 0, 0);
+ widget_t* g2 = group_box_create(win, 0, 0, 0, 0);
+ widget_t* g3 = group_box_create(win, 0, 0, 0, 0);
+ widget_t* g4 = group_box_create(win, 0, 0, 0, 0);
+
+ widget_set_children_layout_params(win, 2, 2, 5, 10);
+ widget_layout(win);
+ ASSERT_EQ(g1->x, 5);
+ ASSERT_EQ(g1->y, 5);
+ ASSERT_EQ(g1->h, 90);
+ ASSERT_EQ(g1->w, 90);
+
+ ASSERT_EQ(g2->x, 105);
+ ASSERT_EQ(g2->y, 5);
+ ASSERT_EQ(g2->h, 90);
+ ASSERT_EQ(g2->w, 90);
+
+ ASSERT_EQ(g3->x, 5);
+ ASSERT_EQ(g3->y, 105);
+ ASSERT_EQ(g3->h, 90);
+ ASSERT_EQ(g3->w, 90);
+
+ ASSERT_EQ(g4->y, 105);
+ ASSERT_EQ(g4->x, 105);
+ ASSERT_EQ(g4->h, 90);
+ ASSERT_EQ(g4->w, 90);
+
+ widget_destroy(win);
+}
+
+TEST(Layuout, layout_children_parse) {
+ children_layout_t layout;
+ children_layout_parser(&layout, "1");
+ ASSERT_EQ(layout.rows, 1);
+ ASSERT_EQ(layout.cols, 0);
+ ASSERT_EQ(layout.margin, 0);
+ ASSERT_EQ(layout.cell_spacing, 0);
+
+ children_layout_parser(&layout, "1 2");
+ ASSERT_EQ(layout.rows, 1);
+ ASSERT_EQ(layout.cols, 2);
+ ASSERT_EQ(layout.margin, 0);
+ ASSERT_EQ(layout.cell_spacing, 0);
+
+ children_layout_parser(&layout, "1 2 3");
+ ASSERT_EQ(layout.rows, 1);
+ ASSERT_EQ(layout.cols, 2);
+ ASSERT_EQ(layout.margin, 3);
+ ASSERT_EQ(layout.cell_spacing, 0);
+
+ children_layout_parser(&layout, "1 2 3 4");
+ ASSERT_EQ(layout.rows, 1);
+ ASSERT_EQ(layout.cols, 2);
+ ASSERT_EQ(layout.margin, 3);
+ ASSERT_EQ(layout.cell_spacing, 4);
+}