diff --git a/components/rtgui/common/rtgui_system.c b/components/rtgui/common/rtgui_system.c index dce11bfaf5..556d679876 100644 --- a/components/rtgui/common/rtgui_system.c +++ b/components/rtgui/common/rtgui_system.c @@ -332,6 +332,7 @@ const char *event_string[] = "HIDE", /* the widget is going to be hidden */ "PAINT", /* paint on screen */ "TIMER", /* timer */ + "UPDATE_TOPLVL", /* update toplevel */ /* clip rect information */ "CLIP_INFO", /* clip rect info */ diff --git a/components/rtgui/include/rtgui/event.h b/components/rtgui/include/rtgui/event.h index 2a06f1850f..5acdf6225f 100644 --- a/components/rtgui/include/rtgui/event.h +++ b/components/rtgui/include/rtgui/event.h @@ -52,6 +52,7 @@ enum _rtgui_event_type RTGUI_EVENT_HIDE, /* the widget is going to be hidden */ RTGUI_EVENT_PAINT, /* paint on screen */ RTGUI_EVENT_TIMER, /* timer */ + RTGUI_EVENT_UPDATE_TOPLVL, /* update the toplevel */ /* clip rect information */ RTGUI_EVENT_CLIP_INFO, /* clip rect info */ @@ -255,6 +256,18 @@ struct rtgui_event_clip_info #define RTGUI_EVENT_SHOW_INIT(e) RTGUI_EVENT_INIT((e), RTGUI_EVENT_SHOW) #define RTGUI_EVENT_HIDE_INIT(e) RTGUI_EVENT_INIT((e), RTGUI_EVENT_HIDE) +struct rtgui_event_update_toplvl +{ + struct rtgui_event parent; + struct rtgui_win *toplvl; +}; + +#define RTGUI_EVENT_UPDATE_TOPLVL_INIT(e) \ + do { \ + RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_UPDATE_TOPLVL); \ + (e)->toplvl = RT_NULL; \ + } while (0) + /* * RTGUI Mouse and Keyboard Event */ @@ -388,6 +401,7 @@ union rtgui_event_generic struct rtgui_event_monitor monitor; struct rtgui_event_paint paint; struct rtgui_event_timer timer; + struct rtgui_event_update_toplvl update_toplvl; struct rtgui_event_clip_info clip_info; struct rtgui_event_mouse mouse; struct rtgui_event_kbd kbd; diff --git a/components/rtgui/include/rtgui/widgets/widget.h b/components/rtgui/include/rtgui/widgets/widget.h index 9b8fd439e9..e588df166f 100644 --- a/components/rtgui/include/rtgui/widgets/widget.h +++ b/components/rtgui/include/rtgui/widgets/widget.h @@ -184,6 +184,7 @@ void rtgui_widget_update_clip(rtgui_widget_t* widget); /* get the toplevel widget of widget */ struct rtgui_win* rtgui_widget_get_toplevel(rtgui_widget_t* widget); +rt_bool_t rtgui_widget_onupdate_toplvl(struct rtgui_object *object, struct rtgui_event *event); void rtgui_widget_show(rtgui_widget_t* widget); rt_bool_t rtgui_widget_onshow(struct rtgui_object *object, struct rtgui_event *event); diff --git a/components/rtgui/widgets/container.c b/components/rtgui/widgets/container.c index f5c954ddcf..7cfe455f54 100644 --- a/components/rtgui/widgets/container.c +++ b/components/rtgui/widgets/container.c @@ -38,26 +38,6 @@ static void _rtgui_container_destructor(rtgui_container_t *container) rtgui_object_destroy(RTGUI_OBJECT(container->layout_box)); } -static void _rtgui_container_update_toplevel(rtgui_container_t* container) -{ - struct rtgui_win *window; - struct rtgui_list_node* node; - - window = rtgui_widget_get_toplevel(RTGUI_WIDGET(container)); - - rtgui_list_foreach(node, &(container->children)) - { - rtgui_widget_t* child = rtgui_list_entry(node, rtgui_widget_t, sibling); - /* set child toplevel */ - child->toplevel = window; - - if (RTGUI_IS_CONTAINER(child)) - { - _rtgui_container_update_toplevel(RTGUI_CONTAINER(child)); - } - } -} - DEFINE_CLASS_TYPE(container, "container", RTGUI_WIDGET_TYPE, _rtgui_container_constructor, @@ -82,6 +62,24 @@ rt_bool_t rtgui_container_dispatch_event(rtgui_container_t *container, rtgui_eve return RT_FALSE; } +/* broadcast means that the return value of event handlers will be ignored. The + * events will always reach every child.*/ +rt_bool_t rtgui_container_broadcast_event(struct rtgui_container *container, struct rtgui_event *event) +{ + struct rtgui_list_node* node; + + rtgui_list_foreach(node, &(container->children)) + { + struct rtgui_widget* w; + w = rtgui_list_entry(node, struct rtgui_widget, sibling); + + if (RTGUI_OBJECT(w)->event_handler) + RTGUI_OBJECT(w)->event_handler(RTGUI_OBJECT(w), event) == RT_TRUE; + } + + return RT_FALSE; +} + rt_bool_t rtgui_container_dispatch_mouse_event(rtgui_container_t *container, struct rtgui_event_mouse* event) { /* handle in child widget */ @@ -164,6 +162,13 @@ rt_bool_t rtgui_container_event_handler(struct rtgui_object* object, struct rtgu rtgui_container_dispatch_event(container, event); break; + case RTGUI_EVENT_UPDATE_TOPLVL: + /* call parent handler */ + rtgui_widget_onupdate_toplvl(object, event); + /* update the children */ + rtgui_container_broadcast_event(container, event); + break; + default: /* call parent widget event handler */ return rtgui_widget_event_handler(RTGUI_OBJECT(widget), event); @@ -205,13 +210,10 @@ void rtgui_container_add_child(rtgui_container_t *container, rtgui_widget_t* chi if (RTGUI_WIDGET(container)->toplevel != RT_NULL && RTGUI_IS_TOPLEVEL(RTGUI_WIDGET(container)->toplevel)) { - child->toplevel = rtgui_widget_get_toplevel(RTGUI_WIDGET(container)); - - /* update all child toplevel */ - if (RTGUI_IS_CONTAINER(child)) - { - _rtgui_container_update_toplevel(RTGUI_CONTAINER(child)); - } + struct rtgui_event_update_toplvl eup; + RTGUI_EVENT_UPDATE_TOPLVL_INIT(&eup); + eup.toplvl = RTGUI_WIDGET(container)->toplevel; + rtgui_container_broadcast_event(container, (struct rtgui_event*)&eup); } } diff --git a/components/rtgui/widgets/notebook.c b/components/rtgui/widgets/notebook.c index 6b6f9ec49f..1192fd6e70 100644 --- a/components/rtgui/widgets/notebook.c +++ b/components/rtgui/widgets/notebook.c @@ -2,6 +2,7 @@ #include #include #include +#include #define RTGUI_NOTEBOOK_TAB_WIDTH 80 @@ -215,6 +216,16 @@ void rtgui_notebook_add(struct rtgui_notebook* notebook, const char* label, stru if (notebook->count - 1 != notebook->current) rtgui_widget_hide(child); + + if (RTGUI_WIDGET(notebook)->toplevel != RT_NULL && + RTGUI_IS_TOPLEVEL(RTGUI_WIDGET(notebook)->toplevel)) + { + struct rtgui_event_update_toplvl eup; + RTGUI_EVENT_UPDATE_TOPLVL_INIT(&eup); + eup.toplvl = RTGUI_WIDGET(notebook)->toplevel; + if (RTGUI_OBJECT(child)->event_handler) + RTGUI_OBJECT(child)->event_handler(RTGUI_OBJECT(child), (struct rtgui_event*)&eup); + } } void rtgui_notebook_remove(struct rtgui_notebook* notebook, rt_uint16_t index) @@ -333,6 +344,19 @@ static rt_bool_t _rtgui_notebook_current_widget_handle(struct rtgui_notebook *no return RT_FALSE; } +static void _rtgui_notebook_all_widget_handle(struct rtgui_notebook *notebook, + struct rtgui_event *event) +{ + struct rtgui_object *object; + int i; + for (i = 0; i < notebook->count; i++) + { + object = RTGUI_OBJECT(notebook->childs[i].widget); + if (object->event_handler) + object->event_handler(object, event); + } +} + rt_bool_t rtgui_notebook_event_handler(struct rtgui_object* object, struct rtgui_event* event) { struct rtgui_notebook* notebook; @@ -362,6 +386,12 @@ rt_bool_t rtgui_notebook_event_handler(struct rtgui_object* object, struct rtgui return _rtgui_notebook_current_widget_handle(notebook, event); case RTGUI_EVENT_KBD: return _rtgui_notebook_current_widget_handle(notebook, event); + case RTGUI_EVENT_UPDATE_TOPLVL: + /* update myself */ + rtgui_widget_onupdate_toplvl(object, event); + /* update all the widgets in myself */ + _rtgui_notebook_all_widget_handle(notebook, event); + return RT_FALSE; default: /* use parent event handler */ return rtgui_widget_event_handler(object, event); diff --git a/components/rtgui/widgets/widget.c b/components/rtgui/widgets/widget.c index dbdd644ce2..97ff00fea9 100644 --- a/components/rtgui/widgets/widget.c +++ b/components/rtgui/widgets/widget.c @@ -145,13 +145,6 @@ void rtgui_widget_set_parent(rtgui_widget_t* widget, rtgui_widget_t* parent) { /* set parent and toplevel widget */ widget->parent = parent; - - /* update children toplevel */ - if (parent->toplevel != RT_NULL && - RTGUI_IS_TOPLEVEL(parent->toplevel)) - { - widget->toplevel = rtgui_widget_get_toplevel(parent); - } } void rtgui_widget_get_extent(rtgui_widget_t* widget, rtgui_rect_t *rect) @@ -402,6 +395,22 @@ struct rtgui_win* rtgui_widget_get_toplevel(rtgui_widget_t* widget) return RTGUI_WIN(r); } +rt_bool_t rtgui_widget_onupdate_toplvl(struct rtgui_object *object, struct rtgui_event *event) +{ + struct rtgui_widget *widget; + struct rtgui_event_update_toplvl *eup; + + RT_ASSERT(object); + RT_ASSERT(event); + + widget = RTGUI_WIDGET(object); + eup = (struct rtgui_event_update_toplvl*)event; + + widget->toplevel = eup->toplvl; + + return RT_FALSE; +} + rt_bool_t rtgui_widget_event_handler(struct rtgui_object* object, rtgui_event_t* event) { RT_ASSERT(object != RT_NULL); @@ -413,6 +422,8 @@ rt_bool_t rtgui_widget_event_handler(struct rtgui_object* object, rtgui_event_t* return rtgui_widget_onshow(object, event); case RTGUI_EVENT_HIDE: return rtgui_widget_onhide(object, event); + case RTGUI_EVENT_UPDATE_TOPLVL: + return rtgui_widget_onupdate_toplvl(object, event); #ifndef RTGUI_USING_SMALL_SIZE case RTGUI_EVENT_PAINT: if (widget->on_draw != RT_NULL)