add vpage widget

This commit is contained in:
lixianjing 2021-06-09 17:32:32 +08:00
parent 53dbeda52b
commit 77cf9a0f78
7 changed files with 518 additions and 2 deletions

View File

@ -0,0 +1,65 @@
<window text="VPage V Translate">
<pages name="pages" x="31%" y="0" w="68%" h="100%" style="at_top">
<vpage name="page1" w="100%" h="100%" ui_asset="tab_button_view_page1" anim_hint="vtranslate" />
<vpage name="page2" w="100%" h="100%" ui_asset="tab_button_view_page2" anim_hint="vtranslate" />
<vpage name="page3" w="100%" h="100%" anim_hint="vtranslate" >
<label x="c" y="m" w="200" h="30" text="page3" />
<button x="c" y="b:10" w="128" h="30" text="close" on:click="back()"/>
</vpage>
<vpage name="page4" w="100%" h="100%" anim_hint="vtranslate" >
<label x="c" y="m" w="200" h="30" text="page4" />
<button x="c" y="b:10" w="128" h="30" text="close" on:click="back()"/>
</vpage>
<vpage w="100%" h="100%" anim_hint="vtranslate" >
<label x="c" y="m" w="200" h="30" text="page5" />
<button x="c" y="b:10" w="128" h="30" text="close" on:click="back()"/>
</vpage>
<vpage w="100%" h="100%" anim_hint="vtranslate" >
<label x="c" y="m" w="200" h="30" text="page6" />
<button x="c" y="b:10" w="128" h="30" text="close" on:click="back()"/>
</vpage>
<vpage w="100%" h="100%" anim_hint="vtranslate" >
<label x="c" y="m" w="200" h="30" text="page7" />
<button x="c" y="b:10" w="128" h="30" text="close" on:click="back()"/>
</vpage>
<vpage w="100%" h="100%" anim_hint="vtranslate" >
<label x="c" y="m" w="200" h="30" text="page8" />
<button x="c" y="b:10" w="128" h="30" text="close" on:click="back()"/>
</vpage>
<vpage w="100%" h="100%" anim_hint="vtranslate" >
<label x="c" y="m" w="200" h="30" text="page9" />
<button x="c" y="b:10" w="128" h="30" text="close" on:click="back()"/>
</vpage>
<vpage w="100%" h="100%" anim_hint="vtranslate" >
<label x="c" y="m" w="200" h="30" text="page10" />
<button x="c" y="b:10" w="128" h="30" text="close" on:click="back()"/>
</vpage>
<vpage w="100%" h="100%" anim_hint="vtranslate" >
<label x="c" y="m" w="200" h="30" text="page11" />
<button x="c" y="b:10" w="128" h="30" text="close" on:click="back()"/>
</vpage>
<vpage w="100%" h="100%" anim_hint="vtranslate" >
<label x="c" y="m" w="200" h="30" text="page12" />
<button x="c" y="b:10" w="128" h="30" text="close" on:click="back()"/>
</vpage>
</pages>
<list_view x="0" y="0" w="30%" h="100%" item_height="40" auto_hide_scroll_bar="true">
<scroll_view name="view" x="0" y="0" w="-12" h="100%">
<tab_button name="b1" text="page1" value="true" />
<tab_button name="b2" text="page2" />
<tab_button name="b3" text="page3" />
<tab_button name="b4" text="page4" />
<tab_button name="b5" text="page5" />
<tab_button name="b6" text="page6" />
<tab_button name="b7" text="page7" />
<tab_button name="b8" text="page8" />
<tab_button name="b9" text="page9" />
<tab_button name="b10" text="page10" />
<tab_button name="b11" text="page11" />
<tab_button name="b12" text="page12" />
</scroll_view>
<scroll_bar_d name="bar" x="right" y="0" w="12" h="100%" value="0"/>
</list_view>
</window>

View File

@ -4,6 +4,7 @@
* 重构pages。
* 修复ui\_builder不能重入的问题。
* 增加window\_manager\_set\_ignore\_input\_events。
* 增加vpage扩展控件(配合pages控件使用可以自动加载/卸载页面, 并提供入场/出场动画)
2021/06/08
* 完善编译脚本(感谢兆坤提供补丁)

View File

@ -22,6 +22,7 @@
#ifndef AWTK_EXT_WIDGETS_H
#define AWTK_EXT_WIDGETS_H
#include "vpage/vpage.h"
#include "switch/switch.h"
#include "gauge/gauge.h"
#include "gauge/gauge_pointer.h"

View File

@ -277,8 +277,6 @@ ret_t window_manager_dispatch_input_event(widget_t* widget, event_t* e) {
return_value_if_fail(wm->vt->dispatch_input_event != NULL, RET_BAD_PARAMS);
if (wm->ignore_input_events) {
log_debug("waiting cursort, ignore input events");
return RET_STOP;
}

View File

@ -19,7 +19,16 @@
*
*/
#if defined(WITH_SDL)
#ifndef WITH_WIDGET_VPAGE
#define WITH_WIDGET_VPAGE
#endif /*WITH_WIDGET_VPAGE*/
#endif /*WITH_SDL*/
#include "ext_widgets.h"
#include "vpage/vpage.h"
#include "switch/switch.h"
#include "gauge/gauge.h"
#include "mledit/mledit.h"
@ -110,6 +119,11 @@ ret_t tk_ext_widgets_init(void) {
widget_factory_register(f, "guage", gauge_create);
widget_factory_register(f, "guage_pointer", gauge_pointer_create);
#ifdef WITH_WIDGET_VPAGE
widget_factory_register(f, WIDGET_TYPE_VPAGE, vpage_create);
#endif /*WITH_WIDGET_VPAGE*/
#ifdef TK_FILE_BROWSER_VIEW_H
widget_factory_register(f, WIDGET_TYPE_FILE_BROWSER_VIEW, file_browser_view_create);
#endif /*TK_FILE_BROWSER_VIEW_H*/

View File

@ -0,0 +1,259 @@
/**
* File: vpage.c
* Author: AWTK Develop Team
* Brief: (/)
*
* Copyright (c) 2021 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2021-06-09 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/mem.h"
#include "tkc/utils.h"
#include "base/ui_loader.h"
#include "base/window_manager.h"
#include "ui_loader/ui_serializer.h"
#include "widget_animators/widget_animator_prop.h"
#include "vpage.h"
ret_t vpage_set_ui_asset(widget_t* widget, const char* ui_asset) {
vpage_t* vpage = VPAGE(widget);
return_value_if_fail(vpage != NULL, RET_BAD_PARAMS);
vpage->ui_asset = tk_str_copy(vpage->ui_asset, ui_asset);
return RET_OK;
}
ret_t vpage_set_anim_hint(widget_t* widget, const char* anim_hint) {
vpage_t* vpage = VPAGE(widget);
return_value_if_fail(vpage != NULL, RET_BAD_PARAMS);
vpage->anim_hint = tk_str_copy(vpage->anim_hint, anim_hint);
return RET_OK;
}
static ret_t vpage_get_prop(widget_t* widget, const char* name, value_t* v) {
vpage_t* vpage = VPAGE(widget);
return_value_if_fail(vpage != NULL && name != NULL && v != NULL, RET_BAD_PARAMS);
if (tk_str_eq(VPAGE_PROP_UI_ASSET, name)) {
value_set_str(v, vpage->ui_asset);
return RET_OK;
} else if (tk_str_eq(WIDGET_PROP_ANIM_HINT, name)) {
value_set_str(v, vpage->anim_hint);
return RET_OK;
}
return RET_NOT_FOUND;
}
static ret_t vpage_set_prop(widget_t* widget, const char* name, const value_t* v) {
return_value_if_fail(widget != NULL && name != NULL && v != NULL, RET_BAD_PARAMS);
if (tk_str_eq(VPAGE_PROP_UI_ASSET, name)) {
vpage_set_ui_asset(widget, value_str(v));
return RET_OK;
} else if (tk_str_eq(WIDGET_PROP_ANIM_HINT, name)) {
vpage_set_anim_hint(widget, value_str(v));
return RET_OK;
}
return RET_NOT_FOUND;
}
static ret_t vpage_on_destroy(widget_t* widget) {
vpage_t* vpage = VPAGE(widget);
return_value_if_fail(widget != NULL && vpage != NULL, RET_BAD_PARAMS);
TKMEM_FREE(vpage->ui_asset);
TKMEM_FREE(vpage->anim_hint);
return RET_OK;
}
static ret_t vpage_dispatch_event(widget_t* widget, int32_t etype) {
event_t e = event_init(etype, widget);
return widget_dispatch_async(widget, &e);
}
static ret_t vpage_on_enter_done(widget_t* widget) {
vpage_dispatch_event(widget, EVT_VPAGE_OPEN);
return RET_OK;
}
static ret_t vpage_on_enter_animation_done(void* ctx, event_t* e) {
return vpage_on_enter_done(WIDGET(ctx));
}
static ret_t vpage_on_enter(widget_t* widget, uint32_t index, uint32_t old_index) {
vpage_t* vpage = VPAGE(widget);
widget_animator_t* am = NULL;
uint32_t nr = widget_count_children(widget->parent);
bool_t can_animate = old_index < nr && widget_is_window_opened(widget);
if (vpage->ui_asset != NULL) {
widget_t* children = ui_loader_load_widget(vpage->ui_asset);
event_t will_open = event_init(EVT_WINDOW_WILL_OPEN, children);
return_value_if_fail(children != NULL, RET_BAD_PARAMS);
widget_add_child(widget, children);
/*some widget depends on will open to initialize*/
widget_dispatch_recursive(children, &will_open);
}
widget_set_visible(widget, TRUE);
vpage_dispatch_event(widget, EVT_VPAGE_WILL_OPEN);
window_manager_set_ignore_input_events(window_manager(), FALSE);
if (vpage->anim_hint != NULL && can_animate) {
if (tk_str_eq(vpage->anim_hint, "htranslate")) {
am = widget_animator_prop_create(widget, TK_ANIMATING_TIME, 0, EASING_SIN_INOUT, "x");
if (old_index < index) {
widget_animator_prop_set_params(am, widget->w, 0);
} else {
widget_animator_prop_set_params(am, -widget->w, 0);
}
} else {
am = widget_animator_prop_create(widget, TK_ANIMATING_TIME, 0, EASING_SIN_INOUT, "y");
if (old_index < index) {
widget_animator_prop_set_params(am, widget->h, 0);
} else {
widget_animator_prop_set_params(am, -widget->h, 0);
}
}
if (am != NULL) {
widget_animator_start(am);
widget_animator_on(am, EVT_ANIM_END, vpage_on_enter_animation_done, widget);
} else {
vpage_on_enter_done(widget);
}
} else {
vpage_on_enter_done(widget);
}
return RET_OK;
}
static ret_t vpage_on_leave_done(widget_t* widget) {
vpage_t* vpage = VPAGE(widget);
if (vpage->ui_asset != NULL) {
vpage_dispatch_event(widget, EVT_VPAGE_CLOSE);
widget_destroy_children(widget);
}
widget_set_visible(widget, FALSE);
window_manager_set_ignore_input_events(window_manager(), FALSE);
return RET_OK;
}
static ret_t vpage_on_leave_animation_done(void* ctx, event_t* e) {
vpage_on_leave_done(WIDGET(ctx));
return RET_OK;
}
static ret_t vpage_on_leave(widget_t* widget, uint32_t index, uint32_t new_index) {
vpage_t* vpage = VPAGE(widget);
if (vpage->anim_hint != NULL) {
widget_animator_t* am = NULL;
if (tk_str_eq(vpage->anim_hint, "htranslate")) {
am = widget_animator_prop_create(widget, TK_ANIMATING_TIME, 0, EASING_SIN_INOUT, "x");
if (new_index < index) {
widget_animator_prop_set_params(am, 0, widget->w);
} else {
widget_animator_prop_set_params(am, 0, -widget->w);
}
} else {
am = widget_animator_prop_create(widget, TK_ANIMATING_TIME, 0, EASING_SIN_INOUT, "y");
if (new_index < index) {
widget_animator_prop_set_params(am, 0, widget->h);
} else {
widget_animator_prop_set_params(am, 0, -widget->h);
}
}
if (am != NULL) {
widget_animator_start(am);
widget_set_visible(widget, TRUE);
window_manager_set_ignore_input_events(window_manager(), TRUE);
widget_animator_on(am, EVT_ANIM_END, vpage_on_leave_animation_done, widget);
} else {
vpage_on_leave_done(widget);
}
} else {
vpage_on_leave_done(widget);
}
return RET_OK;
}
static ret_t vpage_on_current_page_changed(void* ctx, event_t* e) {
widget_t* widget = WIDGET(ctx);
value_change_event_t* evt = value_change_event_cast(e);
uint32_t old_index = value_uint32(&(evt->old_value));
uint32_t new_index = value_uint32(&(evt->new_value));
uint32_t index = widget_index_of(widget);
log_debug("%u -> %u %u\n", old_index, new_index, index);
if (old_index == index) {
vpage_on_leave(widget, index, new_index);
} else if (new_index == index) {
vpage_on_enter(widget, index, old_index);
}
return RET_OK;
}
static ret_t vpage_on_attach_parent(widget_t* widget, widget_t* parent) {
return widget_on(parent, EVT_VALUE_CHANGED, vpage_on_current_page_changed, widget);
}
static ret_t vpage_on_detach_parent(widget_t* widget, widget_t* parent) {
return widget_off_by_ctx(parent, widget);
}
const char* s_vpage_properties[] = {VPAGE_PROP_UI_ASSET, WIDGET_PROP_ANIM_HINT, NULL};
TK_DECL_VTABLE(vpage) = {.size = sizeof(vpage_t),
.type = WIDGET_TYPE_VPAGE,
.clone_properties = s_vpage_properties,
.persistent_properties = s_vpage_properties,
.parent = TK_PARENT_VTABLE(widget),
.create = vpage_create,
.set_prop = vpage_set_prop,
.get_prop = vpage_get_prop,
.on_attach_parent = vpage_on_attach_parent,
.on_detach_parent = vpage_on_detach_parent,
.on_destroy = vpage_on_destroy};
widget_t* vpage_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h) {
widget_t* widget = widget_create(parent, TK_REF_VTABLE(vpage), x, y, w, h);
vpage_t* vpage = VPAGE(widget);
return_value_if_fail(vpage != NULL, NULL);
return widget;
}
widget_t* vpage_cast(widget_t* widget) {
return_value_if_fail(WIDGET_IS_INSTANCE_OF(widget, vpage), NULL);
return widget;
}

View File

@ -0,0 +1,178 @@
/**
* File: vpage.h
* Author: AWTK Develop Team
* Brief: (/, /)
*
* Copyright (c) 2021 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2021-06-09 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_VPAGE_H
#define TK_VPAGE_H
#include "base/widget.h"
BEGIN_C_DECLS
/**
* @class vpage_t
* @parent widget_t
* @annotation ["scriptable","design","widget"]
* (//)
*
* > pages的直接子控件使用
*
* ui_asset:
*
* * EVT\_VPAGE\_CLOSE消息
* * EVT\_VPAGE\_WILL\_OPEN消息 EVT\_VPAGE\_CLOSE消息
*
* vpage\_t也可以当作普通view嵌入到pages中tab控件在切换时具有动画效果
*
* xml中使用"vpage"
*
* ```xml
* <!-- ui -->
* <vpage x="c" y="50" w="100" h="100" ui_asset="mypage"/>
* ```
*
* style来设置控件的显示风格()
*
* ```xml
* <!-- style -->
* <vpage>
* <style name="default">
* <normal />
* </style>
* </vpage>
* ```
*/
typedef struct _vpage_t {
widget_t widget;
/**
* @property {char*} ui_asset
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* UI资源名称
*/
char* ui_asset;
/**
* @property {char*} anim_hint
* @annotation ["set_prop","get_prop","readable","persitent","design","scriptable"]
* (vtranslate: htranslate: )
*/
char* anim_hint;
} vpage_t;
/**
* @enum vpage_event_t
* @annotation ["scriptable"]
* @prefix EVT_
*
*/
typedef enum _vpage_event_t {
/**
* @const EVT_VPAGE_WILL_OPEN
* ()
*/
EVT_VPAGE_WILL_OPEN = EVT_USER_START + 100,
/**
* @const EVT_VPAGE_OPEN
* ()
*/
EVT_VPAGE_OPEN,
/**
* @const EVT_VPAGE_CLOSE
* ()
*/
EVT_VPAGE_CLOSE
} vpage_event_t;
/**
* @event {event_t} EVT_VPAGE_WILL_OPEN
* ()
*/
/**
* @event {event_t} EVT_VPAGE_OPEN
* ()
*/
/**
* @event {event_t} EVT_VPAGE_CLOSE
* ()
*/
/**
* @method vpage_create
* @annotation ["constructor", "scriptable"]
* vpage对象
* @param {widget_t*} parent
* @param {xy_t} x x坐标
* @param {xy_t} y y坐标
* @param {wh_t} w
* @param {wh_t} h
*
* @return {widget_t*} vpage对象
*/
widget_t* vpage_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h);
/**
* @method vpage_cast
* vpage对象(使)
* @annotation ["cast", "scriptable"]
* @param {widget_t*} widget vpage对象
*
* @return {widget_t*} vpage对象
*/
widget_t* vpage_cast(widget_t* widget);
/**
* @method vpage_set_ui_asset
* UI资源名称
* @annotation ["scriptable"]
* @param {widget_t*} widget widget对象
* @param {const char*} ui_asset UI资源名称
*
* @return {ret_t} RET_OK表示成功
*/
ret_t vpage_set_ui_asset(widget_t* widget, const char* ui_asset);
/**
* @method vpage_set_anim_hint
* (vtranslate: htranslate: )
* @annotation ["scriptable"]
* @param {widget_t*} widget widget对象
* @param {const char*} anim_hint
*
* @return {ret_t} RET_OK表示成功
*/
ret_t vpage_set_anim_hint(widget_t* widget, const char* anim_hint);
#define VPAGE_PROP_UI_ASSET "ui_asset"
#define VPAGE_ANIM_VTRANSLATE "vtranslate"
#define VPAGE_ANIM_HTRANSLATE "htranslate"
#define WIDGET_TYPE_VPAGE "vpage"
#define VPAGE(widget) ((vpage_t*)(vpage_cast(WIDGET(widget))))
/*public for subclass and runtime type check*/
TK_EXTERN_VTABLE(vpage);
END_C_DECLS
#endif /*TK_VPAGE_H*/