improve dialog_highlighter

This commit is contained in:
xianjimli 2020-10-20 13:49:37 +08:00
parent 0258c4a275
commit aa88310a2f
5 changed files with 209 additions and 2 deletions

View File

@ -80,6 +80,26 @@ ret_t dialog_highlighter_set_bg_clip_rect(dialog_highlighter_t* h, rect_t* clip_
return RET_OK;
}
ret_t dialog_highlighter_set_system_bar_alpha(dialog_highlighter_t* h, uint8_t alpha) {
return_value_if_fail(h != NULL && h->vt != NULL, RET_BAD_PARAMS);
if (h->vt->set_system_bar_alpha != NULL) {
return h->vt->set_system_bar_alpha(h, alpha);
}
return RET_NOT_IMPL;
}
uint8_t dialog_highlighter_get_alpha(dialog_highlighter_t* h, float_t percent) {
return_value_if_fail(h != NULL && h->vt != NULL, 0x0);
if (h->vt->get_alpha != NULL) {
return h->vt->get_alpha(h, percent);
}
return 0x0;
}
ret_t dialog_highlighter_draw(dialog_highlighter_t* h, float_t percent) {
return_value_if_fail(h != NULL && h->vt != NULL, RET_BAD_PARAMS);
@ -90,6 +110,16 @@ ret_t dialog_highlighter_draw(dialog_highlighter_t* h, float_t percent) {
return RET_NOT_IMPL;
}
ret_t dialog_highlighter_draw_mask(dialog_highlighter_t* h, canvas_t* c, float_t percent) {
return_value_if_fail(h != NULL && h->vt != NULL, RET_BAD_PARAMS);
if (h->vt->draw_mask != NULL) {
return h->vt->draw_mask(h, c, percent);
}
return RET_NOT_IMPL;
}
bool_t dialog_highlighter_is_dynamic(dialog_highlighter_t* h) {
if (h != NULL && h->vt != NULL && h->vt->is_dynamic != NULL) {
return h->vt->is_dynamic(h);

View File

@ -29,6 +29,9 @@ BEGIN_C_DECLS
struct _dialog_highlighter_t;
typedef struct _dialog_highlighter_t dialog_highlighter_t;
typedef ret_t (*dialog_highlighter_set_system_bar_alpha_t)(dialog_highlighter_t* h, uint8_t alpha);
typedef uint8_t (*dialog_highlighter_get_alpha_t)(dialog_highlighter_t* h, float_t percent);
typedef ret_t (*dialog_highlighter_draw_mask_t)(dialog_highlighter_t* h, canvas_t* c, float_t percent);
typedef ret_t (*dialog_highlighter_prepare_t)(dialog_highlighter_t* h, canvas_t* c);
typedef ret_t (*dialog_highlighter_draw_t)(dialog_highlighter_t* h, float_t percent);
typedef bool_t (*dialog_highlighter_is_dynamic_t)(dialog_highlighter_t* h);
@ -42,8 +45,11 @@ typedef struct _dialog_highlighter_vtable_t {
uint32_t size;
dialog_highlighter_draw_t draw;
dialog_highlighter_prepare_t prepare;
dialog_highlighter_draw_mask_t draw_mask;
dialog_highlighter_get_alpha_t get_alpha;
dialog_highlighter_is_dynamic_t is_dynamic;
dialog_highlighter_on_destroy_t on_destroy;
dialog_highlighter_set_system_bar_alpha_t set_system_bar_alpha;
} dialog_highlighter_vtable_t;
/**
@ -148,6 +154,26 @@ ret_t dialog_highlighter_prepare(dialog_highlighter_t* h, canvas_t* c);
*/
ret_t dialog_highlighter_prepare_ex(dialog_highlighter_t* h, canvas_t* c, canvas_t* canvas_offline);
/**
* @method dialog_highlighter_set_system_bar_alpha
* sytem_bar
* @param {dialog_highlighter_t*} h
* @param {uint8_t} alpha sytem_bar
*
* @return {ret_t} RET_OK表示成功
*/
ret_t dialog_highlighter_set_system_bar_alpha(dialog_highlighter_t* h, uint8_t alpha);
/**
* @method dialog_highlighter_get_alpha
*
* @param {dialog_highlighter_t*} h
* @param {float_t} percent
*
* @return {uint8_t}
*/
uint8_t dialog_highlighter_get_alpha(dialog_highlighter_t* h, float_t percent);
/**
* @method dialog_highlighter_draw
*
@ -158,6 +184,17 @@ ret_t dialog_highlighter_prepare_ex(dialog_highlighter_t* h, canvas_t* c, canvas
*/
ret_t dialog_highlighter_draw(dialog_highlighter_t* h, float_t percent);
/**
* @method dialog_highlighter_draw_mask
*
* @param {dialog_highlighter_t*} h
* @param {canvas_t*} c
* @param {float_t} percent
*
* @return {ret_t} RET_OK表示成功
*/
ret_t dialog_highlighter_draw_mask(dialog_highlighter_t* h, canvas_t* c, float_t percent);
/**
* @method dialog_highlighter_is_dynamic
* (便)

View File

@ -36,6 +36,55 @@ static ret_t dialog_highlighter_default_draw_mask(canvas_t* c, uint8_t alpha) {
return RET_OK;
}
static ret_t dialog_highlighter_default_draw_mask_system_bar(canvas_t* c, uint8_t alpha) {
if (alpha > 1) {
widget_t* widget = window_manager();
color_t mask = color_init(0, 0, 0, alpha);
WIDGET_FOR_EACH_CHILD_BEGIN_R(widget, iter, i)
if (widget_is_system_bar(iter)) {
canvas_set_fill_color(c, mask);
canvas_fill_rect(c, iter->x, iter->y, iter->w, iter->h);
}
WIDGET_FOR_EACH_CHILD_END()
}
return RET_OK;
}
static ret_t dialog_highlighter_default_draw_mask_from_percent(dialog_highlighter_t* h, canvas_t* c, float_t percent) {
dialog_highlighter_default_t* dh = (dialog_highlighter_default_t*)h;
return_value_if_fail(dh != NULL && c != NULL, RET_BAD_PARAMS);
if (dh->start_alpha != dh->end_alpha) {
uint8_t a = ((dh->end_alpha - dh->start_alpha) * percent) + dh->start_alpha;
return dialog_highlighter_default_draw_mask(c, a);
} else {
return dialog_highlighter_default_draw_mask(c, dh->end_alpha);
}
}
ret_t dialog_highlighter_default_set_system_bar_alpha(dialog_highlighter_t* h, uint8_t alpha) {
dialog_highlighter_default_t* dh = (dialog_highlighter_default_t*)h;
return_value_if_fail(dh != NULL, RET_BAD_PARAMS);
/* 计算叠加的 system_bar 的高亮透明度 */
dh->system_bar_alpha = (dh->system_bar_alpha * (0xff - alpha)) >> 8;
return RET_OK;
}
uint8_t dialog_highlighter_default_get_alpha(dialog_highlighter_t* h, float_t percent) {
dialog_highlighter_default_t* dh = (dialog_highlighter_default_t*)h;
return_value_if_fail(dh != NULL, 0x0);
if (dh->start_alpha == dh->end_alpha) {
return dh->start_alpha;
} else {
return (0xff * (dh->end_alpha - dh->start_alpha) * percent) / 0xff;
}
}
static ret_t dialog_highlighter_default_prepare(dialog_highlighter_t* h, canvas_t* c) {
dialog_highlighter_default_t* dh = (dialog_highlighter_default_t*)h;
return_value_if_fail(h != NULL && h->vt != NULL && c != NULL, RET_BAD_PARAMS);
@ -79,6 +128,10 @@ static ret_t dialog_highlighter_default_draw(dialog_highlighter_t* h, float_t pe
if (dh->start_alpha != dh->end_alpha) {
uint8_t a = ((dh->end_alpha - dh->start_alpha) * percent) + dh->start_alpha;
dialog_highlighter_default_draw_mask(c, a);
} else {
/* 解决黑色色块绘制到贴图导致 system_bar 的颜色不同步的问题 */
uint8_t a = 0xff - ((dh->system_bar_alpha * (0xff - dh->end_alpha)) >> 8);
dialog_highlighter_default_draw_mask_system_bar(c, a);
}
return RET_OK;
@ -95,6 +148,9 @@ static const dialog_highlighter_vtable_t s_dialog_highlighter_default_vt = {
.desc = "dialog_highlighter_default_t",
.size = sizeof(dialog_highlighter_default_t),
.prepare = dialog_highlighter_default_prepare,
.draw_mask = dialog_highlighter_default_draw_mask_from_percent,
.set_system_bar_alpha = dialog_highlighter_default_set_system_bar_alpha,
.get_alpha = dialog_highlighter_default_get_alpha,
.is_dynamic = dialog_highlighter_default_is_dynamic,
.draw = dialog_highlighter_default_draw};
@ -106,6 +162,7 @@ dialog_highlighter_t* dialog_highlighter_default_create(object_t* args) {
dh->end_alpha = 0;
dh->start_alpha = 0;
dh->system_bar_alpha = 0xff;
if (object_get_prop(args, DIALOG_HIGHLIGHTER_DEFAULT_ARG_ALPHA, &v) == RET_OK) {
dh->start_alpha = value_int(&v);

View File

@ -51,6 +51,12 @@ struct _dialog_highlighter_default_t {
* alpha()alpha值
*/
uint8_t end_alpha;
/**
* @property {uint8_t} system_bar_alpha
* system_bar
*/
uint8_t system_bar_alpha;
};
/**

View File

@ -143,6 +143,59 @@ ret_t window_manager_default_snap_curr_window(widget_t* widget, widget_t* curr_w
return RET_OK;
}
static ret_t window_manager_default_snap_prev_window_draw_dialog_highlighter_and_get_alpha(widget_t* widget, canvas_t* c, uint8_t* alpha){
value_t v;
return_value_if_fail(widget != NULL && c != NULL, FALSE);
if (widget_get_prop(widget, WIDGET_PROP_HIGHLIGHT, &v) == RET_OK) {
const char* args = value_str(&v);
dialog_highlighter_factory_t* f = dialog_highlighter_factory();
dialog_highlighter_t* dialog_highlighter = dialog_highlighter_factory_create_highlighter(f, args, widget);
if (dialog_highlighter != NULL) {
dialog_highlighter_draw_mask(dialog_highlighter, c, 1.0f);
*alpha = dialog_highlighter_get_alpha(dialog_highlighter, 1.0f);
widget_off_by_func(widget, EVT_DESTROY, dialog_highlighter_on_dialog_destroy, dialog_highlighter);
dialog_highlighter_destroy(dialog_highlighter);
return RET_OK;
}
}
return RET_FAIL;
}
static bool_t window_manager_default_is_dialog_highlighter(widget_t* widget) {
value_t v;
return_value_if_fail(widget != NULL, FALSE);
if (widget_is_dialog(widget) && widget_get_prop(widget, WIDGET_PROP_HIGHLIGHT, &v) == RET_OK) {
return TRUE;
}
return FALSE;
}
static widget_t* window_manager_default_find_top_dialog_highlighter(widget_t* widget, widget_t* prev_win, widget_t* curr_win) {
int32_t i = 0;
widget_t* dialog = NULL;
widget_t** children = (widget_t**)(widget->children->elms);
i = widget->children->size - 1;
for (; i >= 0; i--) {
value_t v;
widget_t* iter = children[i];
if (iter == prev_win) {
break;
}
if (iter == curr_win) {
continue;
}
if (window_manager_default_is_dialog_highlighter(iter)) {
dialog = iter;
break;
}
}
return dialog;
}
ret_t window_manager_default_snap_prev_window(widget_t* widget, widget_t* prev_win, bitmap_t* img) {
rect_t r = {0};
canvas_t* c = NULL;
@ -181,6 +234,15 @@ ret_t window_manager_default_snap_prev_window(widget_t* widget, widget_t* prev_w
if (widget_is_system_bar(iter) || !iter->visible) continue;
/* 过滤 curr_win 的对象 */
if (iter != wm->curr_win) {
/* 给前面的高亮对话框叠加黑色色块 */
if (widget_is_dialog(iter)) {
uint8_t a = 0x0;
window_manager_default_snap_prev_window_draw_dialog_highlighter_and_get_alpha(iter, canvas, &a);
if (dialog_highlighter != NULL) {
dialog_highlighter_set_system_bar_alpha(dialog_highlighter, a);
}
}
ENSURE(widget_paint(iter, canvas) == RET_OK);
}
}
@ -473,7 +535,7 @@ static ret_t window_manager_default_close_window(widget_t* widget, widget_t* win
widget_remove_child(widget, window);
idle_add(window_manager_idle_destroy_window, window);
/* 这里是解决没有结束动画,但是 prev_win 是高亮的对话框的情况 */
prev_win = window_manager_get_top_window(widget);
if (prev_win != NULL) {
if (!widget_is_keyboard(window)) {
@ -649,9 +711,11 @@ static ret_t window_manager_animate_done_set_window_foreground(widget_t* widget,
static ret_t window_manager_animate_done(widget_t* widget) {
window_manager_default_t* wm = WINDOW_MANAGER_DEFAULT(widget);
bool_t curr_win_is_keyboard = widget_is_keyboard(wm->animator->curr_win);
bool_t curr_win_is_normal_window = widget_is_normal_window(wm->animator->curr_win);
if (wm->animator != NULL) {
bool_t is_open = wm->animator->open;
widget_t* top_dialog_highligth = NULL;
widget_t* prev_win = wm->animator->prev_win;
widget_t* curr_win = wm->animator->curr_win;
window_animator_destroy(wm->animator);
@ -661,15 +725,28 @@ static ret_t window_manager_animate_done(widget_t* widget) {
wm->ignore_user_input = FALSE;
if (is_open) {
/* 结束打开窗口动画后 */
if (!curr_win_is_keyboard) {
window_manager_dispatch_window_event(prev_win, EVT_WINDOW_TO_BACKGROUND);
}
if (!curr_win_is_normal_window) {
top_dialog_highligth = window_manager_default_find_top_dialog_highlighter(widget, prev_win, curr_win_is_keyboard ? curr_win : NULL);
}
window_manager_dispatch_window_event(curr_win, EVT_WINDOW_OPEN);
} else {
/* 结束关闭窗口动画后 */
if (!curr_win_is_keyboard) {
window_manager_animate_done_set_window_foreground(widget, prev_win, curr_win);
window_manager_create_highlighter(widget, prev_win);
}
top_dialog_highligth = window_manager_default_find_top_dialog_highlighter(widget, prev_win, curr_win);
}
/* 制作一张没有最后一个对话框的高亮背景贴图 */
if (top_dialog_highligth != NULL) {
widget_t* tmp_curr_win = wm->curr_win;
wm->curr_win = top_dialog_highligth;
window_manager_create_highlighter(widget, top_dialog_highligth);
wm->curr_win = tmp_curr_win;
}
if (wm->pending_close_window != NULL) {