optimize widget_clone

This commit is contained in:
xianjimli 2020-01-01 08:50:00 +08:00
parent 32cccf8cff
commit b60bcc8c16
14 changed files with 207 additions and 58 deletions

View File

@ -1,5 +1,8 @@
# 最新动态
* 2020/01/01
* 优化widget\_clone
* 2019/12/31
* 完善RichText感谢尧燊提供补丁

View File

@ -113,6 +113,14 @@ ret_t children_layouter_destroy(children_layouter_t* layouter) {
return layouter->vt->destroy(layouter);
}
children_layouter_t* children_layouter_clone(children_layouter_t* layouter) {
if (layouter != NULL && layouter->vt != NULL && layouter->vt->clone != NULL) {
return layouter->vt->clone(layouter);
}
return NULL;
}
#ifdef WITHOUT_LAYOUTER
children_layouter_t* children_layouter_create(const char* params) {
return NULL;

View File

@ -41,6 +41,7 @@ typedef bool_t (*children_layouter_is_valid_t)(children_layouter_t* layouter);
typedef ret_t (*children_layouter_destroy_t)(children_layouter_t* layouter);
typedef children_layouter_t* (*children_layouter_create_t)(void);
typedef children_layouter_t* (*children_layouter_clone_t)(children_layouter_t* layouter);
typedef struct _children_layouter_vtable_t {
const char* type;
@ -49,6 +50,7 @@ typedef struct _children_layouter_vtable_t {
children_layouter_is_valid_t is_valid;
children_layouter_get_param_t get_param;
children_layouter_set_param_t set_param;
children_layouter_clone_t clone;
children_layouter_destroy_t destroy;
} children_layouter_vtable_t;
@ -176,6 +178,15 @@ ret_t children_layouter_destroy(children_layouter_t* layouter);
*/
children_layouter_t* children_layouter_create(const char* params);
/**
* @method children_layouter_clone
* layouter对象
* @param {children_layouter_t*} layouter
*
* @return {children_layouter_t*} layouter对象
*/
children_layouter_t* children_layouter_clone(children_layouter_t* layouter);
END_C_DECLS
#endif /*TK_CHILDREN_LAYOUTER_H*/

View File

@ -99,6 +99,14 @@ ret_t self_layouter_destroy(self_layouter_t* layouter) {
return layouter->vt->destroy(layouter);
}
self_layouter_t* self_layouter_clone(self_layouter_t* layouter) {
if (layouter != NULL && layouter->vt != NULL && layouter->vt->clone != NULL) {
return layouter->vt->clone(layouter);
}
return NULL;
}
#ifdef WITHOUT_LAYOUTER
self_layouter_t* self_layouter_create(const char* params) {
return NULL;

View File

@ -41,6 +41,7 @@ typedef ret_t (*self_layouter_set_param_t)(self_layouter_t* layouter, const char
typedef ret_t (*self_layouter_destroy_t)(self_layouter_t* layouter);
typedef self_layouter_t* (*self_layouter_create_t)(void);
typedef self_layouter_t* (*self_layouter_clone_t)(self_layouter_t* layouter);
typedef struct _self_layouter_vtable_t {
const char* type;
@ -48,6 +49,7 @@ typedef struct _self_layouter_vtable_t {
self_layouter_layout_t layout;
self_layouter_get_param_t get_param;
self_layouter_set_param_t set_param;
self_layouter_clone_t clone;
self_layouter_destroy_t destroy;
} self_layouter_vtable_t;
@ -155,6 +157,16 @@ ret_t self_layouter_destroy(self_layouter_t* layouter);
*/
self_layouter_t* self_layouter_create(const char* params);
/**
* @method self_layouter_clone
* layouter对象
*
* @param {const char*} layouter
*
* @return {self_layouter_t*} layouter对象
*/
self_layouter_t* self_layouter_clone(self_layouter_t* layouter);
END_C_DECLS
#endif /*TK_SELF_LAYOUTER_H*/

View File

@ -2900,50 +2900,6 @@ ret_t widget_prepare_text_style(widget_t* widget, canvas_t* c) {
return RET_OK;
}
static const char* const s_widget_persistent_props[] = {WIDGET_PROP_NAME,
WIDGET_PROP_STYLE,
WIDGET_PROP_TR_TEXT,
WIDGET_PROP_TEXT,
WIDGET_PROP_ANIMATION,
WIDGET_PROP_ENABLE,
WIDGET_PROP_VISIBLE,
WIDGET_PROP_FLOATING,
WIDGET_PROP_CHILDREN_LAYOUT,
WIDGET_PROP_SELF_LAYOUT,
WIDGET_PROP_OPACITY,
WIDGET_PROP_FOCUSED,
WIDGET_PROP_FEEDBACK,
WIDGET_PROP_FOCUSABLE,
WIDGET_PROP_WITH_FOCUS_STATE,
WIDGET_PROP_SENSITIVE,
NULL};
const char* const* widget_get_persistent_props(void) {
return s_widget_persistent_props;
}
static ret_t widget_copy_props(widget_t* clone, widget_t* widget, const char* const* properties) {
if (properties != NULL) {
value_t v;
value_t defval;
uint32_t i = 0;
for (i = 0; properties[i] != NULL; i++) {
const char* prop = properties[i];
if (widget_get_prop(widget, prop, &v) == RET_OK) {
if (widget_get_prop_default_value(widget, prop, &defval) == RET_OK) {
if (!value_equal(&v, &defval)) {
widget_set_prop(clone, prop, &v);
}
} else {
widget_set_prop(clone, prop, &v);
}
}
}
}
return RET_OK;
}
static ret_t widget_copy_style(widget_t* clone, widget_t* widget) {
if (style_is_mutable(widget->astyle) && style_mutable_cast(widget->astyle) != NULL) {
if (!style_is_mutable(clone->astyle)) {
@ -2958,17 +2914,82 @@ static ret_t widget_copy_style(widget_t* clone, widget_t* widget) {
return RET_OK;
}
static ret_t widget_copy(widget_t* clone, widget_t* widget) {
clone->state = tk_strdup(widget->state);
clone->focused = widget->focused;
widget_copy_style(clone, widget);
widget_copy_props(clone, widget, s_widget_persistent_props);
widget_copy_props(clone, widget, widget->vt->clone_properties);
static const char* const s_widget_persistent_props[] = {WIDGET_PROP_NAME,
WIDGET_PROP_STYLE,
WIDGET_PROP_TR_TEXT,
WIDGET_PROP_TEXT,
WIDGET_PROP_ANIMATION,
WIDGET_PROP_ENABLE,
WIDGET_PROP_VISIBLE,
WIDGET_PROP_FLOATING,
WIDGET_PROP_CHILDREN_LAYOUT,
WIDGET_PROP_SELF_LAYOUT,
WIDGET_PROP_OPACITY,
WIDGET_PROP_FOCUSED,
WIDGET_PROP_FEEDBACK,
WIDGET_PROP_FOCUSABLE,
WIDGET_PROP_SENSITIVE,
WIDGET_PROP_WITH_FOCUS_STATE,
NULL};
if (widget->custom_props) {
clone->custom_props = object_default_clone(OBJECT_DEFAULT(widget->custom_props));
const char* const* widget_get_persistent_props(void) {
return s_widget_persistent_props;
}
static ret_t widget_copy_base_props(widget_t* widget, widget_t* other) {
widget->state = tk_str_copy(widget->state, other->state);
widget->name = tk_str_copy(widget->name, other->name);
widget->style = tk_str_copy(widget->style, other->style);
widget->tr_text = tk_str_copy(widget->tr_text, other->tr_text);
if (other->text.str != NULL) {
widget_set_text(widget, other->text.str);
}
widget->enable = other->enable;
widget->visible = other->visible;
widget->floating = other->floating;
widget->opacity = other->opacity;
widget->focused = other->focused;
widget->feedback = other->feedback;
widget->focusable = other->focusable;
widget->sensitive = other->sensitive;
widget->with_focus_state = other->with_focus_state;
if (other->animation != NULL && *(other->animation)) {
widget_set_animation(widget, other->animation);
}
if (other->self_layout != NULL) {
widget->self_layout = self_layouter_clone(other->self_layout);
}
if (other->children_layout != NULL) {
widget->children_layout = children_layouter_clone(other->children_layout);
}
return RET_OK;
}
static ret_t widget_copy(widget_t* widget, widget_t* other) {
return_value_if_fail(widget != NULL && other != NULL, RET_BAD_PARAMS);
return_value_if_fail(widget->vt == other->vt, RET_BAD_PARAMS);
widget_copy_style(widget, other);
widget_copy_base_props(widget, other);
if (widget->vt->on_copy != NULL) {
widget->vt->on_copy(widget, other);
} else {
widget_on_copy_default(widget, other);
}
if (other->custom_props) {
widget->custom_props = object_default_clone(OBJECT_DEFAULT(other->custom_props));
}
widget_set_need_update_style(widget);
return RET_OK;
}
@ -2977,11 +2998,9 @@ widget_t* widget_clone(widget_t* widget, widget_t* parent) {
return_value_if_fail(widget != NULL && widget->vt != NULL && widget->vt->create != NULL, NULL);
clone = widget->vt->create(parent, widget->x, widget->y, widget->w, widget->h);
TKMEM_FREE(clone->state);
return_value_if_fail(clone != NULL, NULL);
widget_copy(clone, widget);
widget_set_need_update_style(clone);
WIDGET_FOR_EACH_CHILD_BEGIN(widget, iter, i)
widget_clone(iter, clone);

View File

@ -72,6 +72,7 @@ typedef ret_t (*widget_on_layout_children_t)(widget_t* widget);
typedef ret_t (*widget_get_prop_t)(widget_t* widget, const char* name, value_t* v);
typedef ret_t (*widget_get_prop_default_value_t)(widget_t* widget, const char* name, value_t* v);
typedef ret_t (*widget_set_prop_t)(widget_t* widget, const char* name, const value_t* v);
typedef ret_t (*widget_on_copy_t)(widget_t* widget, widget_t* other);
typedef widget_t* (*widget_find_target_t)(widget_t* widget, xy_t x, xy_t y);
typedef widget_t* (*widget_create_t)(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h);
typedef ret_t (*widget_on_destroy_t)(widget_t* widget);
@ -148,8 +149,12 @@ struct _widget_vtable_t {
widget_create_t create;
widget_get_prop_t get_prop;
widget_get_prop_default_value_t get_prop_default_value;
widget_set_prop_t set_prop;
widget_invalidate_t invalidate;
widget_find_target_t find_target;
widget_get_prop_default_value_t get_prop_default_value;
widget_on_copy_t on_copy;
widget_on_keyup_t on_keyup;
widget_on_keydown_t on_keydown;
widget_on_wheel_t on_wheel;
@ -163,14 +168,12 @@ struct _widget_vtable_t {
widget_on_pointer_move_t on_pointer_move;
widget_on_pointer_up_t on_pointer_up;
widget_on_layout_children_t on_layout_children;
widget_invalidate_t invalidate;
widget_on_add_child_t on_add_child;
widget_on_remove_child_t on_remove_child;
widget_on_attach_parent_t on_attach_parent;
widget_on_detach_parent_t on_detach_parent;
widget_on_event_t on_event;
widget_on_event_before_children_t on_event_before_children;
widget_find_target_t find_target;
widget_on_destroy_t on_destroy;
};

View File

@ -189,6 +189,32 @@ widget_t* widget_find_target_default(widget_t* widget, xy_t x, xy_t y) {
return NULL;
}
static ret_t widget_copy_props(widget_t* clone, widget_t* widget, const char* const* properties) {
if (properties != NULL) {
value_t v;
value_t defval;
uint32_t i = 0;
for (i = 0; properties[i] != NULL; i++) {
const char* prop = properties[i];
if (widget_get_prop(widget, prop, &v) == RET_OK) {
if (widget_get_prop_default_value(widget, prop, &defval) == RET_OK) {
if (!value_equal(&v, &defval)) {
widget_set_prop(clone, prop, &v);
}
} else {
widget_set_prop(clone, prop, &v);
}
}
}
}
return RET_OK;
}
ret_t widget_on_copy_default(widget_t* widget, widget_t* other) {
return widget_copy_props(widget, other, widget->vt->clone_properties);
}
ret_t widget_on_destroy_default(widget_t* widget) {
(void)widget;
return RET_OK;
@ -203,6 +229,7 @@ ret_t widget_on_paint_null(widget_t* widget, canvas_t* c) {
TK_DECL_VTABLE(widget) = {.size = sizeof(widget_t),
.type = WIDGET_TYPE_NONE,
.parent = NULL,
.on_copy = widget_on_copy_default,
.invalidate = widget_invalidate_default,
.on_event = widget_on_event_default,
.on_paint_self = widget_on_paint_self_default,

View File

@ -36,6 +36,7 @@ ret_t widget_on_click_default(widget_t* widget, pointer_event_t* e);
ret_t widget_on_pointer_down_default(widget_t* widget, pointer_event_t* e);
ret_t widget_on_pointer_move_default(widget_t* widget, pointer_event_t* e);
ret_t widget_on_pointer_up_default(widget_t* widget, pointer_event_t* e);
ret_t widget_on_copy_default(widget_t* widget, widget_t* other);
ret_t widget_get_prop_default(widget_t* widget, const char* name, value_t* v);
ret_t widget_set_prop_default(widget_t* widget, const char* name, const value_t* v);
widget_t* widget_find_target_default(widget_t* widget, xy_t x, xy_t y);

View File

@ -359,8 +359,19 @@ static ret_t children_layouter_list_view_destroy(children_layouter_t* layouter)
return RET_OK;
}
static children_layouter_t* children_layouter_list_view_clone(children_layouter_t* layouter) {
children_layouter_list_view_t* l = TKMEM_ZALLOC(children_layouter_list_view_t);
memcpy(l, layouter, sizeof(*l));
str_init(&(l->layouter.params), 0);
str_set(&(l->layouter.params), layouter->params.str);
return (children_layouter_t*)l;
}
static const children_layouter_vtable_t s_children_layouter_list_view_vtable = {
.type = CHILDREN_LAYOUTER_LIST_VIEW,
.clone = children_layouter_list_view_clone,
.to_string = children_layouter_list_view_to_string,
.get_param = children_layouter_list_view_get_param,
.set_param = children_layouter_list_view_set_param,

View File

@ -420,8 +420,19 @@ static ret_t children_layouter_default_destroy(children_layouter_t* layouter) {
return RET_OK;
}
static children_layouter_t* children_layouter_default_clone(children_layouter_t* layouter) {
children_layouter_default_t* l = TKMEM_ZALLOC(children_layouter_default_t);
memcpy(l, layouter, sizeof(*l));
str_init(&(l->layouter.params), 0);
str_set(&(l->layouter.params), layouter->params.str);
return (children_layouter_t*)l;
}
static const children_layouter_vtable_t s_children_layouter_default_vtable = {
.type = "default",
.clone = children_layouter_default_clone,
.to_string = children_layouter_default_to_string,
.get_param = children_layouter_default_get_param,
.set_param = children_layouter_default_set_param,

View File

@ -385,8 +385,19 @@ static ret_t self_layouter_default_destroy(self_layouter_t* layouter) {
return RET_OK;
}
static self_layouter_t* self_layouter_default_clone(self_layouter_t* layouter) {
self_layouter_default_t* l = TKMEM_ZALLOC(self_layouter_default_t);
memcpy(l, layouter, sizeof(*l));
str_init(&(l->layouter.params), 0);
str_set(&(l->layouter.params), layouter->params.str);
return (self_layouter_t*)l;
}
static const self_layouter_vtable_t s_self_layouter_default_vtable = {
.type = "default",
.clone = self_layouter_default_clone,
.to_string = self_layouter_default_to_string,
.get_param = self_layouter_default_get_param,
.set_param = self_layouter_default_set_param,

View File

@ -350,8 +350,19 @@ static ret_t self_layouter_menu_destroy(self_layouter_t* layouter) {
return RET_OK;
}
static self_layouter_t* self_layouter_menu_clone(self_layouter_t* layouter) {
self_layouter_menu_t* l = TKMEM_ZALLOC(self_layouter_menu_t);
memcpy(l, layouter, sizeof(*l));
str_init(&(l->layouter.params), 0);
str_set(&(l->layouter.params), layouter->params.str);
return (self_layouter_t*)l;
}
static const self_layouter_vtable_t s_self_layouter_menu_vtable = {
.type = "menu",
.clone = self_layouter_menu_clone,
.get_param = self_layouter_menu_get_param,
.set_param = self_layouter_menu_set_param,
.layout = self_layouter_menu_layout,

View File

@ -11,6 +11,7 @@
#include "base/window.h"
#include "gtest/gtest.h"
#include <stdlib.h>
#include "ui_loader/ui_serializer.h"
TEST(Button, basic) {
value_t v1;
@ -42,9 +43,10 @@ TEST(Button, basic) {
TEST(Button, clone) {
value_t v1;
str_t str;
widget_t* w1 = button_create(NULL, 10, 20, 30, 40);
str_init(&str, 0);
value_set_int(&v1, 200);
ASSERT_EQ(widget_set_prop(w1, WIDGET_PROP_REPEAT, &v1), RET_OK);
widget_set_self_layout_params(w1, "1", "2", "3", "4");
@ -54,9 +56,20 @@ TEST(Button, clone) {
ASSERT_EQ(button_cast(w1), w1);
widget_t* w2 = widget_clone(w1, NULL);
log_debug("==================================\n");
widget_to_xml(w1, &str);
log_debug("w1:%s\n", str.str);
str_set(&str, "");
widget_to_xml(w2, &str);
log_debug("w2:%s\n", str.str);
log_debug("==================================\n");
ASSERT_EQ(widget_equal(w1, w2), TRUE);
widget_destroy(w1);
widget_destroy(w2);
str_reset(&str);
}
static ret_t button_on_click_to_remove_parent(void* ctx, event_t* e) {