Skip to content

Commit

Permalink
feat(gui): add rule for cache children style
Browse files Browse the repository at this point in the history
  • Loading branch information
lc-soft committed Mar 4, 2019
1 parent ebf843f commit 50cc6b2
Show file tree
Hide file tree
Showing 9 changed files with 292 additions and 124 deletions.
2 changes: 1 addition & 1 deletion include/LCUI/gui/css_library.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ typedef struct LCUI_SelectorRec_ {
int rank; /**< 权值,决定优先级 */
int batch_num; /**< 批次号 */
int length; /**< 选择器结点长度 */
unsigned int hash; /**< 哈希值 */
unsigned hash; /**< 哈希值 */
LCUI_SelectorNode *nodes; /**< 选择器结点列表 */
} LCUI_SelectorRec, *LCUI_Selector;

Expand Down
25 changes: 22 additions & 3 deletions include/LCUI/gui/widget_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ typedef enum LCUI_WidgetState {

typedef struct LCUI_WidgetRec_* LCUI_Widget;
typedef struct LCUI_WidgetPrototypeRec_ *LCUI_WidgetPrototype;
typedef struct LCUI_WidgetTaskContextRec_ *LCUI_WidgetTaskContext;
typedef const struct LCUI_WidgetPrototypeRec_ *LCUI_WidgetPrototypeC;

typedef void(*LCUI_WidgetFunction)(LCUI_Widget);
Expand Down Expand Up @@ -159,11 +160,21 @@ typedef struct LCUI_WidgetData_ {
} LCUI_WidgetData;

typedef struct LCUI_WidgetTaskContextRec_ {
LCUI_Selector selector;
LCUI_Widget widget;
} LCUI_WidgetTaskContextRec, *LCUI_WidgetTaskContext;
Dict *style_cache;
unsigned style_hash;
LCUI_WidgetTaskContext parent;
} LCUI_WidgetTaskContextRec;

typedef struct LCUI_WidgetRulesRec_ {
/**
* Cache the stylesheets of children to improve the query speed of
* the stylesheet.
* If this rule is enabled, we recommend that you manually call
* Widget_GenerateHash() to generate a hash value for the children
* of the widget.
*/
LCUI_BOOL cache_children_style;

/** Refresh the style of all child widgets if the status has changed */
LCUI_BOOL ignore_status_change;

Expand All @@ -185,6 +196,7 @@ typedef struct LCUI_WidgetRulesRec_ {

typedef struct LCUI_WidgetRulesDataRec_ {
LCUI_WidgetRulesRec rules;
Dict *style_cache;
size_t default_max_update_count;
size_t current_index;
} LCUI_WidgetRulesDataRec, *LCUI_WidgetRulesData;
Expand All @@ -203,6 +215,7 @@ typedef struct LCUI_WidgetAttributeRec_ {

/** 部件结构 */
typedef struct LCUI_WidgetRec_ {
unsigned hash; /**< 哈希值 */
LCUI_WidgetState state; /**< 状态 */
float x, y; /**< 当前坐标(由 origin 计算而来) */
float origin_x, origin_y; /**< 当前布局下计算出的坐标 */
Expand Down Expand Up @@ -401,6 +414,12 @@ LCUI_API void Widget_SetTitleW(LCUI_Widget w, const wchar_t *title);
/** 为部件添加状态 */
LCUI_API void Widget_AddState(LCUI_Widget w, LCUI_WidgetState state);

/** Generate a hash for a widget to identify it and siblings */
LCUI_API void Widget_GenerateSelfHash(LCUI_Widget w);

/** Generate hash values for a widget and its children */
LCUI_API void Widget_GenerateHash(LCUI_Widget w);

/** Set widget updating rules */
LCUI_API int Widget_SetRules(LCUI_Widget w, const LCUI_WidgetRulesRec *rules);

Expand Down
56 changes: 53 additions & 3 deletions src/gui/widget_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ static void Widget_Init(LCUI_Widget widget)
{
ZEROSET(widget, LCUI_Widget);
widget->state = LCUI_WSTATE_CREATED;
widget->trigger = EventTrigger();
widget->style = StyleSheet();
widget->computed_style.opacity = 1.0;
widget->computed_style.visible = TRUE;
Expand Down Expand Up @@ -271,12 +270,62 @@ void Widget_SetTitleW(LCUI_Widget w, const wchar_t *title)
Widget_AddTask(w, LCUI_WTASK_TITLE);
}

void Widget_GenerateSelfHash(LCUI_Widget widget)
{
int i;
unsigned hash = 1080;
LCUI_Widget w;

for (w = widget; w; w = w->parent) {
if (w != widget) {
hash = strhash(hash, " ");
}
if (w->type) {
hash = strhash(hash, w->type);
} else {
hash = strhash(hash, "*");
}
if (w->id) {
hash = strhash(hash, "#");
hash = strhash(hash, w->id);
}
if (w->classes) {
for (i = 0; w->classes[i]; ++i) {
hash = strhash(hash, ".");
hash = strhash(hash, w->classes[i]);
}
}
if (w->status) {
for (i = 0; w->status[i]; ++i) {
hash = strhash(hash, ":");
hash = strhash(hash, w->status[i]);
}
}
if (w->rules && w->rules->cache_children_style) {
break;
}
}
widget->hash = hash;
}

void Widget_GenerateHash(LCUI_Widget w)
{
LinkedListNode *node;

Widget_GenerateSelfHash(w);
for (LinkedList_Each(node, &w->children_show)) {
Widget_GenerateHash(node->data);
}
}

int Widget_SetRules(LCUI_Widget w, const LCUI_WidgetRulesRec *rules)
{
LCUI_WidgetRulesData data;

if (w->rules) {
free(w->rules);
data = (LCUI_WidgetRulesData)w->rules;
if (data) {
Dict_Release(data->style_cache);
free(data);
w->rules = NULL;
}
if (!rules) {
Expand All @@ -288,6 +337,7 @@ int Widget_SetRules(LCUI_Widget w, const LCUI_WidgetRulesRec *rules)
}
data->rules = *rules;
data->current_index = 0;
data->style_cache = NULL;
data->default_max_update_count = 2048;
w->rules = (LCUI_WidgetRules)data;
return 0;
Expand Down
5 changes: 5 additions & 0 deletions src/gui/widget_class.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ static int Widget_HandleClassesChange(LCUI_Widget w, const char *name)
if (w->rules && w->rules->ignore_classes_change) {
return 0;
}
/* If widget is not ready, indicate that the style of the children has
* been marked needs to be refreshed */
if (w->state < LCUI_WSTATE_READY) {
return 1;
}
if (Widget_GetChildrenStyleChanges(w, 0, name) > 0) {
Widget_MarkChildrenRefreshByClasses(w);
return 1;
Expand Down
30 changes: 20 additions & 10 deletions src/gui/widget_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,11 @@ static void WidgetEventTranslator(LCUI_Event e, LCUI_WidgetEventPack pack)
handler->func(w, &pack->event, pack->data);
while (!pack->event.cancel_bubble && w->parent) {
w = w->parent;
pack->widget = w;
/** 向父级部件冒泡传递事件 */
EventTrigger_Trigger(w->trigger, e->type, pack);
if (w->trigger) {
pack->widget = w;
/** 向父级部件冒泡传递事件 */
EventTrigger_Trigger(w->trigger, e->type, pack);
}
}
}

Expand Down Expand Up @@ -434,6 +436,9 @@ int Widget_BindEventById(LCUI_Widget widget, int event_id,
handler->func = func;
handler->data = data;
handler->destroy_data = destroy_data;
if (!widget->trigger) {
widget->trigger = EventTrigger();
}
return EventTrigger_Bind(widget->trigger, event_id,
(LCUI_EventFunc)WidgetEventTranslator, handler,
DestroyWidgetEventHandler);
Expand Down Expand Up @@ -507,9 +512,6 @@ static int Widget_TriggerEventEx(LCUI_Widget widget, LCUI_WidgetEventPack pack)
{
LCUI_WidgetEvent e = &pack->event;

if (!widget->trigger) {
return -1;
}
pack->widget = widget;
switch (e->type) {
case LCUI_WEVENT_CLICK:
Expand All @@ -522,7 +524,8 @@ static int Widget_TriggerEventEx(LCUI_Widget widget, LCUI_WidgetEventPack pack)
break;
}
default:
if (0 < EventTrigger_Trigger(widget->trigger, e->type, pack)) {
if (widget->trigger && 0 <
EventTrigger_Trigger(widget->trigger, e->type, pack)) {
return 0;
}
if (!widget->parent || e->cancel_bubble) {
Expand All @@ -534,7 +537,8 @@ static int Widget_TriggerEventEx(LCUI_Widget widget, LCUI_WidgetEventPack pack)
if (!widget->parent || e->cancel_bubble) {
return -1;
}
while (widget->computed_style.pointer_events == SV_NONE) {
while (widget->trigger &&
widget->computed_style.pointer_events == SV_NONE) {
LCUI_Widget w;
LCUI_BOOL is_pointer_event = TRUE;
int pointer_x, pointer_y;
Expand Down Expand Up @@ -587,6 +591,7 @@ LCUI_BOOL Widget_PostEvent(LCUI_Widget widget, LCUI_WidgetEvent ev, void *data,
LCUI_Event sys_ev;
LCUI_TaskRec task;
LCUI_WidgetEventPack pack;

if (widget->state == LCUI_WSTATE_DELETED) {
return FALSE;
}
Expand Down Expand Up @@ -620,6 +625,7 @@ LCUI_BOOL Widget_PostEvent(LCUI_Widget widget, LCUI_WidgetEvent ev, void *data,
int Widget_TriggerEvent(LCUI_Widget widget, LCUI_WidgetEvent e, void *data)
{
LCUI_WidgetEventPackRec pack;

if (!e->target) {
e->target = widget;
}
Expand Down Expand Up @@ -1203,6 +1209,7 @@ int Widget_PostSurfaceEvent(LCUI_Widget w, int event_type, LCUI_BOOL sync_props)
int *data;
LCUI_WidgetEventRec e = { 0 };
LCUI_Widget root = LCUIWidget_GetRoot();

if (w->parent != root && w != root) {
return -1;
}
Expand All @@ -1221,13 +1228,16 @@ int Widget_PostSurfaceEvent(LCUI_Widget w, int event_type, LCUI_BOOL sync_props)
void Widget_DestroyEventTrigger(LCUI_Widget w)
{
LCUI_WidgetEventRec e = { LCUI_WEVENT_DESTROY, 0 };

Widget_TriggerEvent(w, &e, NULL);
Widget_ReleaseMouseCapture(w);
Widget_ReleaseTouchCapture(w, -1);
Widget_StopEventPropagation(w);
LCUIWidget_ClearEventTarget(w);
EventTrigger_Destroy(w->trigger);
w->trigger = NULL;
if (w->trigger) {
EventTrigger_Destroy(w->trigger);
w->trigger = NULL;
}
}

static void BindSysEvent(int e, LCUI_SysEventFunc func)
Expand Down
4 changes: 4 additions & 0 deletions src/gui/widget_status.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ static void Widget_MarkChildrenRefreshByStatus(LCUI_Widget w)
static int Widget_HandleStatusChange(LCUI_Widget w, const char *name)
{
Widget_UpdateStyle(w, TRUE);
if (w->state < LCUI_WSTATE_READY) {
return 1;
}
if (w->rules && w->rules->ignore_status_change) {
return 0;
}
Expand Down Expand Up @@ -94,6 +97,7 @@ int Widget_RemoveStatus(LCUI_Widget w, const char *status_name)
void Widget_UpdateStatus(LCUI_Widget widget)
{
LCUI_Widget child;

if (!widget->parent) {
return;
}
Expand Down
Loading

0 comments on commit 50cc6b2

Please sign in to comment.