Skip to content

Commit

Permalink
feat(gui): add rule for allow widget updates only when visible
Browse files Browse the repository at this point in the history
  • Loading branch information
lc-soft committed Mar 4, 2019
1 parent ec5e0d6 commit 93049c4
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 24 deletions.
11 changes: 10 additions & 1 deletion include/LCUI/gui/widget_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,12 @@ typedef struct LCUI_WidgetTaskContextRec_ {
} LCUI_WidgetTaskContextRec;

typedef struct LCUI_WidgetRulesRec_ {
/**
* Suspend update if the current widget is not visible or is
* completely covered by other widgets
*/
LCUI_BOOL only_on_visible;

/**
* Cache the stylesheets of children to improve the query speed of
* the stylesheet.
Expand All @@ -190,7 +196,7 @@ typedef struct LCUI_WidgetRulesRec_ {
*/
int max_update_children_count;

/** Limit the number of children rendered */
/** Limit the number of children rendered */
unsigned max_render_children_count;

/** A callback function on update progress */
Expand Down Expand Up @@ -417,6 +423,9 @@ LCUI_API void Widget_SetTitleW(LCUI_Widget w, const wchar_t *title);
/** 为部件添加状态 */
LCUI_API void Widget_AddState(LCUI_Widget w, LCUI_WidgetState state);

/** Check whether the widget is in the visible area */
LCUI_API LCUI_BOOL Widget_InVisibleArea(LCUI_Widget w);

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

Expand Down
35 changes: 20 additions & 15 deletions include/LCUI/util/rect.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,32 +31,38 @@
#ifndef LCUI_UTIL_RECT_H
#define LCUI_UTIL_RECT_H

#define LCUIRect_IsIncludeRect(a, b) \
((b)->x >= (a)->x && (b)->x + (b)->width <= (a)->x + (a)->width && \
(b)->y >= (a)->y && (b)->y + (b)->height <= (a)->y + (a)->height)

#define LCUIRectF_IsIncludeRect LCUIRect_IsIncludeRect

LCUI_BEGIN_HEADER

/* 将数值转换成LCUI_Rect型结构体 */
LCUI_API LCUI_Rect Rect(int x, int y, int w, int h);

/** 根据容器尺寸,获取指定区域中需要裁剪的区域 */
LCUI_API void LCUIRect_GetCutArea(int box_w, int box_h,
LCUI_Rect rect, LCUI_Rect *cut);
LCUI_API void LCUIRect_GetCutArea(int box_w, int box_h, LCUI_Rect rect,
LCUI_Rect *cut);

#define LCUIRect_HasPoint(rect, X, Y) (X >= (rect)->x && Y >= (rect)->y \
&& X < (rect)->x + (rect)->width \
&& Y < (rect)->y + (rect)->height)
#define LCUIRect_HasPoint(rect, X, Y) \
(X >= (rect)->x && Y >= (rect)->y && X < (rect)->x + (rect)->width && \
Y < (rect)->y + (rect)->height)

/** 将矩形区域范围调整在容器有效范围内 */
LCUI_API LCUI_BOOL LCUIRect_ValidateArea(LCUI_Rect *rect, int box_w, int box_h);

LCUI_API LCUI_BOOL LCUIRectF_ValidateArea(LCUI_RectF *rect, float box_w, float box_h);
LCUI_API LCUI_BOOL LCUIRectF_ValidateArea(LCUI_RectF *rect, float box_w,
float box_h);

LCUI_API void LCUIRect_ToRectF(const LCUI_Rect *rect,
LCUI_RectF *rectf, float scale);
LCUI_API void LCUIRect_ToRectF(const LCUI_Rect *rect, LCUI_RectF *rectf,
float scale);

LCUI_API void LCUIRect_Scale(const LCUI_Rect *src,
LCUI_Rect *dst, float scale);
LCUI_API void LCUIRect_Scale(const LCUI_Rect *src, LCUI_Rect *dst, float scale);

LCUI_API void LCUIRectF_ToRect(const LCUI_RectF *rectf,
LCUI_Rect *rect, float scale);
LCUI_API void LCUIRectF_ToRect(const LCUI_RectF *rectf, LCUI_Rect *rect,
float scale);

/** 检测矩形是否遮盖另一个矩形 */
LCUI_API LCUI_BOOL LCUIRect_IsCoverRect(LCUI_Rect *rect1, LCUI_Rect *rect2);
Expand All @@ -69,8 +75,7 @@ LCUI_API LCUI_BOOL LCUIRect_IsCoverRect(LCUI_Rect *rect1, LCUI_Rect *rect2);
* @returns 如果两个矩形重叠,则返回TRUE,否则返回FALSE
*/
LCUI_API LCUI_BOOL LCUIRect_GetOverlayRect(const LCUI_Rect *a,
const LCUI_Rect *b,
LCUI_Rect *out);
const LCUI_Rect *b, LCUI_Rect *out);

LCUI_API LCUI_BOOL LCUIRectF_GetOverlayRect(const LCUI_RectF *a,
const LCUI_RectF *b,
Expand Down Expand Up @@ -102,7 +107,7 @@ LCUI_API int RectList_Add(LinkedList *list, LCUI_Rect *rect);
/** 删除脏矩形 */
LCUI_API int RectList_Delete(LinkedList *list, LCUI_Rect *rect);

#define RectList_Clear(LIST) LinkedList_Clear( LIST, free )
#define RectList_Clear(LIST) LinkedList_Clear(LIST, free)

LCUI_END_HEADER

Expand Down
56 changes: 56 additions & 0 deletions src/gui/widget_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,62 @@ void Widget_SetTitleW(LCUI_Widget w, const wchar_t *title)
Widget_AddTask(w, LCUI_WTASK_TITLE);
}

LCUI_BOOL Widget_InVisibleArea(LCUI_Widget w)
{
LinkedListNode *node;
LCUI_RectF rect;
LCUI_Widget self, parent, child;
LCUI_WidgetStyle *style;

rect = w->box.padding;
/* If the size of the widget is not fixed, then set the maximum size to
* avoid it being judged invisible all the time. */
if (rect.width < 1 && Widget_HasAutoStyle(w, key_width)) {
rect.width = w->parent->box.padding.width;
}
if (rect.height < 1 && Widget_HasAutoStyle(w, key_height)) {
rect.height = w->parent->box.padding.height;
}
for (self = w, parent = w->parent; parent;
self = parent, parent = parent->parent) {
if (!Widget_IsVisible(parent)) {
return FALSE;
}
for (node = self->node_show.prev; node && node->prev;
node = node->prev) {
child = node->data;
style = &child->computed_style;
if (child->state < LCUI_WSTATE_LAYOUTED ||
child == self || !Widget_IsVisible(child)) {
continue;
}
DEBUG_MSG("rect: (%g,%g,%g,%g), child rect: "
"(%g,%g,%g,%g), child: %s %s\n",
rect.x, rect.y, rect.width, rect.height,
child->box.border.x, child->box.border.y,
child->box.border.width,
child->box.border.height, child->type,
child->id);
if (!LCUIRectF_IsIncludeRect(&child->box.border,
&rect)) {
continue;
}
if (style->opacity == 1.0f &&
style->background.color.alpha == 255) {
return FALSE;
}
}
rect.x += parent->box.padding.x;
rect.y += parent->box.padding.y;
LCUIRectF_ValidateArea(&rect, parent->box.padding.width,
parent->box.padding.height);
if (rect.width < 1 || rect.height < 1) {
return FALSE;
}
}
return TRUE;
}

void Widget_GenerateSelfHash(LCUI_Widget widget)
{
int i;
Expand Down
14 changes: 12 additions & 2 deletions src/gui/widget_task.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,14 @@ static size_t Widget_UpdateChildren(LCUI_Widget w, LCUI_WidgetTaskContext ctx)

data = (LCUI_WidgetRulesData)w->rules;
if (data) {
if (data->rules.only_on_visible) {
if (!Widget_InVisibleArea(w)) {
DEBUG_MSG("%s %s: is not visible\n", w->type,
w->id);
return 0;
}
}
DEBUG_MSG("%s %s: is visible\n", w->type, w->id);
msec = clock();
}
if (!w->task.for_children) {
Expand Down Expand Up @@ -335,8 +343,10 @@ static size_t Widget_UpdateChildren(LCUI_Widget w, LCUI_WidgetTaskContext ctx)
}
break;
}
if (data && data->rules.on_update_progress) {
data->rules.on_update_progress(w, data->current_index);
if (data) {
if (data->rules.on_update_progress) {
data->rules.on_update_progress(w, data->current_index);
}
}
return total;
}
Expand Down
6 changes: 0 additions & 6 deletions src/util/rect.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,10 @@
* POSSIBILITY OF SUCH DAMAGE.
*/


//#define DEBUG
#include <stdlib.h>
#include <LCUI_Build.h>
#include <LCUI/LCUI.h>

#define LCUIRect_IsIncludeRect(a,b) \
b->x >= a->x && b->x + b->width <= a->x + a->width \
&& b->y >= a->y && b->y + b->height <= a->y + a->height

LCUI_Rect Rect(int x, int y, int w, int h)
{
LCUI_Rect r;
Expand Down

0 comments on commit 93049c4

Please sign in to comment.