mirror of
https://gitee.com/zlgopen/awtk.git
synced 2024-11-30 02:58:26 +08:00
optimize widget_clone
This commit is contained in:
parent
32cccf8cff
commit
b60bcc8c16
@ -1,5 +1,8 @@
|
||||
# 最新动态
|
||||
|
||||
* 2020/01/01
|
||||
* 优化widget\_clone
|
||||
|
||||
* 2019/12/31
|
||||
* 完善RichText(感谢尧燊提供补丁)
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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*/
|
||||
|
@ -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;
|
||||
|
@ -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*/
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user