diff options
Diffstat (limited to 'components/rtgui/widgets')
26 files changed, 5451 insertions, 6128 deletions
diff --git a/components/rtgui/widgets/about_view.c b/components/rtgui/widgets/about_view.c index 45f9a9431e..6bc012b255 100644 --- a/components/rtgui/widgets/about_view.c +++ b/components/rtgui/widgets/about_view.c @@ -1,101 +1,101 @@ -/*
- * File : about_view.c
- * This file is part of RTGUI in RT-Thread RTOS
- * COPYRIGHT (C) 2010, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2010-01-06 Bernard first version
- */
-
-#include <rtgui/rtgui_theme.h>
-#include <rtgui/widgets/about_view.h>
-
-static void _rtgui_about_view_constructor(struct rtgui_about_view *view)
-{
- /* default rect */
- struct rtgui_rect rect = {0, 0, 200, 200};
-
- /* set default widget rect and set event handler */
- rtgui_widget_set_event_handler(RTGUI_WIDGET(view),rtgui_about_view_event_handler);
- rtgui_widget_set_rect(RTGUI_WIDGET(view), &rect);
-
- RTGUI_WIDGET(view)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
-
- view->logo = RT_NULL;
- view->description = RT_NULL;
-
- RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(view)) = RTGUI_ALIGN_CENTER_VERTICAL;
-}
-
-DEFINE_CLASS_TYPE(aboutview, "aboutview",
- RTGUI_VIEW_TYPE,
- _rtgui_about_view_constructor,
- RT_NULL,
- sizeof(struct rtgui_about_view));
-
-void rtgui_about_view_ondraw(struct rtgui_about_view* view)
-{
- struct rtgui_rect rect;
- struct rtgui_dc* dc;
-
- dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view));
- if (dc == RT_NULL) return;
-
- rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
- rtgui_dc_fill_rect(dc, &rect);
-
- if (view->logo != RT_NULL)
- rtgui_image_blit(view->logo, dc, &rect);
-
- rect.y1 += view->logo->h + 5;
- if (view->description != RT_NULL)
- rtgui_dc_draw_text(dc, view->description, &rect);
-
- rect.y1 += rtgui_dc_get_gc(dc)->font->height;
- rtgui_dc_draw_hline(dc, rect.x1 + 3, rect.x2 - 3, rect.y1);
- RTGUI_DC_FC(dc) = white;
- rtgui_dc_draw_hline(dc, rect.x1 + 4, rect.x2 - 2, rect.y1 + 1);
-
- rtgui_dc_end_drawing(dc);
-}
-
-rt_bool_t rtgui_about_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
-{
- struct rtgui_about_view* view = RT_NULL;
-
- view = RTGUI_ABOUT_VIEW(widget);
- switch (event->type)
- {
- case RTGUI_EVENT_PAINT:
- rtgui_about_view_ondraw(view);
- return RT_FALSE;
- }
-
- /* use view event handler */
- return rtgui_view_event_handler(widget, event);
-}
-
-rtgui_about_view_t* rtgui_about_view_create(rtgui_image_t *logo, const char* description)
-{
- struct rtgui_about_view* view = RT_NULL;
-
- view = (struct rtgui_about_view*) rtgui_widget_create(RTGUI_ABOUT_VIEW_TYPE);
- if (view != RT_NULL)
- {
- view->logo = logo;
- view->description = description;
- }
-
- return view;
-}
-
-void rtgui_about_view_destroy(rtgui_about_view_t* view)
-{
- /* destroy view */
- rtgui_widget_destroy(RTGUI_WIDGET(view));
-}
+/* + * File : about_view.c + * This file is part of RTGUI in RT-Thread RTOS + * COPYRIGHT (C) 2010, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2010-01-06 Bernard first version + */ + +#include <rtgui/rtgui_theme.h> +#include <rtgui/widgets/about_view.h> + +static void _rtgui_about_view_constructor(struct rtgui_about_view *view) +{ + /* default rect */ + struct rtgui_rect rect = {0, 0, 200, 200}; + + /* set default widget rect and set event handler */ + rtgui_object_set_event_handler(RTGUI_OBJECT(view),rtgui_about_view_event_handler); + rtgui_widget_set_rect(RTGUI_WIDGET(view), &rect); + + RTGUI_WIDGET(view)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE; + + view->logo = RT_NULL; + view->description = RT_NULL; + + RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(view)) = RTGUI_ALIGN_CENTER_VERTICAL; +} + +DEFINE_CLASS_TYPE(aboutview, "aboutview", + RTGUI_CONTAINER_TYPE, + _rtgui_about_view_constructor, + RT_NULL, + sizeof(struct rtgui_about_view)); + +void rtgui_about_view_ondraw(struct rtgui_about_view* view) +{ + struct rtgui_rect rect; + struct rtgui_dc* dc; + + dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view)); + if (dc == RT_NULL) return; + + rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); + rtgui_dc_fill_rect(dc, &rect); + + if (view->logo != RT_NULL) + rtgui_image_blit(view->logo, dc, &rect); + + rect.y1 += view->logo->h + 5; + if (view->description != RT_NULL) + rtgui_dc_draw_text(dc, view->description, &rect); + + rect.y1 += rtgui_dc_get_gc(dc)->font->height; + rtgui_dc_draw_hline(dc, rect.x1 + 3, rect.x2 - 3, rect.y1); + RTGUI_DC_FC(dc) = white; + rtgui_dc_draw_hline(dc, rect.x1 + 4, rect.x2 - 2, rect.y1 + 1); + + rtgui_dc_end_drawing(dc); +} + +rt_bool_t rtgui_about_view_event_handler(struct rtgui_object* widget, struct rtgui_event* event) +{ + struct rtgui_about_view* view = RT_NULL; + + view = RTGUI_ABOUT_VIEW(widget); + switch (event->type) + { + case RTGUI_EVENT_PAINT: + rtgui_about_view_ondraw(view); + return RT_FALSE; + } + + /* use view event handler */ + return rtgui_container_event_handler(widget, event); +} + +rtgui_about_view_t* rtgui_about_view_create(rtgui_image_t *logo, const char* description) +{ + struct rtgui_about_view* view = RT_NULL; + + view = (struct rtgui_about_view*) rtgui_widget_create(RTGUI_ABOUT_VIEW_TYPE); + if (view != RT_NULL) + { + view->logo = logo; + view->description = description; + } + + return view; +} + +void rtgui_about_view_destroy(rtgui_about_view_t* view) +{ + /* destroy view */ + rtgui_widget_destroy(RTGUI_WIDGET(view)); +} diff --git a/components/rtgui/widgets/box.c b/components/rtgui/widgets/box.c index e5fc0e8318..860245c0db 100644 --- a/components/rtgui/widgets/box.c +++ b/components/rtgui/widgets/box.c @@ -18,23 +18,23 @@ static void _rtgui_box_constructor(rtgui_box_t *box) { /* init widget and set event handler */ - rtgui_widget_set_event_handler(RTGUI_WIDGET(box), rtgui_box_event_handler); + rtgui_object_set_event_handler(RTGUI_OBJECT(box), rtgui_box_event_handler); RTGUI_WIDGET(box)->flag |= RTGUI_WIDGET_FLAG_TRANSPARENT; - rtgui_widget_set_event_handler(RTGUI_WIDGET(box), rtgui_box_event_handler); + rtgui_object_set_event_handler(RTGUI_OBJECT(box), rtgui_box_event_handler); /* set proper of control */ box->orient = RTGUI_HORIZONTAL; box->border_size = RTGUI_BORDER_DEFAULT_WIDTH; } -DEFINE_CLASS_TYPE(box, "box", +DEFINE_CLASS_TYPE(box, "box", RTGUI_CONTAINER_TYPE, _rtgui_box_constructor, RT_NULL, sizeof(struct rtgui_box)); -rt_bool_t rtgui_box_event_handler(rtgui_widget_t* widget, rtgui_event_t* event) +rt_bool_t rtgui_box_event_handler(struct rtgui_object *widget, rtgui_event_t *event) { struct rtgui_box* box = (struct rtgui_box*)widget; @@ -48,7 +48,7 @@ rt_bool_t rtgui_box_event_handler(rtgui_widget_t* widget, rtgui_event_t* event) break; default: - return rtgui_container_event_handler(RTGUI_WIDGET(box), event); + return rtgui_container_event_handler(RTGUI_OBJECT(box), event); } return RT_FALSE; @@ -166,7 +166,8 @@ static void rtgui_box_layout_vertical(rtgui_box_t* box) size_event.y = rect->y1; size_event.w = rect->x2 - rect->x1; size_event.h = rect->y2 - rect->y1; - widget->event_handler(widget, &size_event.parent); + RTGUI_OBJECT(widget)->event_handler(RTGUI_OBJECT(widget), + &size_event.parent); /* point to next height */ next_y = rect->y2; @@ -258,7 +259,8 @@ static void rtgui_box_layout_horizontal(rtgui_box_t* box) size_event.y = rect->y1; size_event.w = rect->x2 - rect->x1; size_event.h = rect->y2 - rect->y1; - widget->event_handler(widget, &size_event.parent); + RTGUI_OBJECT(widget)->event_handler(RTGUI_OBJECT(widget), + &size_event.parent); /* point to next width */ next_x = rect->x2; diff --git a/components/rtgui/widgets/button.c b/components/rtgui/widgets/button.c index ecd4e24e87..a10d04ebbf 100644 --- a/components/rtgui/widgets/button.c +++ b/components/rtgui/widgets/button.c @@ -14,13 +14,13 @@ #include <rtgui/dc.h> #include <rtgui/rtgui_theme.h> #include <rtgui/widgets/button.h> -#include <rtgui/widgets/toplevel.h> +#include <rtgui/widgets/window.h> static void _rtgui_button_constructor(rtgui_button_t *button) { /* init widget and set event handler */ RTGUI_WIDGET(button)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE; - rtgui_widget_set_event_handler(RTGUI_WIDGET(button), rtgui_button_event_handler); + rtgui_object_set_event_handler(RTGUI_OBJECT(button), rtgui_button_event_handler); /* un-press button */ button->flag = 0; @@ -57,13 +57,16 @@ DEFINE_CLASS_TYPE(button, "button", _rtgui_button_destructor, sizeof(struct rtgui_button)); -rt_bool_t rtgui_button_event_handler(struct rtgui_widget* widget, struct rtgui_event* event) +rt_bool_t rtgui_button_event_handler(struct rtgui_object* object, struct rtgui_event* event) { - struct rtgui_button* btn; + struct rtgui_widget *widget; + struct rtgui_button *btn; RT_ASSERT(widget != RT_NULL); + RT_ASSERT(event != RT_NULL); - btn = (struct rtgui_button*) widget; + widget = RTGUI_WIDGET(object); + btn = RTGUI_BUTTON(widget); switch (event->type) { case RTGUI_EVENT_PAINT: @@ -150,10 +153,10 @@ rt_bool_t rtgui_button_event_handler(struct rtgui_widget* widget, struct rtgui_e if (emouse->button & RTGUI_MOUSE_BUTTON_LEFT) { /* set the last mouse event handled widget */ - rtgui_toplevel_t* toplevel; + struct rtgui_win* win; - toplevel = RTGUI_TOPLEVEL(RTGUI_WIDGET(btn)->toplevel); - toplevel->last_mevent_widget = RTGUI_WIDGET(btn); + win = RTGUI_WIN(RTGUI_WIDGET(btn)->toplevel); + win->last_mevent_widget = RTGUI_WIDGET(btn); /* it's a normal button */ if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN) diff --git a/components/rtgui/widgets/checkbox.c b/components/rtgui/widgets/checkbox.c index 35c76d46a5..78c3cd97c8 100644 --- a/components/rtgui/widgets/checkbox.c +++ b/components/rtgui/widgets/checkbox.c @@ -1,146 +1,153 @@ -#include <rtgui/dc.h>
-#include <rtgui/rtgui_theme.h>
-#include <rtgui/widgets/checkbox.h>
-
-static void _rtgui_checkbox_constructor(rtgui_checkbox_t *box)
-{
- /* init widget and set event handler */
- RTGUI_WIDGET(box)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
- rtgui_widget_set_event_handler(RTGUI_WIDGET(box), rtgui_checkbox_event_handler);
-
- /* set status */
- box->status_down = RTGUI_CHECKBOX_STATUS_UNCHECKED;
- box->on_button = RT_NULL;
-
- /* set default gc */
- RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(box)) = RTGUI_ALIGN_LEFT | RTGUI_ALIGN_CENTER_VERTICAL;
-}
-
-DEFINE_CLASS_TYPE(checkbox, "checkbox",
- RTGUI_LABEL_TYPE,
- _rtgui_checkbox_constructor,
- RT_NULL,
- sizeof(struct rtgui_checkbox));
-
-void rtgui_checkbox_set_onbutton(rtgui_checkbox_t* checkbox, rtgui_onbutton_func_t func)
-{
- RT_ASSERT(checkbox != RT_NULL);
-
- checkbox->on_button = func;
-}
-
-rt_bool_t rtgui_checkbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
-{
- struct rtgui_checkbox* box = (struct rtgui_checkbox*)widget;
-
- switch (event->type)
- {
- case RTGUI_EVENT_PAINT:
-#ifndef RTGUI_USING_SMALL_SIZE
- if (widget->on_draw != RT_NULL)
- {
- return widget->on_draw(widget, event);
- }
- else
-#endif
- rtgui_theme_draw_checkbox(box);
- break;
-
- case RTGUI_EVENT_MOUSE_BUTTON:
- {
- if (RTGUI_WIDGET_IS_ENABLE(widget) && !RTGUI_WIDGET_IS_HIDE(widget))
- {
- struct rtgui_event_mouse* emouse = (struct rtgui_event_mouse*)event;
- if (emouse->button & RTGUI_MOUSE_BUTTON_LEFT &&
- emouse->button & RTGUI_MOUSE_BUTTON_UP)
- {
- /* set focus */
- rtgui_widget_focus(widget);
-
- if (box->status_down & RTGUI_CHECKBOX_STATUS_UNCHECKED)
- {
- /* check it */
- box->status_down = RTGUI_CHECKBOX_STATUS_CHECKED;
- }
- else
- {
- /* un-check it */
- box->status_down = RTGUI_CHECKBOX_STATUS_UNCHECKED;
- }
- }
-
- /* draw checkbox */
- rtgui_theme_draw_checkbox(box);
-
-#ifndef RTGUI_USING_SMALL_SIZE
- /* call user callback */
- if (widget->on_mouseclick != RT_NULL)
- {
- return widget->on_mouseclick(widget, event);
- }
-#endif
- if (box->on_button != RT_NULL)
- {
- box->on_button(widget, event);
- return RT_TRUE;
- }
- }
-
- return RT_TRUE;
- }
- }
-
- return RT_FALSE;
-}
-
-struct rtgui_checkbox* rtgui_checkbox_create(const char* text, rt_bool_t checked)
-{
- struct rtgui_checkbox* box;
-
- box = (struct rtgui_checkbox*) rtgui_widget_create (RTGUI_CHECKBOX_TYPE);
- if (box != RT_NULL)
- {
- rtgui_rect_t rect;
-
- /* set default rect */
- rtgui_font_get_metrics(rtgui_font_default(), text, &rect);
- rect.x2 += RTGUI_BORDER_DEFAULT_WIDTH + 5 + (RTGUI_BORDER_DEFAULT_WIDTH << 1);
- rect.y2 += (RTGUI_BORDER_DEFAULT_WIDTH << 1);
-
- rtgui_widget_set_rect(RTGUI_WIDGET(box), &rect);
- rtgui_label_set_text(RTGUI_LABEL(box), text);
-
- if (checked == RT_TRUE)
- box->status_down = RTGUI_CHECKBOX_STATUS_CHECKED;
- else
- box->status_down = RTGUI_CHECKBOX_STATUS_UNCHECKED;
- }
-
- return box;
-}
-
-void rtgui_checkbox_destroy(rtgui_checkbox_t* box)
-{
- rtgui_widget_destroy(RTGUI_WIDGET(box));
-}
-
-void rtgui_checkbox_set_checked(rtgui_checkbox_t* checkbox, rt_bool_t checked)
-{
- RT_ASSERT(checkbox != RT_NULL);
- if (checked == RT_TRUE)
- checkbox->status_down = RTGUI_CHECKBOX_STATUS_CHECKED;
- else
- checkbox->status_down = RTGUI_CHECKBOX_STATUS_UNCHECKED;
-
-}
-
-rt_bool_t rtgui_checkbox_get_checked(rtgui_checkbox_t* checkbox)
-{
- RT_ASSERT(checkbox != RT_NULL);
-
- if (checkbox->status_down == RTGUI_CHECKBOX_STATUS_CHECKED)
- return RT_TRUE;
-
- return RT_FALSE;
-}
-
+#include <rtgui/dc.h> +#include <rtgui/rtgui_theme.h> +#include <rtgui/widgets/checkbox.h> + +static void _rtgui_checkbox_constructor(rtgui_checkbox_t *box) +{ + /* init widget and set event handler */ + RTGUI_WIDGET(box)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE; + rtgui_object_set_event_handler(RTGUI_OBJECT(box), rtgui_checkbox_event_handler); + + /* set status */ + box->status_down = RTGUI_CHECKBOX_STATUS_UNCHECKED; + box->on_button = RT_NULL; + + /* set default gc */ + RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(box)) = RTGUI_ALIGN_LEFT | RTGUI_ALIGN_CENTER_VERTICAL; +} + +DEFINE_CLASS_TYPE(checkbox, "checkbox", + RTGUI_LABEL_TYPE, + _rtgui_checkbox_constructor, + RT_NULL, + sizeof(struct rtgui_checkbox)); + +void rtgui_checkbox_set_onbutton(rtgui_checkbox_t* checkbox, rtgui_onbutton_func_t func) +{ + RT_ASSERT(checkbox != RT_NULL); + + checkbox->on_button = func; +} + +rt_bool_t rtgui_checkbox_event_handler(struct rtgui_object* object, struct rtgui_event* event) +{ + struct rtgui_widget *widget; + struct rtgui_checkbox *box = (struct rtgui_checkbox*)widget; + + RT_ASSERT(widget != RT_NULL); + RT_ASSERT(event != RT_NULL); + + widget = RTGUI_WIDGET(object); + box = RTGUI_CHECKBOX(object); + + switch (event->type) + { + case RTGUI_EVENT_PAINT: +#ifndef RTGUI_USING_SMALL_SIZE + if (widget->on_draw != RT_NULL) + { + return widget->on_draw(widget, event); + } + else +#endif + rtgui_theme_draw_checkbox(box); + break; + + case RTGUI_EVENT_MOUSE_BUTTON: + { + if (RTGUI_WIDGET_IS_ENABLE(widget) && !RTGUI_WIDGET_IS_HIDE(widget)) + { + struct rtgui_event_mouse* emouse = (struct rtgui_event_mouse*)event; + if (emouse->button & RTGUI_MOUSE_BUTTON_LEFT && + emouse->button & RTGUI_MOUSE_BUTTON_UP) + { + /* set focus */ + rtgui_widget_focus(widget); + + if (box->status_down & RTGUI_CHECKBOX_STATUS_UNCHECKED) + { + /* check it */ + box->status_down = RTGUI_CHECKBOX_STATUS_CHECKED; + } + else + { + /* un-check it */ + box->status_down = RTGUI_CHECKBOX_STATUS_UNCHECKED; + } + } + + /* draw checkbox */ + rtgui_theme_draw_checkbox(box); + +#ifndef RTGUI_USING_SMALL_SIZE + /* call user callback */ + if (widget->on_mouseclick != RT_NULL) + { + return widget->on_mouseclick(widget, event); + } +#endif + if (box->on_button != RT_NULL) + { + box->on_button(widget, event); + return RT_TRUE; + } + } + + return RT_TRUE; + } + } + + return RT_FALSE; +} + +struct rtgui_checkbox* rtgui_checkbox_create(const char* text, rt_bool_t checked) +{ + struct rtgui_checkbox* box; + + box = (struct rtgui_checkbox*) rtgui_widget_create (RTGUI_CHECKBOX_TYPE); + if (box != RT_NULL) + { + rtgui_rect_t rect; + + /* set default rect */ + rtgui_font_get_metrics(rtgui_font_default(), text, &rect); + rect.x2 += RTGUI_BORDER_DEFAULT_WIDTH + 5 + (RTGUI_BORDER_DEFAULT_WIDTH << 1); + rect.y2 += (RTGUI_BORDER_DEFAULT_WIDTH << 1); + + rtgui_widget_set_rect(RTGUI_WIDGET(box), &rect); + rtgui_label_set_text(RTGUI_LABEL(box), text); + + if (checked == RT_TRUE) + box->status_down = RTGUI_CHECKBOX_STATUS_CHECKED; + else + box->status_down = RTGUI_CHECKBOX_STATUS_UNCHECKED; + } + + return box; +} + +void rtgui_checkbox_destroy(rtgui_checkbox_t* box) +{ + rtgui_widget_destroy(RTGUI_WIDGET(box)); +} + +void rtgui_checkbox_set_checked(rtgui_checkbox_t* checkbox, rt_bool_t checked) +{ + RT_ASSERT(checkbox != RT_NULL); + if (checked == RT_TRUE) + checkbox->status_down = RTGUI_CHECKBOX_STATUS_CHECKED; + else + checkbox->status_down = RTGUI_CHECKBOX_STATUS_UNCHECKED; + +} + +rt_bool_t rtgui_checkbox_get_checked(rtgui_checkbox_t* checkbox) +{ + RT_ASSERT(checkbox != RT_NULL); + + if (checkbox->status_down == RTGUI_CHECKBOX_STATUS_CHECKED) + return RT_TRUE; + + return RT_FALSE; +} + diff --git a/components/rtgui/widgets/combobox.c b/components/rtgui/widgets/combobox.c index 972d467fed..282a975f08 100644 --- a/components/rtgui/widgets/combobox.c +++ b/components/rtgui/widgets/combobox.c @@ -1,259 +1,276 @@ -#include <rtgui/dc.h>
-#include <rtgui/rtgui_theme.h>
-#include <rtgui/widgets/combobox.h>
-
-static rt_bool_t rtgui_combobox_pulldown_hide(struct rtgui_widget* widget, struct rtgui_event* event);
-const static rt_uint8_t down_arrow[] = {0xff, 0x7e, 0x3c, 0x18};
-
-static void _rtgui_combobox_constructor(rtgui_combobox_t *box)
-{
- rtgui_rect_t rect = {0, 0, RTGUI_COMBOBOX_WIDTH, RTGUI_COMBOBOX_HEIGHT};
-
- /* init widget and set event handler */
- rtgui_widget_set_event_handler(RTGUI_WIDGET(box), rtgui_combobox_event_handler);
- rtgui_widget_set_rect(RTGUI_WIDGET(box), &rect);
-
- RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(box)) = RTGUI_ALIGN_CENTER_VERTICAL;
-
- box->pd_pressed = RT_FALSE;
- box->current_item = 0;
- box->on_selected = RT_NULL;
- box->pd_win = RT_NULL;
-}
-
-static void _rtgui_combobox_destructor(rtgui_combobox_t *box)
-{
- /* destroy pull down window */
- rtgui_win_destroy(box->pd_win);
-
- /* reset box field */
- box->pd_win = RT_NULL;
-}
-
-void rtgui_combobox_pdwin_onitem(struct rtgui_widget* widget, struct rtgui_event* event)
-{
- rtgui_win_t* pd_win;
- rtgui_combobox_t* combo;
- rtgui_listbox_t* list;
-
- list = RTGUI_LISTBOX(widget);
- pd_win = RTGUI_WIN(rtgui_widget_get_toplevel(widget));
- combo = RTGUI_COMBOBOX(pd_win->user_data);
- combo->current_item = list->current_item;
-
- if (combo->on_selected != RT_NULL)
- combo->on_selected(RTGUI_WIDGET(combo), RT_NULL);
-
- rtgui_win_hiden(pd_win);
- rtgui_widget_update(RTGUI_WIDGET(combo));
-
- return ;
-}
-
-rt_bool_t rtgui_combobox_pdwin_ondeactive(struct rtgui_widget* widget, struct rtgui_event* event)
-{
- rtgui_win_hiden(RTGUI_WIN(widget));
- return RT_TRUE;
-}
-
-DEFINE_CLASS_TYPE(combobox, "combobox",
- RTGUI_WIDGET_TYPE,
- _rtgui_combobox_constructor,
- _rtgui_combobox_destructor,
- sizeof(struct rtgui_combobox));
-
-rtgui_combobox_t *rtgui_combobox_create(struct rtgui_listbox_item* items, rt_uint16_t count, struct rtgui_rect* rect)
-{
- rtgui_combobox_t *box;
-
- box = (rtgui_combobox_t*)rtgui_widget_create(RTGUI_COMBOBOX_TYPE);
- box->items_count = count;
- box->items = items;
- rtgui_widget_set_rect(RTGUI_WIDGET(box), rect);
-
- box->pd_win = RT_NULL;
-
- return box;
-}
-
-void rtgui_combobox_destroy(rtgui_combobox_t* box)
-{
- rtgui_widget_destroy(RTGUI_WIDGET(box));
-}
-
-static void rtgui_combobox_ondraw(struct rtgui_combobox* box)
-{
- /* draw button */
- rtgui_color_t bc;
- struct rtgui_dc* dc;
- struct rtgui_rect rect, r;
-
- /* begin drawing */
- dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(box));
- if (dc == RT_NULL) return;
-
- bc = RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(box));
-
- /* get widget rect */
- rtgui_widget_get_rect(RTGUI_WIDGET(box), &rect);
- RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(box)) = white;
-
- /* fill widget rect with background color */
- rtgui_dc_fill_rect(dc, &rect);
- rtgui_dc_draw_rect(dc, &rect);
-
- /* draw current item */
- if (box->current_item < box->items_count)
- {
- rect.x1 += 5;
- rtgui_dc_draw_text(dc, box->items[box->current_item].name, &rect);
- }
-
- /* restore background color */
- RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(box)) = bc;
-
- /* draw pull down button */
- rect.x1 = rect.x2 - RTGUI_COMBOBOX_BUTTON_WIDTH;
- rtgui_rect_inflate(&rect, -1);
- rtgui_dc_fill_rect(dc, &rect);
- if (box->pd_pressed == RT_TRUE) rtgui_dc_draw_border(dc, &rect, RTGUI_BORDER_SUNKEN);
- else rtgui_dc_draw_border(dc, &rect, RTGUI_BORDER_RAISE);
-
- r.x1 = 0; r.y1 = 0; r.x2 = 8; r.y2 = 4;
- rtgui_rect_moveto_align(&rect, &r, RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL);
- rtgui_dc_draw_byte(dc, r.x1, r.y1, 4, down_arrow);
-
- /* end drawing */
- rtgui_dc_end_drawing(dc);
- return;
-}
-
-static rt_bool_t rtgui_combobox_onmouse_button(struct rtgui_combobox* box, struct rtgui_event_mouse* event)
-{
- struct rtgui_rect rect;
-
- /* get widget rect */
- rect = RTGUI_WIDGET(box)->extent;
-
- /* move to the pull down button */
- rect.x1 = rect.x2 - RTGUI_COMBOBOX_BUTTON_WIDTH;
- if (rtgui_rect_contains_point(&rect, event->x, event->y) == RT_EOK)
- {
- /* handle mouse button on pull down button */
- if (event->button & RTGUI_MOUSE_BUTTON_LEFT &&
- event->button & RTGUI_MOUSE_BUTTON_DOWN)
- {
- box->pd_pressed = RT_TRUE;
- rtgui_widget_update(RTGUI_WIDGET(box));
- }
- else if (event->button & RTGUI_MOUSE_BUTTON_LEFT &&
- event->button & RTGUI_MOUSE_BUTTON_UP)
- {
- box->pd_pressed = RT_FALSE;
- rtgui_widget_update(RTGUI_WIDGET(box));
-
- /* pop pull down window */
- if (box->pd_win == RT_NULL)
- {
- rtgui_listbox_t *list;
-
- /* create pull down window */
- rect = RTGUI_WIDGET(box)->extent;
- rect.y1 = rect.y2;
- rect.y2 = rect.y1 + 5 * (2 + rtgui_theme_get_selected_height());
- box->pd_win = rtgui_win_create(RT_NULL, "combo", &rect, RTGUI_WIN_STYLE_NO_TITLE);
- rtgui_win_set_ondeactivate(RTGUI_WIN(box->pd_win), rtgui_combobox_pulldown_hide);
- /* set user data to parent combobox */
- box->pd_win->user_data = (rt_uint32_t)box;
-
- /* create list box */
- rtgui_rect_inflate(&rect, -1);
- list = rtgui_listbox_create(box->items, box->items_count, &rect);
- rtgui_container_add_child(RTGUI_CONTAINER(box->pd_win), RTGUI_WIDGET(list));
- rtgui_widget_focus(RTGUI_WIDGET(list));
-
- rtgui_listbox_set_onitem(list, rtgui_combobox_pdwin_onitem);
- rtgui_win_set_ondeactivate(box->pd_win, rtgui_combobox_pdwin_ondeactive);
- }
-
- /* show combo box pull down window */
- rtgui_win_show(RTGUI_WIN(box->pd_win), RT_FALSE);
- }
-
- return RT_TRUE;
- }
-
- return RT_FALSE;
-}
-
-rt_bool_t rtgui_combobox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
-{
- struct rtgui_combobox* box = (struct rtgui_combobox*)widget;
-
- switch (event->type)
- {
- case RTGUI_EVENT_PAINT:
-#ifndef RTGUI_USING_SMALL_SIZE
- if (widget->on_draw != RT_NULL) widget->on_draw(widget, event);
- else
-#endif
- rtgui_combobox_ondraw(box);
-
- break;
-
- case RTGUI_EVENT_MOUSE_BUTTON:
- return rtgui_combobox_onmouse_button(box, (struct rtgui_event_mouse*)event);
-
- case RTGUI_EVENT_FOCUSED:
- {
- /* item focused */
- struct rtgui_event_focused* focused;
-
- focused = (struct rtgui_event_focused*) event;
-
- if (focused->widget != RT_NULL)
- {
- /* hide pull down window */
- rtgui_win_hiden(RTGUI_WIN(box->pd_win));
- rtgui_combobox_ondraw(box);
- }
- }
- break;
- }
-
- return RT_FALSE;
-}
-
-static rt_bool_t rtgui_combobox_pulldown_hide(struct rtgui_widget* widget, struct rtgui_event* event)
-{
- struct rtgui_combobox* box;
-
- if (widget == RT_NULL) return RT_TRUE;
-
- box = (struct rtgui_combobox*) (((struct rtgui_win*)widget)->user_data);
- if (box == RT_NULL) return RT_TRUE;
-
- /* hide pull down window */
- rtgui_win_hiden(RTGUI_WIN(box->pd_win));
-
- /* clear pull down button state */
- box->pd_pressed = RT_FALSE;
- rtgui_widget_update(RTGUI_WIDGET(box));
-
- return RT_TRUE;
-}
-
-struct rtgui_listbox_item* rtgui_combox_get_select(struct rtgui_combobox* box)
-{
- if ((box != RT_NULL) && (box->current_item < box->items_count))
- {
- return &(box->items[box->current_item]);
- }
-
- return RT_NULL;
-}
-
-void rtgui_combobox_set_onselected(struct rtgui_combobox* box, rtgui_onitem_func_t func)
-{
- box->on_selected = func;
-}
+#include <rtgui/dc.h> +#include <rtgui/rtgui_theme.h> +#include <rtgui/widgets/combobox.h> + +static rt_bool_t rtgui_combobox_pulldown_hide(struct rtgui_object* object, struct rtgui_event* event); +const static rt_uint8_t down_arrow[] = {0xff, 0x7e, 0x3c, 0x18}; + +static void _rtgui_combobox_constructor(rtgui_combobox_t *box) +{ + rtgui_rect_t rect = {0, 0, RTGUI_COMBOBOX_WIDTH, RTGUI_COMBOBOX_HEIGHT}; + + /* init widget and set event handler */ + rtgui_object_set_event_handler(RTGUI_OBJECT(box), rtgui_combobox_event_handler); + rtgui_widget_set_rect(RTGUI_WIDGET(box), &rect); + + RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(box)) = RTGUI_ALIGN_CENTER_VERTICAL; + + box->pd_pressed = RT_FALSE; + box->current_item = 0; + box->on_selected = RT_NULL; + box->pd_win = RT_NULL; +} + +static void _rtgui_combobox_destructor(rtgui_combobox_t *box) +{ + /* destroy pull down window */ + rtgui_win_destroy(box->pd_win); + + /* reset box field */ + box->pd_win = RT_NULL; +} + +rt_bool_t rtgui_combobox_pdwin_onitem(struct rtgui_object* object, struct rtgui_event* event) +{ + struct rtgui_widget *widget; + rtgui_win_t* pd_win; + rtgui_combobox_t* combo; + rtgui_listbox_t* list; + + RT_ASSERT(object != RT_NULL); + RT_ASSERT(event != RT_NULL); + + widget = RTGUI_WIDGET(object); + list = RTGUI_LISTBOX(widget); + pd_win = RTGUI_WIN(rtgui_widget_get_toplevel(widget)); + combo = RTGUI_COMBOBOX(pd_win->user_data); + combo->current_item = list->current_item; + + if (combo->on_selected != RT_NULL) + combo->on_selected(RTGUI_OBJECT(combo), RT_NULL); + + rtgui_win_hiden(pd_win); + rtgui_widget_update(RTGUI_WIDGET(combo)); + + return RT_FALSE; +} + +rt_bool_t rtgui_combobox_pdwin_ondeactive(struct rtgui_object* object, struct rtgui_event* event) +{ + rtgui_win_hiden(RTGUI_WIN(object)); + return RT_TRUE; +} + +DEFINE_CLASS_TYPE(combobox, "combobox", + RTGUI_WIDGET_TYPE, + _rtgui_combobox_constructor, + _rtgui_combobox_destructor, + sizeof(struct rtgui_combobox)); + +rtgui_combobox_t *rtgui_combobox_create(struct rtgui_listbox_item* items, rt_uint16_t count, struct rtgui_rect* rect) +{ + rtgui_combobox_t *box; + + box = (rtgui_combobox_t*)rtgui_widget_create(RTGUI_COMBOBOX_TYPE); + box->items_count = count; + box->items = items; + rtgui_widget_set_rect(RTGUI_WIDGET(box), rect); + + box->pd_win = RT_NULL; + + return box; +} + +void rtgui_combobox_destroy(rtgui_combobox_t* box) +{ + rtgui_widget_destroy(RTGUI_WIDGET(box)); +} + +static void rtgui_combobox_ondraw(struct rtgui_combobox* box) +{ + /* draw button */ + rtgui_color_t bc; + struct rtgui_dc* dc; + struct rtgui_rect rect, r; + + /* begin drawing */ + dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(box)); + if (dc == RT_NULL) return; + + bc = RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(box)); + + /* get widget rect */ + rtgui_widget_get_rect(RTGUI_WIDGET(box), &rect); + RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(box)) = white; + + /* fill widget rect with background color */ + rtgui_dc_fill_rect(dc, &rect); + rtgui_dc_draw_rect(dc, &rect); + + /* draw current item */ + if (box->current_item < box->items_count) + { + rect.x1 += 5; + rtgui_dc_draw_text(dc, box->items[box->current_item].name, &rect); + } + + /* restore background color */ + RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(box)) = bc; + + /* draw pull down button */ + rect.x1 = rect.x2 - RTGUI_COMBOBOX_BUTTON_WIDTH; + rtgui_rect_inflate(&rect, -1); + rtgui_dc_fill_rect(dc, &rect); + if (box->pd_pressed == RT_TRUE) rtgui_dc_draw_border(dc, &rect, RTGUI_BORDER_SUNKEN); + else rtgui_dc_draw_border(dc, &rect, RTGUI_BORDER_RAISE); + + r.x1 = 0; r.y1 = 0; r.x2 = 8; r.y2 = 4; + rtgui_rect_moveto_align(&rect, &r, RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL); + rtgui_dc_draw_byte(dc, r.x1, r.y1, 4, down_arrow); + + /* end drawing */ + rtgui_dc_end_drawing(dc); + return; +} + +static rt_bool_t rtgui_combobox_onmouse_button(struct rtgui_combobox* box, struct rtgui_event_mouse* event) +{ + struct rtgui_rect rect; + + /* get widget rect */ + rect = RTGUI_WIDGET(box)->extent; + + /* move to the pull down button */ + rect.x1 = rect.x2 - RTGUI_COMBOBOX_BUTTON_WIDTH; + if (rtgui_rect_contains_point(&rect, event->x, event->y) == RT_EOK) + { + /* handle mouse button on pull down button */ + if (event->button & RTGUI_MOUSE_BUTTON_LEFT && + event->button & RTGUI_MOUSE_BUTTON_DOWN) + { + box->pd_pressed = RT_TRUE; + rtgui_widget_update(RTGUI_WIDGET(box)); + } + else if (event->button & RTGUI_MOUSE_BUTTON_LEFT && + event->button & RTGUI_MOUSE_BUTTON_UP) + { + box->pd_pressed = RT_FALSE; + rtgui_widget_update(RTGUI_WIDGET(box)); + + /* pop pull down window */ + if (box->pd_win == RT_NULL) + { + rtgui_listbox_t *list; + + /* create pull down window */ + rect = RTGUI_WIDGET(box)->extent; + rect.y1 = rect.y2; + rect.y2 = rect.y1 + 5 * (2 + rtgui_theme_get_selected_height()); + box->pd_win = rtgui_win_create(RT_NULL, "combo", &rect, RTGUI_WIN_STYLE_NO_TITLE); + rtgui_win_set_ondeactivate(RTGUI_WIN(box->pd_win), rtgui_combobox_pulldown_hide); + /* set user data to parent combobox */ + box->pd_win->user_data = (rt_uint32_t)box; + + /* create list box */ + rtgui_rect_inflate(&rect, -1); + list = rtgui_listbox_create(box->items, box->items_count, &rect); + rtgui_container_add_child(RTGUI_CONTAINER(box->pd_win), RTGUI_WIDGET(list)); + rtgui_widget_focus(RTGUI_WIDGET(list)); + + rtgui_listbox_set_onitem(list, rtgui_combobox_pdwin_onitem); + rtgui_win_set_ondeactivate(box->pd_win, rtgui_combobox_pdwin_ondeactive); + } + + /* show combo box pull down window */ + rtgui_win_show(RTGUI_WIN(box->pd_win), RT_FALSE); + } + + return RT_TRUE; + } + + return RT_FALSE; +} + +rt_bool_t rtgui_combobox_event_handler(struct rtgui_object* object, struct rtgui_event* event) +{ + struct rtgui_combobox *box; + + RT_ASSERT(object != RT_NULL); + RT_ASSERT(event != RT_NULL); + + box = RTGUI_COMBOBOX(object); + + switch (event->type) + { + case RTGUI_EVENT_PAINT: +#ifndef RTGUI_USING_SMALL_SIZE + if (widget->on_draw != RT_NULL) widget->on_draw(widget, event); + else +#endif + rtgui_combobox_ondraw(box); + + break; + + case RTGUI_EVENT_MOUSE_BUTTON: + return rtgui_combobox_onmouse_button(box, (struct rtgui_event_mouse*)event); + + case RTGUI_EVENT_FOCUSED: + { + /* item focused */ + struct rtgui_event_focused* focused; + + focused = (struct rtgui_event_focused*) event; + + if (focused->widget != RT_NULL) + { + /* hide pull down window */ + rtgui_win_hiden(RTGUI_WIN(box->pd_win)); + rtgui_combobox_ondraw(box); + } + } + break; + } + + return RT_FALSE; +} + +static rt_bool_t rtgui_combobox_pulldown_hide(struct rtgui_object* object, struct rtgui_event* event) +{ + struct rtgui_widget *widget; + struct rtgui_combobox *box; + + RT_ASSERT(object != RT_NULL); + RT_ASSERT(event != RT_NULL); + + widget = RTGUI_WIDGET(object); + box = RTGUI_COMBOBOX(object); + + if (widget == RT_NULL) return RT_TRUE; + + box = (struct rtgui_combobox*) (((struct rtgui_win*)widget)->user_data); + if (box == RT_NULL) return RT_TRUE; + + /* hide pull down window */ + rtgui_win_hiden(RTGUI_WIN(box->pd_win)); + + /* clear pull down button state */ + box->pd_pressed = RT_FALSE; + rtgui_widget_update(RTGUI_WIDGET(box)); + + return RT_TRUE; +} + +struct rtgui_listbox_item* rtgui_combox_get_select(struct rtgui_combobox* box) +{ + if ((box != RT_NULL) && (box->current_item < box->items_count)) + { + return &(box->items[box->current_item]); + } + + return RT_NULL; +} + +void rtgui_combobox_set_onselected(struct rtgui_combobox* box, rtgui_event_handler_ptr func) +{ + box->on_selected = func; +} diff --git a/components/rtgui/widgets/container.c b/components/rtgui/widgets/container.c index c1e90f719a..3e919ba19a 100644 --- a/components/rtgui/widgets/container.c +++ b/components/rtgui/widgets/container.c @@ -10,37 +10,55 @@ * Change Logs: * Date Author Notes * 2009-10-16 Bernard first version + * 2010-09-24 Bernard fix container destroy issue */ -#include <rtgui/widgets/toplevel.h> +#include <rtgui/dc.h> +#include <rtgui/rtgui_system.h> +#include <rtgui/rtgui_application.h> #include <rtgui/widgets/container.h> +#include <rtgui/widgets/window.h> static void _rtgui_container_constructor(rtgui_container_t *container) { - /* set event handler and init field */ - rtgui_widget_set_event_handler(RTGUI_WIDGET(container), rtgui_container_event_handler); + /* init container */ + rtgui_object_set_event_handler(RTGUI_OBJECT(container), + rtgui_container_event_handler); + rtgui_list_init(&(container->children)); - - /* set focused widget to itself */ - container->focused = RTGUI_WIDGET(container); - /* set container as focusable widget */ - RTGUI_WIDGET(container)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE; + + /* container is used to 'contain'(show) widgets and dispatch events to + * them, not interact with user. So no need to grab focus. If we did it, + * some widget inherited from container(e.g. notebook) will grab the focus + * annoyingly. + * + * For example, a focusable notebook N has a widget W. When the user press + * W, N will gain the focus and W will lose it at first. Then N will set + * focus to W because it is W that eventually interact with people. N will + * yield focus and W will gain the focus again. This loop will make W + * repaint twice every time user press it. + * + * Just eliminate it. + */ + RTGUI_WIDGET(container)->flag &= ~RTGUI_WIDGET_FLAG_FOCUSABLE; } static void _rtgui_container_destructor(rtgui_container_t *container) { - /* destroy children of container */ rtgui_container_destroy_children(container); } 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 = rtgui_widget_get_toplevel(RTGUI_WIDGET(container)); + child->toplevel = window; if (RTGUI_IS_CONTAINER(child)) { @@ -49,7 +67,7 @@ static void _rtgui_container_update_toplevel(rtgui_container_t* container) } } -DEFINE_CLASS_TYPE(container, "container", +DEFINE_CLASS_TYPE(container, "container", RTGUI_WIDGET_TYPE, _rtgui_container_constructor, _rtgui_container_destructor, @@ -65,7 +83,8 @@ rt_bool_t rtgui_container_dispatch_event(rtgui_container_t *container, rtgui_eve struct rtgui_widget* w; w = rtgui_list_entry(node, struct rtgui_widget, sibling); - if (w->event_handler(w, event) == RT_TRUE) return RT_TRUE; + if (RTGUI_OBJECT(w)->event_handler(RTGUI_OBJECT(w), event) == RT_TRUE) + return RT_TRUE; } return RT_FALSE; @@ -75,64 +94,106 @@ rt_bool_t rtgui_container_dispatch_mouse_event(rtgui_container_t *container, str { /* handle in child widget */ struct rtgui_list_node* node; - rtgui_widget_t *focus; + struct rtgui_widget *old_focus; + + old_focus = RTGUI_WIDGET(container)->toplevel->focused_widget; - /* get focus widget on toplevel */ - focus = RTGUI_CONTAINER(RTGUI_WIDGET(container)->toplevel)->focused; rtgui_list_foreach(node, &(container->children)) { struct rtgui_widget* w; w = rtgui_list_entry(node, struct rtgui_widget, sibling); - if (rtgui_rect_contains_point(&(w->extent), event->x, event->y) == RT_EOK) + if (rtgui_rect_contains_point(&(w->extent), + event->x, event->y) == RT_EOK) { - if ((focus != w) && RTGUI_WIDGET_IS_FOCUSABLE(w)) + if ((old_focus != w) && RTGUI_WIDGET_IS_FOCUSABLE(w)) rtgui_widget_focus(w); - if (w->event_handler(w, (rtgui_event_t*)event) == RT_TRUE) return RT_TRUE; + if (RTGUI_OBJECT(w)->event_handler(RTGUI_OBJECT(w), + (rtgui_event_t*)event) == RT_TRUE) + return RT_TRUE; } } return RT_FALSE; } -rt_bool_t rtgui_container_event_handler(rtgui_widget_t* widget, rtgui_event_t* event) +rt_bool_t rtgui_container_event_handler(struct rtgui_object* object, struct rtgui_event* event) { - rtgui_container_t *container = RTGUI_CONTAINER(widget); + struct rtgui_container *container; + struct rtgui_widget *widget; + + RT_ASSERT(object != RT_NULL); + RT_ASSERT(event != RT_NULL); + + container = RTGUI_CONTAINER(object); + widget = RTGUI_WIDGET(object); switch (event->type) { case RTGUI_EVENT_PAINT: - case RTGUI_EVENT_COMMAND: - case RTGUI_EVENT_RESIZE: - rtgui_container_dispatch_event(container, event); + { + struct rtgui_dc* dc; + struct rtgui_rect rect; + + dc = rtgui_dc_begin_drawing(widget); + if (dc == RT_NULL) + return RT_FALSE; + rtgui_widget_get_rect(widget, &rect); + + /* fill container with background */ + rtgui_dc_fill_rect(dc, &rect); + + /* paint on each child */ + rtgui_container_dispatch_event(container, event); + + rtgui_dc_end_drawing(dc); + } break; case RTGUI_EVENT_KBD: + /* let parent to handle keyboard event */ + if (widget->parent != RT_NULL && + widget->parent != RTGUI_WIDGET(widget->toplevel)) { - /* let parent to handle keyboard event */ - if (widget->parent != RT_NULL && widget->parent != widget->toplevel) - { - return widget->parent->event_handler(widget->parent, event); - } + return RTGUI_OBJECT(widget->parent)->event_handler( + RTGUI_OBJECT(widget->parent), + event); } break; case RTGUI_EVENT_MOUSE_BUTTON: + case RTGUI_EVENT_MOUSE_MOTION: /* handle in child widget */ return rtgui_container_dispatch_mouse_event(container, (struct rtgui_event_mouse*)event); - case RTGUI_EVENT_MOUSE_MOTION: - return rtgui_container_dispatch_mouse_event(container, - (struct rtgui_event_mouse*)event); + case RTGUI_EVENT_COMMAND: + case RTGUI_EVENT_RESIZE: + rtgui_container_dispatch_event(container, event); + break; default: /* call parent widget event handler */ - return rtgui_widget_event_handler(widget, event); + return rtgui_widget_event_handler(RTGUI_OBJECT(widget), event); } return RT_FALSE; } +rtgui_container_t* rtgui_container_create(void) +{ + struct rtgui_container* container; + + /* allocate container */ + container = (struct rtgui_container*) rtgui_widget_create (RTGUI_CONTAINER_TYPE); + return container; +} + +void rtgui_container_destroy(rtgui_container_t* container) +{ + rtgui_container_hide(container); + rtgui_widget_destroy(RTGUI_WIDGET(container)); +} + /* * This function will add a child to a container widget * Note: this function will not change the widget layout @@ -168,13 +229,7 @@ void rtgui_container_remove_child(rtgui_container_t *container, rtgui_widget_t* RT_ASSERT(container != RT_NULL); RT_ASSERT(child != RT_NULL); - if (child == container->focused) - { - /* set focused to itself */ - container->focused = RTGUI_WIDGET(container); - - rtgui_widget_focus(RTGUI_WIDGET(container)); - } + rtgui_widget_unfocus(child); /* remove widget from parent's children list */ rtgui_list_remove(&(container->children), &(child->sibling)); @@ -218,9 +273,6 @@ void rtgui_container_destroy_children(rtgui_container_t *container) } container->children.next = RT_NULL; - container->focused = RTGUI_WIDGET(container); - if (RTGUI_WIDGET(container)->parent != RT_NULL) - rtgui_widget_focus(RTGUI_WIDGET(container)); /* update widget clip */ rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(RTGUI_WIDGET(container)->toplevel)); @@ -237,3 +289,26 @@ rtgui_widget_t* rtgui_container_get_first_child(rtgui_container_t* container) return child; } + +#ifndef RTGUI_USING_SMALL_SIZE +void rtgui_container_set_box(rtgui_container_t* container, struct rtgui_box* box) +{ + if (container == RT_NULL || box == RT_NULL) + return; + + rtgui_container_add_child(RTGUI_CONTAINER(container), RTGUI_WIDGET(box)); + rtgui_widget_set_rect(RTGUI_WIDGET(box), &(RTGUI_WIDGET(container)->extent)); +} +#endif + +void rtgui_container_hide(rtgui_container_t* container) +{ + if (container == RT_NULL) return; + + if (RTGUI_WIDGET(container)->parent == RT_NULL) + { + RTGUI_WIDGET_HIDE(RTGUI_WIDGET(container)); + return; + } +} + diff --git a/components/rtgui/widgets/filelist_view.c b/components/rtgui/widgets/filelist_view.c index 3e38cb193f..14209749ca 100644 --- a/components/rtgui/widgets/filelist_view.c +++ b/components/rtgui/widgets/filelist_view.c @@ -1,846 +1,827 @@ -/*
- * File : filelist_view.c
- * This file is part of RTGUI in RT-Thread RTOS
- * COPYRIGHT (C) 2010, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2010-01-06 Bernard first version
- */
-
-#include <rtgui/rtgui_object.h>
-#include <rtgui/rtgui_system.h>
-#include <rtgui/rtgui_theme.h>
-
-#include <rtgui/list.h>
-#include <rtgui/image.h>
-#include <rtgui/widgets/view.h>
-#include <rtgui/widgets/workbench.h>
-#include <rtgui/widgets/filelist_view.h>
-#include <rtgui/widgets/listbox.h>
-#include <rtgui/widgets/window.h>
-
-#if defined(RTGUI_USING_DFS_FILERW) || defined(RTGUI_USING_STDIO_FILERW)
-#ifdef _WIN32
-#include <io.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#define PATH_SEPARATOR '\\'
-#else
-#include <dfs_posix.h>
-#define PATH_SEPARATOR '/'
-#endif
-
-#include <string.h>
-
-#define RTGUI_FILELIST_MARGIN 5
-
-const static char * file_xpm[] = {
-"16 16 21 1",
-" c None",
-". c #999999",
-"+ c #818181",
-"@ c #FFFFFF",
-"# c #ECECEC",
-"$ c #EAEAEA",
-"% c #EBEBEB",
-"& c #EDEDED",
-"* c #F0F0F0",
-"= c #C4C4C4",
-"- c #C5C5C5",
-"; c #C6C6C6",
-"> c #C7C7C7",
-", c #EEEEEE",
-"' c #EDEDE5",
-") c #EDEDE6",
-"! c #EFEFEF",
-"~ c #C8C8C8",
-"{ c #F1F1F1",
-"] c #F2F2F2",
-"^ c #959595",
-".++++++++++++ ",
-"+@@@@@@@@@@@@+ ",
-"+@#$$%%%##&*@+ ",
-"+@$=--;;;;>*@+ ",
-"+@$%%###&&,*@+ ",
-"+@%-;;;;;;>*@+ ",
-"+@%%##&&'#,*@+ ",
-"+@%;;;;,,),*@+ ",
-"+@##&&,,!!!*@+ ",
-"+@#;;;>>~~~*@+ ",
-"+@#&,,!!*{{{@+ ",
-"+@&;>>~~~{{]@+ ",
-"+@&&,!!**{]]@+ ",
-"+@@@@@@@@@@@@+ ",
-"^++++++++++++^ ",
-" "};
-
-const static char * folder_xpm[] = {
-"16 16 121 2",
-" c None",
-". c #D9B434",
-"+ c #E1C25E",
-"@ c #E2C360",
-"# c #E2C35F",
-"$ c #DBB63C",
-"% c #DAB336",
-"& c #FEFEFD",
-"* c #FFFFFE",
-"= c #FFFEFE",
-"- c #FFFEFD",
-"; c #FBF7EA",
-"> c #E4C76B",
-", c #E3C76B",
-"' c #E6CD79",
-") c #E5CA74",
-"! c #DAAF35",
-"~ c #FEFCF7",
-"{ c #F8E48E",
-"] c #F5DE91",
-"^ c #F5E09F",
-"/ c #F6E1AC",
-"( c #FEFBEF",
-"_ c #FEFDF4",
-": c #FEFCF3",
-"< c #FEFCF1",
-"[ c #FEFBEE",
-"} c #FFFDFA",
-"| c #DAAF36",
-"1 c #DAAA36",
-"2 c #FDFAF1",
-"3 c #F5DE94",
-"4 c #F4DC93",
-"5 c #F2D581",
-"6 c #EDCA6A",
-"7 c #EACB6C",
-"8 c #EFD385",
-"9 c #EFD280",
-"0 c #EFD07A",
-"a c #EECF76",
-"b c #EECF72",
-"c c #FBF7E9",
-"d c #DAAE34",
-"e c #DAAB35",
-"f c #FBF6E8",
-"g c #EFD494",
-"h c #EECE88",
-"i c #E9C173",
-"j c #F6E9C9",
-"k c #FEFCF2",
-"l c #FEFCF0",
-"m c #DAAB36",
-"n c #DAA637",
-"o c #FFFDF8",
-"p c #FFFDF6",
-"q c #FFFCF5",
-"r c #FCF6D8",
-"s c #F8E694",
-"t c #F7E385",
-"u c #F6DF76",
-"v c #F5DB68",
-"w c #F4D85C",
-"x c #FCF4D7",
-"y c #DAA435",
-"z c #DAA136",
-"A c #FEFCF6",
-"B c #FCF2C8",
-"C c #FBEFB9",
-"D c #FAECAC",
-"E c #F9E89C",
-"F c #F7E38B",
-"G c #F6E07C",
-"H c #F6DC6C",
-"I c #F5D95D",
-"J c #F4D64F",
-"K c #F3D344",
-"L c #FCF3D0",
-"M c #DA9F35",
-"N c #DA9A36",
-"O c #FDFAF2",
-"P c #FAEDB3",
-"Q c #F9E9A4",
-"R c #F8E695",
-"S c #F7E285",
-"T c #F6DE76",
-"U c #F5DB65",
-"V c #F4D757",
-"W c #F3D449",
-"X c #F2D13B",
-"Y c #F1CE30",
-"Z c #FBF2CC",
-"` c #DA9835",
-" . c #DA9435",
-".. c #FEFAEF",
-"+. c #F9E9A1",
-"@. c #F8E591",
-"#. c #F7E181",
-"$. c #F6DE72",
-"%. c #F5DA63",
-"&. c #F4D754",
-"*. c #F3D347",
-"=. c #F2D039",
-"-. c #F1CD2E",
-";. c #F0CB26",
-">. c #FBF2CA",
-",. c #D98E33",
-"'. c #FAF0DC",
-"). c #F4DDA7",
-"!. c #F4DB9E",
-"~. c #F3DA96",
-"{. c #F3D88E",
-"]. c #F3D786",
-"^. c #F2D47F",
-"/. c #F2D379",
-"(. c #F1D272",
-"_. c #F1D06C",
-":. c #F1CF69",
-"<. c #F8EAC2",
-"[. c #D8882D",
-"}. c #D8872D",
-"|. c #D8862C",
-" ",
-" ",
-" ",
-" . + @ @ @ # $ ",
-" % & * = - * ; > , , , ' ) ",
-" ! ~ { ] ^ / ( _ : < ( [ } | ",
-" 1 2 3 4 5 6 7 8 9 0 a b c d ",
-" e f g h i j k : k l ( [ * m ",
-" n * o p q : r s t u v w x y ",
-" z A B C D E F G H I J K L M ",
-" N O P Q R S T U V W X Y Z ` ",
-" ...+.@.#.$.%.&.*.=.-.;.>. . ",
-" ,.'.).!.~.{.].^./.(._.:.<.,. ",
-" [.}.[.[.[.[.[.[.[.[.}.[.|. ",
-" ",
-" "};
-
-/* image for file and folder */
-static rtgui_image_t *file_image, *folder_image;
-static struct rtgui_listbox_item items[] =
-{
-#ifdef RTGUI_USING_FONTHZ
- {"�����", RT_NULL},
- {"ѡ���ļ���", RT_NULL},
- {"�˳�", RT_NULL}
-#else
- {"Open folder", RT_NULL},
- {"Select folder", RT_NULL},
- {"Cancel", RT_NULL}
-#endif
-};
-static void rtgui_filelist_view_clear(rtgui_filelist_view_t* view);
-
-static void rtgui_filelist_view_on_folder_item(rtgui_widget_t* widget, struct rtgui_event* event)
-{
- rtgui_win_t *menu;
- rtgui_listbox_t *listbox;
- rtgui_filelist_view_t *view;
-
- listbox = RTGUI_LISTBOX(widget);
- menu = RTGUI_WIN(rtgui_widget_get_toplevel(widget));
- view = RTGUI_FILELIST_VIEW(menu->user_data);
-
- /* hide window */
- rtgui_win_hiden(menu);
-
- switch (listbox->current_item)
- {
- case 0:
- {
- char* dir_ptr;
-
- /* destroy menu window */
- rtgui_win_destroy(menu);
-
- dir_ptr = (char*) rtgui_malloc (256);
- rtgui_filelist_view_get_fullpath(view, dir_ptr, 256);
- rtgui_filelist_view_set_directory(view, dir_ptr);
- rt_free(dir_ptr);
- }
- break;
- case 1:
- /* destroy menu window */
- rtgui_win_destroy(menu);
- if (RTGUI_VIEW(view)->modal_show == RT_TRUE)
- {
- rtgui_view_end_modal(RTGUI_VIEW(view), RTGUI_MODAL_OK);
- }
- break;
-
- default:
- /* destroy menu window */
- rtgui_win_destroy(menu);
- break;
- }
-}
-
-static rt_bool_t rtgui_filelist_view_on_menu_deactivate(rtgui_widget_t* widget, struct rtgui_event* event)
-{
- rtgui_win_t *menu;
- menu = RTGUI_WIN(rtgui_widget_get_toplevel(widget));
-
- /* destroy menu window */
- rtgui_win_destroy(menu);
-
- return RT_TRUE;
-}
-
-static void rtgui_filelist_view_menu_pop(rtgui_widget_t *parent)
-{
- rtgui_win_t *menu;
- rtgui_listbox_t *listbox;
- rtgui_rect_t screen, rect = {0, 0, 140, 85};
-
- rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), &screen);
- rtgui_rect_moveto_align(&screen, &rect, RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL);
-
- menu = rtgui_win_create(RTGUI_TOPLEVEL(rtgui_widget_get_toplevel(parent)),
- "Folder Menu", &rect, RTGUI_WIN_STYLE_DEFAULT);
- if (menu != RT_NULL)
- {
- /* set user data on menu window */
- menu->user_data = (rt_uint32_t)parent;
-
- rtgui_win_set_ondeactivate(menu, rtgui_filelist_view_on_menu_deactivate);
-
- listbox = rtgui_listbox_create(items, sizeof(items)/sizeof(items[0]), &rect);
- rtgui_listbox_set_onitem(listbox, rtgui_filelist_view_on_folder_item);
- rtgui_container_add_child(RTGUI_CONTAINER(menu), RTGUI_WIDGET(listbox));
- rtgui_win_show(menu, RT_FALSE);
- rtgui_widget_focus(RTGUI_WIDGET(listbox));
- rtgui_listbox_set_current_item(listbox, 0);
- }
-}
-
-static void _rtgui_filelist_view_constructor(struct rtgui_filelist_view *view)
-{
- /* default rect */
- struct rtgui_rect rect = {0, 0, 200, 200};
-
- /* set default widget rect and set event handler */
- rtgui_widget_set_event_handler(RTGUI_WIDGET(view), rtgui_filelist_view_event_handler);
- rtgui_widget_set_rect(RTGUI_WIDGET(view), &rect);
-
- RTGUI_WIDGET(view)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
-
- view->current_item = 0;
- view->items_count = 0;
- view->page_items = 0;
-
- view->current_directory = RT_NULL;
- view->pattern = RT_NULL;
- RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(view)) = white;
- RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(view)) = RTGUI_ALIGN_CENTER_VERTICAL;
-
- file_image = rtgui_image_create_from_mem("xpm",
- (rt_uint8_t*)file_xpm, sizeof(file_xpm), RT_TRUE);
- folder_image = rtgui_image_create_from_mem("xpm",
- (rt_uint8_t*)folder_xpm, sizeof(folder_xpm), RT_TRUE);
-}
-
-static void _rtgui_filelist_view_destructor(struct rtgui_filelist_view *view)
-{
- /* delete all file items */
- rtgui_filelist_view_clear(view);
- /* delete current directory and pattern */
- rtgui_free(view->current_directory); view->current_directory = RT_NULL;
- rtgui_free(view->pattern); view->pattern = RT_NULL;
-
- /* delete image */
- rtgui_image_destroy(file_image);
- rtgui_image_destroy(folder_image);
-}
-
-DEFINE_CLASS_TYPE(filelist, "filelist",
- RTGUI_VIEW_TYPE,
- _rtgui_filelist_view_constructor,
- _rtgui_filelist_view_destructor,
- sizeof(struct rtgui_filelist_view));
-
-void rtgui_filelist_view_ondraw(struct rtgui_filelist_view* view)
-{
- struct rtgui_dc* dc;
- rt_uint16_t page_index, index;
- struct rtgui_file_item* item;
- struct rtgui_rect rect, item_rect, image_rect;
-
- dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view));
- if (dc == RT_NULL) return;
-
- rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
- rtgui_dc_fill_rect(dc, &rect);
-
- /* get item base rect */
- item_rect = rect;
- item_rect.y1 += 1;
- item_rect.y2 = item_rect.y1 + (1 + rtgui_theme_get_selected_height());
-
- /* get image base rect */
- image_rect.x1 = RTGUI_FILELIST_MARGIN; image_rect.y1 = 0;
- image_rect.x2 = RTGUI_FILELIST_MARGIN + file_image->w; image_rect.y2 = file_image->h;
- rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
-
- /* get current page */
- page_index = (view->current_item / view->page_items) * view->page_items;
- for (index = 0; index < view->page_items; index ++)
- {
- if (page_index + index >= view->items_count) break;
-
- item = &(view->items[page_index + index]);
-
- if (page_index + index == view->current_item)
- {
- rtgui_theme_draw_selected(dc, &item_rect);
- }
- else
- {
- /* draw background */
- rtgui_dc_fill_rect(dc, &item_rect);
- }
-
- /* draw item */
-
- if (item->type == RTGUI_FITEM_FILE)
- rtgui_image_blit(file_image, dc, &image_rect);
- else
- rtgui_image_blit(folder_image, dc, &image_rect);
-
- /* draw text */
- item_rect.x1 += RTGUI_FILELIST_MARGIN + file_image->w + 2;
- rtgui_dc_draw_text(dc, item->name, &item_rect);
- item_rect.x1 -= RTGUI_FILELIST_MARGIN + file_image->w + 2;
-
- /* move to next item position */
- item_rect.y1 += (rtgui_theme_get_selected_height() + 1);
- item_rect.y2 += (rtgui_theme_get_selected_height() + 1);
-
- image_rect.y1 += (rtgui_theme_get_selected_height() + 1);
- image_rect.y2 += (rtgui_theme_get_selected_height() + 1);
- }
-
- rtgui_dc_end_drawing(dc);
-}
-
-void rtgui_filelist_view_update_current(struct rtgui_filelist_view* view, rt_uint16_t old_item)
-{
- struct rtgui_dc* dc;
- struct rtgui_file_item* item;
- rtgui_rect_t rect, item_rect, image_rect;
-
- if (old_item/view->page_items != view->current_item/view->page_items)
- {
- /* it's not a same page, update all */
- rtgui_widget_update(RTGUI_WIDGET(view));
- return;
- }
-
- dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view));
- if (dc == RT_NULL) return;
-
- rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
-
- /* get old item rect */
- item_rect = rect;
- item_rect.y1 += 1;
- item_rect.y1 += (old_item % view->page_items) * (1 + rtgui_theme_get_selected_height());
- item_rect.y2 = item_rect.y1 + (1 + rtgui_theme_get_selected_height());
-
- /* get image rect */
- image_rect.x1 = RTGUI_FILELIST_MARGIN; image_rect.y1 = 0;
- image_rect.x2 = RTGUI_FILELIST_MARGIN + file_image->w; image_rect.y2 = file_image->h;
- rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
-
- /* draw old item */
- rtgui_dc_fill_rect(dc, &item_rect);
-
- item = &(view->items[old_item]);
- if (item->type == RTGUI_FITEM_FILE) /* draw item image */
- rtgui_image_blit(file_image, dc, &image_rect);
- else
- rtgui_image_blit(folder_image, dc, &image_rect);
-
- item_rect.x1 += RTGUI_FILELIST_MARGIN + file_image->w + 2;
- rtgui_dc_draw_text(dc, item->name, &item_rect);
-
- /* draw current item */
- item_rect = rect;
- item_rect.y1 += 1;
- item_rect.y1 += (view->current_item % view->page_items) * (1 + rtgui_theme_get_selected_height());
- item_rect.y2 = item_rect.y1 + (1 + rtgui_theme_get_selected_height());
-
- rtgui_theme_draw_selected(dc, &item_rect);
-
- /* get image base rect */
- image_rect.x1 = RTGUI_FILELIST_MARGIN; image_rect.y1 = 0;
- image_rect.x2 = RTGUI_FILELIST_MARGIN + file_image->w; image_rect.y2 = file_image->h;
- rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
-
- item = &(view->items[view->current_item]);
- if (item->type == RTGUI_FITEM_FILE) /* draw item image */
- rtgui_image_blit(file_image, dc, &image_rect);
- else
- rtgui_image_blit(folder_image, dc, &image_rect);
-
- item_rect.x1 += RTGUI_FILELIST_MARGIN + file_image->w + 2;
- rtgui_dc_draw_text(dc, item->name, &item_rect);
-
- rtgui_dc_end_drawing(dc);
-}
-
-static void rtgui_filelist_view_onenturn(struct rtgui_filelist_view* view)
-{
- if (view->items[view->current_item].type == RTGUI_FITEM_DIR)
- {
- char new_path[64];
-
- if (strcmp(view->items[view->current_item].name, ".") == 0) return ;
- if (strcmp(view->items[view->current_item].name, "..") == 0)
- {
- char *ptr;
- ptr = strrchr(view->current_directory, PATH_SEPARATOR);
-
- if (ptr == RT_NULL) return ;
- if (ptr == &(view->current_directory[0]))
- {
- /* it's root directory */
- new_path[0] = PATH_SEPARATOR;
- new_path[1] = '\0';
- }
- else
- {
- strncpy(new_path, view->current_directory, ptr - view->current_directory + 1);
- new_path[ptr - view->current_directory] = '\0';
- }
- }
- else if (view->current_item == 0 &&
-#ifdef _WIN32
- (view->current_directory[1] == ':') && (view->current_directory[2] == '\\'))
-#else
- (view->current_directory[0] == '/') && (view->current_directory[1] == '\0'))
-#endif
- {
- if (RTGUI_VIEW(view)->modal_show == RT_TRUE)
- {
- rtgui_view_end_modal(RTGUI_VIEW(view), RTGUI_MODAL_CANCEL);
- }
- else
- {
- rtgui_filelist_view_destroy(view);
- }
-
- return ;
- }
- else
- {
- rtgui_filelist_view_menu_pop(RTGUI_WIDGET(view));
- return ;
- }
- rtgui_filelist_view_set_directory(view, new_path);
- }
- else
- {
- if (RTGUI_VIEW(view)->modal_show == RT_TRUE)
- {
- rtgui_view_end_modal(RTGUI_VIEW(view), RTGUI_MODAL_OK);
- }
- }
-}
-
-rt_bool_t rtgui_filelist_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
-{
- struct rtgui_filelist_view* view = RT_NULL;
-
- view = RTGUI_FILELIST_VIEW(widget);
- switch (event->type)
- {
- case RTGUI_EVENT_PAINT:
- rtgui_filelist_view_ondraw(view);
- return RT_FALSE;
-
- case RTGUI_EVENT_RESIZE:
- {
- struct rtgui_event_resize* resize;
-
- resize = (struct rtgui_event_resize*)event;
-
- /* recalculate page items */
- if (file_image != RT_NULL)
- view->page_items = resize->h / (1 + rtgui_theme_get_selected_height());
- else
- view->page_items = resize->h / (2 + 14);
- }
- break;
-
- case RTGUI_EVENT_MOUSE_BUTTON:
- {
- rtgui_rect_t rect;
- struct rtgui_event_mouse* emouse;
-
- emouse = (struct rtgui_event_mouse*)event;
-
- /* calculate selected item */
-
- /* get physical extent information */
- rtgui_widget_get_rect(widget, &rect);
- rtgui_widget_rect_to_device(widget, &rect);
-
- if (rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK)
- {
- rt_uint16_t index;
- rt_uint16_t current_page;
- rt_uint16_t old_item;
-
- index = (emouse->y - rect.y1) / (2 + rtgui_theme_get_selected_height());
-
- /* get current page */
- current_page = view->current_item/view->page_items;
- old_item = view->current_item;
-
- if (index + current_page * view->page_items < view->items_count)
- {
- /* set selected item */
- view->current_item = index + current_page * view->page_items;
- if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN)
- {
- rtgui_filelist_view_update_current(view, old_item);
- }
- else
- {
- /* up event */
- rtgui_filelist_view_onenturn(view);
- }
- }
-
- return RT_TRUE;
- }
- }
- break;
-
- case RTGUI_EVENT_KBD:
- {
- struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
- if (ekbd->type == RTGUI_KEYDOWN)
- {
- rt_uint16_t old_item;
-
- old_item = view->current_item;
- switch (ekbd->key)
- {
- case RTGUIK_UP:
- if (view->current_item > 0)
- view->current_item --;
- rtgui_filelist_view_update_current(view, old_item);
- return RT_TRUE;
-
- case RTGUIK_DOWN:
- if (view->current_item < view->items_count - 1)
- view->current_item ++;
- rtgui_filelist_view_update_current(view, old_item);
- return RT_TRUE;
-
- case RTGUIK_LEFT:
- if (view->current_item - view->page_items >= 0)
- view->current_item -= view->page_items;
- rtgui_filelist_view_update_current(view, old_item);
- return RT_TRUE;
-
- case RTGUIK_RIGHT:
- if (view->current_item + view->page_items < view->items_count - 1)
- view->current_item += view->page_items;
- rtgui_filelist_view_update_current(view, old_item);
- return RT_TRUE;
-
- case RTGUIK_RETURN:
- rtgui_filelist_view_onenturn(view);
- return RT_TRUE;
-
- default:
- break;
- }
- }
- }
- return RT_FALSE;
- }
-
- /* use view event handler */
- return rtgui_view_event_handler(widget, event);
-}
-
-rtgui_filelist_view_t* rtgui_filelist_view_create(rtgui_workbench_t* workbench,
- const char* directory, const char* pattern, const rtgui_rect_t* rect)
-{
- struct rtgui_filelist_view* view = RT_NULL;
-
- /* create a new view */
- view = (struct rtgui_filelist_view*) rtgui_widget_create(RTGUI_FILELIST_VIEW_TYPE);
- if (view != RT_NULL)
- {
- view->items = RT_NULL;
- view->pattern = rt_strdup(pattern);
- view->page_items = rtgui_rect_height(*rect) / (1 + rtgui_theme_get_selected_height());
- rtgui_filelist_view_set_directory(view, directory);
-
- rtgui_workbench_add_view(workbench, RTGUI_VIEW(view));
- }
-
- return view;
-}
-
-void rtgui_filelist_view_destroy(rtgui_filelist_view_t* view)
-{
- /* destroy view */
- rtgui_widget_destroy(RTGUI_WIDGET(view));
-}
-
-/* clear all file items */
-static void rtgui_filelist_view_clear(rtgui_filelist_view_t* view)
-{
- rt_uint32_t index;
- struct rtgui_file_item* item;
-
- for (index = 0; index < view->items_count; index ++)
- {
- item = &(view->items[index]);
-
- /* release item name */
- rt_free(item->name);
- item->name = RT_NULL;
- }
-
- /* release items */
- rtgui_free(view->items);
- view->items = RT_NULL;
-
- view->items_count = 0;
- view->current_item = 0;
-}
-
-void rtgui_filelist_view_set_directory(rtgui_filelist_view_t* view, const char* directory)
-{
- struct rtgui_file_item *item;
-
- RT_ASSERT(view != RT_NULL);
-
- /* clear file items firstly */
- rtgui_filelist_view_clear(view);
- if (directory != RT_NULL)
- {
- DIR* dir;
- struct stat s;
- char* fullpath;
- rt_uint32_t index;
- struct dirent* dirent;
-
- view->items_count = 0;
- dir = opendir(directory);
- if (dir == RT_NULL) goto __return;
-
- /* current directory exists, set it */
- if (view->current_directory != RT_NULL) rt_free(view->current_directory);
- view->current_directory = rt_strdup(directory);
-
- do
- {
- dirent = readdir(dir);
- if (dirent == RT_NULL) break;
-
- if (strcmp(dirent->d_name, ".") == 0) continue;
- if (strcmp(dirent->d_name, "..") == 0) continue;
-
- view->items_count ++;
- } while (dirent != RT_NULL);
- closedir(dir);
-
- view->items_count ++; /* root directory for [x] exit, others for .. */
-
- view->items = (struct rtgui_file_item*) rtgui_malloc(sizeof(struct rtgui_file_item) * view->items_count);
- if (view->items == RT_NULL) return; /* no memory */
-
- index = 0;
- if (directory[0] == '/' && directory[1] != '\0')
- {
- item = &(view->items[0]);
-
- /* add .. directory */
- item->name = rt_strdup("..");
- item->type = RTGUI_FITEM_DIR;
- item->size = 0;
-
- index ++;
- }
- else
- {
- item = &(view->items[0]);
-
- /* add .. directory */
- item->name = rt_strdup("�˳��ļ����");
- item->type = RTGUI_FITEM_DIR;
- item->size = 0;
-
- index ++;
- }
-
- /* reopen directory */
- dir = opendir(directory);
- fullpath = rtgui_malloc(256);
- while (index < view->items_count)
- {
- dirent = readdir(dir);
- if (dirent == RT_NULL) break;
-
- if (strcmp(dirent->d_name, ".") == 0) continue;
- if (strcmp(dirent->d_name, "..") == 0) continue;
-
- item = &(view->items[index]);
- item->name = rt_strdup(dirent->d_name);
-
- rt_memset(&s, 0, sizeof(struct stat));
-
- /* build full path for the file */
- if (directory[strlen(directory) - 1] != PATH_SEPARATOR)
- rt_snprintf(fullpath, 256, "%s%c%s", directory, PATH_SEPARATOR, dirent->d_name);
- else
- rt_snprintf(fullpath, 256, "%s%s", directory, dirent->d_name);
-
- stat(fullpath, &s);
- if ( s.st_mode & S_IFDIR )
- {
- item->type = RTGUI_FITEM_DIR;
- item->size = 0;
- }
- else
- {
- item->type = RTGUI_FITEM_FILE;
- item->size = s.st_size;
- }
-
- index ++;
- }
- rtgui_free(fullpath);
- closedir(dir);
- }
-
- view->current_item = 0;
-
-__return:
- /* update view */
- rtgui_widget_update(RTGUI_WIDGET(view));
-}
-
-void rtgui_filelist_view_get_fullpath(rtgui_filelist_view_t* view, char* path, rt_size_t len)
-{
- RT_ASSERT(view != RT_NULL);
-
- if (view->current_directory[strlen(view->current_directory) - 1] != PATH_SEPARATOR)
- rt_snprintf(path, len, "%s%c%s",view->current_directory, PATH_SEPARATOR,
- view->items[view->current_item].name);
- else
- rt_snprintf(path, len, "%s%s",view->current_directory,
- view->items[view->current_item].name);
-}
-#endif
+/* + * File : filelist_view.c + * This file is part of RTGUI in RT-Thread RTOS + * COPYRIGHT (C) 2010, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2010-01-06 Bernard first version + */ + +#include <rtgui/rtgui_object.h> +#include <rtgui/rtgui_system.h> +#include <rtgui/rtgui_theme.h> +#include <rtgui/rtgui_application.h> + +#include <rtgui/list.h> +#include <rtgui/image.h> +#include <rtgui/widgets/container.h> +#include <rtgui/widgets/filelist_view.h> +#include <rtgui/widgets/listbox.h> +#include <rtgui/widgets/window.h> + +#if defined(RTGUI_USING_DFS_FILERW) || defined(RTGUI_USING_STDIO_FILERW) +#ifdef _WIN32 +#include <io.h> +#include <dirent.h> +#include <sys/stat.h> +#define PATH_SEPARATOR '\\' +#else +#include <dfs_posix.h> +#define PATH_SEPARATOR '/' +#endif + +#include <string.h> + +#define RTGUI_FILELIST_MARGIN 5 + +const static char * file_xpm[] = { +"16 16 21 1", +" c None", +". c #999999", +"+ c #818181", +"@ c #FFFFFF", +"# c #ECECEC", +"$ c #EAEAEA", +"% c #EBEBEB", +"& c #EDEDED", +"* c #F0F0F0", +"= c #C4C4C4", +"- c #C5C5C5", +"; c #C6C6C6", +"> c #C7C7C7", +", c #EEEEEE", +"' c #EDEDE5", +") c #EDEDE6", +"! c #EFEFEF", +"~ c #C8C8C8", +"{ c #F1F1F1", +"] c #F2F2F2", +"^ c #959595", +".++++++++++++ ", +"+@@@@@@@@@@@@+ ", +"+@#$$%%%##&*@+ ", +"+@$=--;;;;>*@+ ", +"+@$%%###&&,*@+ ", +"+@%-;;;;;;>*@+ ", +"+@%%##&&'#,*@+ ", +"+@%;;;;,,),*@+ ", +"+@##&&,,!!!*@+ ", +"+@#;;;>>~~~*@+ ", +"+@#&,,!!*{{{@+ ", +"+@&;>>~~~{{]@+ ", +"+@&&,!!**{]]@+ ", +"+@@@@@@@@@@@@+ ", +"^++++++++++++^ ", +" "}; + +const static char * folder_xpm[] = { +"16 16 121 2", +" c None", +". c #D9B434", +"+ c #E1C25E", +"@ c #E2C360", +"# c #E2C35F", +"$ c #DBB63C", +"% c #DAB336", +"& c #FEFEFD", +"* c #FFFFFE", +"= c #FFFEFE", +"- c #FFFEFD", +"; c #FBF7EA", +"> c #E4C76B", +", c #E3C76B", +"' c #E6CD79", +") c #E5CA74", +"! c #DAAF35", +"~ c #FEFCF7", +"{ c #F8E48E", +"] c #F5DE91", +"^ c #F5E09F", +"/ c #F6E1AC", +"( c #FEFBEF", +"_ c #FEFDF4", +": c #FEFCF3", +"< c #FEFCF1", +"[ c #FEFBEE", +"} c #FFFDFA", +"| c #DAAF36", +"1 c #DAAA36", +"2 c #FDFAF1", +"3 c #F5DE94", +"4 c #F4DC93", +"5 c #F2D581", +"6 c #EDCA6A", +"7 c #EACB6C", +"8 c #EFD385", +"9 c #EFD280", +"0 c #EFD07A", +"a c #EECF76", +"b c #EECF72", +"c c #FBF7E9", +"d c #DAAE34", +"e c #DAAB35", +"f c #FBF6E8", +"g c #EFD494", +"h c #EECE88", +"i c #E9C173", +"j c #F6E9C9", +"k c #FEFCF2", +"l c #FEFCF0", +"m c #DAAB36", +"n c #DAA637", +"o c #FFFDF8", +"p c #FFFDF6", +"q c #FFFCF5", +"r c #FCF6D8", +"s c #F8E694", +"t c #F7E385", +"u c #F6DF76", +"v c #F5DB68", +"w c #F4D85C", +"x c #FCF4D7", +"y c #DAA435", +"z c #DAA136", +"A c #FEFCF6", +"B c #FCF2C8", +"C c #FBEFB9", +"D c #FAECAC", +"E c #F9E89C", +"F c #F7E38B", +"G c #F6E07C", +"H c #F6DC6C", +"I c #F5D95D", +"J c #F4D64F", +"K c #F3D344", +"L c #FCF3D0", +"M c #DA9F35", +"N c #DA9A36", +"O c #FDFAF2", +"P c #FAEDB3", +"Q c #F9E9A4", +"R c #F8E695", +"S c #F7E285", +"T c #F6DE76", +"U c #F5DB65", +"V c #F4D757", +"W c #F3D449", +"X c #F2D13B", +"Y c #F1CE30", +"Z c #FBF2CC", +"` c #DA9835", +" . c #DA9435", +".. c #FEFAEF", +"+. c #F9E9A1", +"@. c #F8E591", +"#. c #F7E181", +"$. c #F6DE72", +"%. c #F5DA63", +"&. c #F4D754", +"*. c #F3D347", +"=. c #F2D039", +"-. c #F1CD2E", +";. c #F0CB26", +">. c #FBF2CA", +",. c #D98E33", +"'. c #FAF0DC", +"). c #F4DDA7", +"!. c #F4DB9E", +"~. c #F3DA96", +"{. c #F3D88E", +"]. c #F3D786", +"^. c #F2D47F", +"/. c #F2D379", +"(. c #F1D272", +"_. c #F1D06C", +":. c #F1CF69", +"<. c #F8EAC2", +"[. c #D8882D", +"}. c #D8872D", +"|. c #D8862C", +" ", +" ", +" ", +" . + @ @ @ # $ ", +" % & * = - * ; > , , , ' ) ", +" ! ~ { ] ^ / ( _ : < ( [ } | ", +" 1 2 3 4 5 6 7 8 9 0 a b c d ", +" e f g h i j k : k l ( [ * m ", +" n * o p q : r s t u v w x y ", +" z A B C D E F G H I J K L M ", +" N O P Q R S T U V W X Y Z ` ", +" ...+.@.#.$.%.&.*.=.-.;.>. . ", +" ,.'.).!.~.{.].^./.(._.:.<.,. ", +" [.}.[.[.[.[.[.[.[.[.}.[.|. ", +" ", +" "}; + +/* image for file and folder */ +static rtgui_image_t *file_image, *folder_image; +static struct rtgui_listbox_item items[] = +{ +#ifdef RTGUI_USING_FONTHZ + {"���ː`����", RT_NULL}, + {"���v�`����", RT_NULL}, + {"�X��", RT_NULL} +#else + {"Open folder", RT_NULL}, + {"Select folder", RT_NULL}, + {"Cancel", RT_NULL} +#endif +}; +static void rtgui_filelist_view_clear(rtgui_filelist_view_t* view); + +static void rtgui_filelist_view_on_folder_item(rtgui_widget_t* widget, struct rtgui_event* event) +{ + rtgui_win_t *menu; + rtgui_listbox_t *listbox; + rtgui_filelist_view_t *view; + + listbox = RTGUI_LISTBOX(widget); + menu = RTGUI_WIN(rtgui_widget_get_toplevel(widget)); + view = RTGUI_FILELIST_VIEW(menu->user_data); + + /* hide window */ + rtgui_win_hiden(menu); + + switch (listbox->current_item) + { + case 0: + { + char* dir_ptr; + + /* destroy menu window */ + rtgui_win_destroy(menu); + + dir_ptr = (char*) rtgui_malloc (256); + rtgui_filelist_view_get_fullpath(view, dir_ptr, 256); + rtgui_filelist_view_set_directory(view, dir_ptr); + rt_free(dir_ptr); + } + break; + case 1: + /* destroy menu window */ + rtgui_win_destroy(menu); + break; + + default: + /* destroy menu window */ + rtgui_win_destroy(menu); + break; + } +} + +static rt_bool_t rtgui_filelist_view_on_menu_deactivate(rtgui_widget_t* widget, struct rtgui_event* event) +{ + rtgui_win_t *menu; + menu = RTGUI_WIN(rtgui_widget_get_toplevel(widget)); + + /* destroy menu window */ + rtgui_win_destroy(menu); + + return RT_TRUE; +} + +static void rtgui_filelist_view_menu_pop(rtgui_widget_t *parent) +{ + rtgui_win_t *menu; + rtgui_listbox_t *listbox; + rtgui_rect_t screen, rect = {0, 0, 140, 85}; + + rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), &screen); + rtgui_rect_moveto_align(&screen, &rect, RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL); + + menu = rtgui_win_create(RTGUI_TOPLEVEL(rtgui_widget_get_toplevel(parent)), + "Folder Menu", &rect, RTGUI_WIN_STYLE_DEFAULT); + if (menu != RT_NULL) + { + /* set user data on menu window */ + menu->user_data = (rt_uint32_t)parent; + + rtgui_win_set_ondeactivate(menu, rtgui_filelist_view_on_menu_deactivate); + + listbox = rtgui_listbox_create(items, sizeof(items)/sizeof(items[0]), &rect); + rtgui_listbox_set_onitem(listbox, rtgui_filelist_view_on_folder_item); + rtgui_container_add_child(RTGUI_CONTAINER(menu), RTGUI_WIDGET(listbox)); + rtgui_win_show(menu, RT_FALSE); + rtgui_widget_focus(RTGUI_WIDGET(listbox)); + rtgui_listbox_set_current_item(listbox, 0); + } +} + +static void _rtgui_filelist_view_constructor(struct rtgui_filelist_view *view) +{ + /* default rect */ + struct rtgui_rect rect = {0, 0, 200, 200}; + + /* set default widget rect and set event handler */ + rtgui_object_set_event_handler(RTGUI_WIDGET(view), rtgui_filelist_view_event_handler); + rtgui_widget_set_rect(RTGUI_WIDGET(view), &rect); + + RTGUI_WIDGET(view)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE; + + view->current_item = 0; + view->items_count = 0; + view->page_items = 0; + + view->current_directory = RT_NULL; + view->pattern = RT_NULL; + RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(view)) = white; + RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(view)) = RTGUI_ALIGN_CENTER_VERTICAL; + + file_image = rtgui_image_create_from_mem("xpm", + (rt_uint8_t*)file_xpm, sizeof(file_xpm), RT_TRUE); + folder_image = rtgui_image_create_from_mem("xpm", + (rt_uint8_t*)folder_xpm, sizeof(folder_xpm), RT_TRUE); +} + +static void _rtgui_filelist_view_destructor(struct rtgui_filelist_view *view) +{ + /* delete all file items */ + rtgui_filelist_view_clear(view); + /* delete current directory and pattern */ + rtgui_free(view->current_directory); view->current_directory = RT_NULL; + rtgui_free(view->pattern); view->pattern = RT_NULL; + + /* delete image */ + rtgui_image_destroy(file_image); + rtgui_image_destroy(folder_image); +} + +DEFINE_CLASS_TYPE(filelist, "filelist", + RTGUI_CONTAINER_TYPE, + _rtgui_filelist_view_constructor, + _rtgui_filelist_view_destructor, + sizeof(struct rtgui_filelist_view)); + +void rtgui_filelist_view_ondraw(struct rtgui_filelist_view* view) +{ + struct rtgui_dc* dc; + rt_uint16_t page_index, index; + struct rtgui_file_item* item; + struct rtgui_rect rect, item_rect, image_rect; + + dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view)); + if (dc == RT_NULL) return; + + rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); + rtgui_dc_fill_rect(dc, &rect); + + /* get item base rect */ + item_rect = rect; + item_rect.y1 += 1; + item_rect.y2 = item_rect.y1 + (1 + rtgui_theme_get_selected_height()); + + /* get image base rect */ + image_rect.x1 = RTGUI_FILELIST_MARGIN; image_rect.y1 = 0; + image_rect.x2 = RTGUI_FILELIST_MARGIN + file_image->w; image_rect.y2 = file_image->h; + rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL); + + /* get current page */ + page_index = (view->current_item / view->page_items) * view->page_items; + for (index = 0; index < view->page_items; index ++) + { + if (page_index + index >= view->items_count) break; + + item = &(view->items[page_index + index]); + + if (page_index + index == view->current_item) + { + rtgui_theme_draw_selected(dc, &item_rect); + } + else + { + /* draw background */ + rtgui_dc_fill_rect(dc, &item_rect); + } + + /* draw item */ + if (item->type == RTGUI_FITEM_FILE) + rtgui_image_blit(file_image, dc, &image_rect); + else + rtgui_image_blit(folder_image, dc, &image_rect); + + /* draw text */ + item_rect.x1 += RTGUI_FILELIST_MARGIN + file_image->w + 2; + rtgui_dc_draw_text(dc, item->name, &item_rect); + item_rect.x1 -= RTGUI_FILELIST_MARGIN + file_image->w + 2; + + /* move to next item position */ + item_rect.y1 += (rtgui_theme_get_selected_height() + 1); + item_rect.y2 += (rtgui_theme_get_selected_height() + 1); + + image_rect.y1 += (rtgui_theme_get_selected_height() + 1); + image_rect.y2 += (rtgui_theme_get_selected_height() + 1); + } + + rtgui_dc_end_drawing(dc); +} + +void rtgui_filelist_view_update_current(struct rtgui_filelist_view* view, rt_uint16_t old_item) +{ + struct rtgui_dc* dc; + struct rtgui_file_item* item; + rtgui_rect_t rect, item_rect, image_rect; + + if (old_item/view->page_items != view->current_item/view->page_items) + { + /* it's not a same page, update all */ + rtgui_widget_update(RTGUI_WIDGET(view)); + return; + } + + dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view)); + if (dc == RT_NULL) return; + + rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); + + /* get old item rect */ + item_rect = rect; + item_rect.y1 += 1; + item_rect.y1 += (old_item % view->page_items) * (1 + rtgui_theme_get_selected_height()); + item_rect.y2 = item_rect.y1 + (1 + rtgui_theme_get_selected_height()); + + /* get image rect */ + image_rect.x1 = RTGUI_FILELIST_MARGIN; image_rect.y1 = 0; + image_rect.x2 = RTGUI_FILELIST_MARGIN + file_image->w; image_rect.y2 = file_image->h; + rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL); + + /* draw old item */ + rtgui_dc_fill_rect(dc, &item_rect); + + item = &(view->items[old_item]); + if (item->type == RTGUI_FITEM_FILE) /* draw item image */ + rtgui_image_blit(file_image, dc, &image_rect); + else + rtgui_image_blit(folder_image, dc, &image_rect); + + item_rect.x1 += RTGUI_FILELIST_MARGIN + file_image->w + 2; + rtgui_dc_draw_text(dc, item->name, &item_rect); + + /* draw current item */ + item_rect = rect; + item_rect.y1 += 1; + item_rect.y1 += (view->current_item % view->page_items) * (1 + rtgui_theme_get_selected_height()); + item_rect.y2 = item_rect.y1 + (1 + rtgui_theme_get_selected_height()); + + rtgui_theme_draw_selected(dc, &item_rect); + + /* get image base rect */ + image_rect.x1 = RTGUI_FILELIST_MARGIN; image_rect.y1 = 0; + image_rect.x2 = RTGUI_FILELIST_MARGIN + file_image->w; image_rect.y2 = file_image->h; + rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL); + + item = &(view->items[view->current_item]); + if (item->type == RTGUI_FITEM_FILE) /* draw item image */ + rtgui_image_blit(file_image, dc, &image_rect); + else + rtgui_image_blit(folder_image, dc, &image_rect); + + item_rect.x1 += RTGUI_FILELIST_MARGIN + file_image->w + 2; + rtgui_dc_draw_text(dc, item->name, &item_rect); + + rtgui_dc_end_drawing(dc); +} + +static void rtgui_filelist_view_onenturn(struct rtgui_filelist_view* view) +{ + if (view->items[view->current_item].type == RTGUI_FITEM_DIR) + { + char new_path[64]; + + if (strcmp(view->items[view->current_item].name, ".") == 0) return ; + if (strcmp(view->items[view->current_item].name, "..") == 0) + { + char *ptr; + ptr = strrchr(view->current_directory, PATH_SEPARATOR); + + if (ptr == RT_NULL) return ; + if (ptr == &(view->current_directory[0])) + { + /* it's root directory */ + new_path[0] = PATH_SEPARATOR; + new_path[1] = '\0'; + } + else + { + strncpy(new_path, view->current_directory, ptr - view->current_directory + 1); + new_path[ptr - view->current_directory] = '\0'; + } + } + else if (view->current_item == 0 && +#ifdef _WIN32 + (view->current_directory[1] == ':') && (view->current_directory[2] == '\\') +#else + (view->current_directory[0] == '/') && (view->current_directory[1] == '\0') +#endif + ) + { + rtgui_filelist_view_destroy(view); + + return ; + } + else + { + rtgui_filelist_view_menu_pop(RTGUI_WIDGET(view)); + return ; + } + rtgui_filelist_view_set_directory(view, new_path); + } +} + +rt_bool_t rtgui_filelist_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event) +{ + struct rtgui_filelist_view* view = RT_NULL; + + view = RTGUI_FILELIST_VIEW(widget); + switch (event->type) + { + case RTGUI_EVENT_PAINT: + rtgui_filelist_view_ondraw(view); + return RT_FALSE; + + case RTGUI_EVENT_RESIZE: + { + struct rtgui_event_resize* resize; + + resize = (struct rtgui_event_resize*)event; + + /* recalculate page items */ + if (file_image != RT_NULL) + view->page_items = resize->h / (1 + rtgui_theme_get_selected_height()); + else + view->page_items = resize->h / (2 + 14); + } + break; + + case RTGUI_EVENT_MOUSE_BUTTON: + { + rtgui_rect_t rect; + struct rtgui_event_mouse* emouse; + + emouse = (struct rtgui_event_mouse*)event; + + /* calculate selected item */ + + /* get physical extent information */ + rtgui_widget_get_rect(widget, &rect); + rtgui_widget_rect_to_device(widget, &rect); + + if (rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK) + { + rt_uint16_t index; + rt_uint16_t current_page; + rt_uint16_t old_item; + + index = (emouse->y - rect.y1) / (2 + rtgui_theme_get_selected_height()); + + /* get current page */ + current_page = view->current_item/view->page_items; + old_item = view->current_item; + + if (index + current_page * view->page_items < view->items_count) + { + /* set selected item */ + view->current_item = index + current_page * view->page_items; + if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN) + { + rtgui_filelist_view_update_current(view, old_item); + } + else + { + /* up event */ + rtgui_filelist_view_onenturn(view); + } + } + + return RT_TRUE; + } + } + break; + + case RTGUI_EVENT_KBD: + { + struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event; + if (ekbd->type == RTGUI_KEYDOWN) + { + rt_uint16_t old_item; + + old_item = view->current_item; + switch (ekbd->key) + { + case RTGUIK_UP: + if (view->current_item > 0) + view->current_item --; + rtgui_filelist_view_update_current(view, old_item); + return RT_TRUE; + + case RTGUIK_DOWN: + if (view->current_item < view->items_count - 1) + view->current_item ++; + rtgui_filelist_view_update_current(view, old_item); + return RT_TRUE; + + case RTGUIK_LEFT: + if (view->current_item - view->page_items >= 0) + view->current_item -= view->page_items; + rtgui_filelist_view_update_current(view, old_item); + return RT_TRUE; + + case RTGUIK_RIGHT: + if (view->current_item + view->page_items < view->items_count - 1) + view->current_item += view->page_items; + rtgui_filelist_view_update_current(view, old_item); + return RT_TRUE; + + case RTGUIK_RETURN: + rtgui_filelist_view_onenturn(view); + return RT_TRUE; + + default: + break; + } + } + } + return RT_FALSE; + } + + /* use view event handler */ + return rtgui_container_event_handler(widget, event); +} + +rtgui_filelist_view_t* rtgui_filelist_view_create(const char* directory, + const char* pattern, + const rtgui_rect_t* rect) +{ + struct rtgui_filelist_view* view = RT_NULL; + + /* create a new view */ + view = (struct rtgui_filelist_view*) rtgui_widget_create(RTGUI_FILELIST_VIEW_TYPE); + if (view != RT_NULL) + { + view->items = RT_NULL; + view->pattern = rt_strdup(pattern); + view->page_items = rtgui_rect_height(*rect) / (1 + rtgui_theme_get_selected_height()); + rtgui_filelist_view_set_directory(view, directory); + } + + return view; +} + +void rtgui_filelist_view_destroy(rtgui_filelist_view_t* view) +{ + /* destroy view */ + rtgui_widget_destroy(RTGUI_WIDGET(view)); +} + +/* clear all file items */ +static void rtgui_filelist_view_clear(rtgui_filelist_view_t* view) +{ + rt_uint32_t index; + struct rtgui_file_item* item; + + for (index = 0; index < view->items_count; index ++) + { + item = &(view->items[index]); + + /* release item name */ + rt_free(item->name); + item->name = RT_NULL; + } + + /* release items */ + rtgui_free(view->items); + view->items = RT_NULL; + + view->items_count = 0; + view->current_item = 0; +} + +void rtgui_filelist_view_set_directory(rtgui_filelist_view_t* view, const char* directory) +{ + struct rtgui_file_item *item; + + RT_ASSERT(view != RT_NULL); + + /* clear file items firstly */ + rtgui_filelist_view_clear(view); + if (directory != RT_NULL) + { + DIR* dir; + struct stat s; + char* fullpath; + rt_uint32_t index; + struct dirent* dirent; + + view->items_count = 0; + dir = opendir(directory); + if (dir == RT_NULL) goto __return; + + /* current directory exists, set it */ + if (view->current_directory != RT_NULL) rt_free(view->current_directory); + view->current_directory = rt_strdup(directory); + + do + { + dirent = readdir(dir); + if (dirent == RT_NULL) break; + + if (strcmp(dirent->d_name, ".") == 0) continue; + if (strcmp(dirent->d_name, "..") == 0) continue; + + view->items_count ++; + } while (dirent != RT_NULL); + closedir(dir); + + view->items_count ++; /* root directory for [x] exit, others for .. */ + + view->items = (struct rtgui_file_item*) rtgui_malloc(sizeof(struct rtgui_file_item) * view->items_count); + if (view->items == RT_NULL) return; /* no memory */ + + index = 0; + if (directory[0] == '/' && directory[1] != '\0') + { + item = &(view->items[0]); + + /* add .. directory */ + item->name = rt_strdup(".."); + item->type = RTGUI_FITEM_DIR; + item->size = 0; + + index ++; + } + else + { + item = &(view->items[0]); + + /* add .. directory */ + item->name = rt_strdup("�X�̐`��㚔M"); + item->type = RTGUI_FITEM_DIR; + item->size = 0; + + index ++; + } + + /* reopen directory */ + dir = opendir(directory); + fullpath = rtgui_malloc(256); + while (index < view->items_count) + { + dirent = readdir(dir); + if (dirent == RT_NULL) break; + + if (strcmp(dirent->d_name, ".") == 0) continue; + if (strcmp(dirent->d_name, "..") == 0) continue; + + item = &(view->items[index]); + item->name = rt_strdup(dirent->d_name); + + rt_memset(&s, 0, sizeof(struct stat)); + + /* build full path for the file */ + if (directory[strlen(directory) - 1] != PATH_SEPARATOR) + rt_snprintf(fullpath, 256, "%s%c%s", directory, PATH_SEPARATOR, dirent->d_name); + else + rt_snprintf(fullpath, 256, "%s%s", directory, dirent->d_name); + + stat(fullpath, &s); + if ( s.st_mode & S_IFDIR ) + { + item->type = RTGUI_FITEM_DIR; + item->size = 0; + } + else + { + item->type = RTGUI_FITEM_FILE; + item->size = s.st_size; + } + + index ++; + } + rtgui_free(fullpath); + closedir(dir); + } + + view->current_item = 0; + +__return: + /* update view */ + rtgui_widget_update(RTGUI_WIDGET(view)); +} + +void rtgui_filelist_view_get_fullpath(rtgui_filelist_view_t* view, char* path, rt_size_t len) +{ + RT_ASSERT(view != RT_NULL); + + if (view->current_directory[strlen(view->current_directory) - 1] != PATH_SEPARATOR) + rt_snprintf(path, len, "%s%c%s",view->current_directory, PATH_SEPARATOR, + view->items[view->current_item].name); + else + rt_snprintf(path, len, "%s%s",view->current_directory, + view->items[view->current_item].name); +} +#endif diff --git a/components/rtgui/widgets/iconbox.c b/components/rtgui/widgets/iconbox.c index 860fc44476..1ba74e3ce2 100644 --- a/components/rtgui/widgets/iconbox.c +++ b/components/rtgui/widgets/iconbox.c @@ -19,7 +19,7 @@ static void _rtgui_iconbox_constructor(rtgui_iconbox_t *iconbox) { /* init widget and set event handler */ RTGUI_WIDGET(iconbox)->flag |= RTGUI_WIDGET_FLAG_TRANSPARENT; - rtgui_widget_set_event_handler(RTGUI_WIDGET(iconbox), rtgui_iconbox_event_handler); + rtgui_object_set_event_handler(RTGUI_OBJECT(iconbox), rtgui_iconbox_event_handler); /* set proper of control */ iconbox->image = RT_NULL; @@ -46,9 +46,14 @@ DEFINE_CLASS_TYPE(iconbox, "iconbox", _rtgui_iconbox_destructor, sizeof(struct rtgui_iconbox)); -rt_bool_t rtgui_iconbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event) +rt_bool_t rtgui_iconbox_event_handler(struct rtgui_object* object, struct rtgui_event* event) { - struct rtgui_iconbox* iconbox = (struct rtgui_iconbox*)widget; + struct rtgui_iconbox* iconbox; + + RT_ASSERT(object != RT_NULL); + RT_ASSERT(event != RT_NULL); + + iconbox = RTGUI_ICONBOX(object); switch (event->type) { diff --git a/components/rtgui/widgets/label.c b/components/rtgui/widgets/label.c index 59cf22b6f4..db8528e139 100644 --- a/components/rtgui/widgets/label.c +++ b/components/rtgui/widgets/label.c @@ -19,7 +19,7 @@ static void _rtgui_label_constructor(rtgui_label_t *label) { /* init widget and set event handler */ - rtgui_widget_set_event_handler(RTGUI_WIDGET(label), rtgui_label_event_handler); + rtgui_object_set_event_handler(RTGUI_OBJECT(label), rtgui_label_event_handler); /* set field */ label->text = RT_NULL; @@ -38,13 +38,12 @@ DEFINE_CLASS_TYPE(label, "label", _rtgui_label_destructor, sizeof(struct rtgui_label)); -rt_bool_t rtgui_label_event_handler(struct rtgui_widget* widget, struct rtgui_event* event) +rt_bool_t rtgui_label_event_handler(struct rtgui_object *object, struct rtgui_event* event) { - struct rtgui_label* label; + struct rtgui_label *label; + RTGUI_WIDGET_EVENT_HANDLER_PREPARE - RT_ASSERT(widget != RT_NULL); - - label = (struct rtgui_label*) widget; + label = RTGUI_LABEL(object); switch (event->type) { case RTGUI_EVENT_PAINT: diff --git a/components/rtgui/widgets/list_view.c b/components/rtgui/widgets/list_view.c index 99783f2cf3..1b45365271 100644 --- a/components/rtgui/widgets/list_view.c +++ b/components/rtgui/widgets/list_view.c @@ -1,636 +1,636 @@ -/*
- * File : list_view.c
- * This file is part of RTGUI in RT-Thread RTOS
- * COPYRIGHT (C) 2010, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2010-01-06 Bernard first version
- */
-
-#include <rtgui/rtgui_theme.h>
-#include <rtgui/widgets/list_view.h>
-
-#define LIST_MARGIN 5
-
-static void _rtgui_list_view_constructor(struct rtgui_list_view *view)
-{
- /* default rect */
- struct rtgui_rect rect = {0, 0, 200, 200};
-
- /* set default widget rect and set event handler */
- rtgui_widget_set_event_handler(RTGUI_WIDGET(view),rtgui_list_view_event_handler);
- rtgui_widget_set_rect(RTGUI_WIDGET(view), &rect);
-
- RTGUI_WIDGET(view)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
-
- view->flag = RTGUI_LIST_VIEW_LIST;
- view->current_item = 0;
- view->items_count = 0;
- view->page_items = 0;
-
- RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(view)) = white;
- RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(view)) = RTGUI_ALIGN_CENTER_VERTICAL;
-}
-
-DEFINE_CLASS_TYPE(listview, "listview",
- RTGUI_VIEW_TYPE,
- _rtgui_list_view_constructor,
- RT_NULL,
- sizeof(struct rtgui_list_view));
-
-static void rtgui_list_view_onicondraw(struct rtgui_list_view* view, struct rtgui_dc *dc)
-{
- struct rtgui_rect rect, item_rect, drawing_rect;
- rt_ubase_t c, r, item_index; /* col and row index */
- rt_ubase_t item_width, item_height;
- rtgui_image_t* image;
-
- if (view->items_count == 0) return;
-
- rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
- item_index = (view->current_item / view->page_items) * view->page_items;
-
- item_width = (rtgui_rect_width(rect) - 2 * LIST_MARGIN)/view->col_items;
- item_height = (rtgui_rect_height(rect) - 4)/view->row_items;
- image = view->items[0].image;
-
- for (r = 0; r < view->row_items; r ++)
- {
- for (c = 0; c < view->col_items; c ++)
- {
- if (item_index < view->items_count)
- {
- item_rect.y1 = rect.y1 + LIST_MARGIN + r * item_height;
- item_rect.x1 = rect.x1 + LIST_MARGIN + c * item_width;
- item_rect.x2 = item_rect.x1 + item_width;
- item_rect.y2 = item_rect.y1 + item_height;
-
- if (item_index == view->current_item)
- {
- rtgui_theme_draw_selected(dc, &item_rect);
- }
-
- drawing_rect.x1 = drawing_rect.y1 = 0;
- drawing_rect.x2 = image->w;
- drawing_rect.y2 = image->h;
- rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL);
- drawing_rect.y1 += 5; drawing_rect.y2 += 5;
- rtgui_image_blit(view->items[item_index].image, dc, &drawing_rect);
-
- item_rect.y1 = drawing_rect.y2 + LIST_MARGIN;
- item_rect.x1 += 3; item_rect.x2 -=3;
- rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), view->items[item_index].name,
- &drawing_rect);
- rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL);
- rtgui_dc_draw_text(dc, view->items[item_index].name, &drawing_rect);
-
- item_index ++;
- }
- else break;
- }
- }
-}
-
-static void rtgui_list_view_update_icon(struct rtgui_list_view* view, rt_int16_t old_item)
-{
- struct rtgui_rect rect, item_rect, drawing_rect;
- rt_ubase_t c, r; /* col and row index */
- rt_ubase_t item_width, item_height;
- rtgui_image_t* image;
- struct rtgui_dc* dc;
-
- if ((view->items_count == 0) ||
- (old_item == view->current_item))
- return;
-
- if (old_item/view->page_items != view->current_item/view->page_items)
- {
- /* it's not a same page, update all */
- rtgui_widget_update(RTGUI_WIDGET(view));
- return;
- }
-
- dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view));
- if (dc == RT_NULL) return;
-
- rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
-
- item_width = (rtgui_rect_width(rect) - 2 * LIST_MARGIN)/view->col_items;
- item_height = (rtgui_rect_height(rect) - 4)/view->row_items;
- image = view->items[0].image;
-
- /* update old item */
- r = (old_item % view->page_items)/ view->col_items;
- c = (old_item % view->page_items)% view->col_items;
- item_rect.y1 = rect.y1 + LIST_MARGIN + r * item_height;
- item_rect.x1 = rect.x1 + LIST_MARGIN + c * item_width;
- item_rect.x2 = item_rect.x1 + item_width;
- item_rect.y2 = item_rect.y1 + item_height;
- rtgui_dc_fill_rect(dc, &item_rect);
-
- /* draw image */
- drawing_rect.x1 = drawing_rect.y1 = 0;
- drawing_rect.x2 = image->w;
- drawing_rect.y2 = image->h;
- rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL);
- drawing_rect.y1 += 5; drawing_rect.y2 += 5;
- rtgui_image_blit(view->items[old_item].image, dc, &drawing_rect);
-
- /* draw text */
- item_rect.y1 = drawing_rect.y2 + LIST_MARGIN;
- item_rect.x1 += 3; item_rect.x2 -=3;
- rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), view->items[old_item].name,
- &drawing_rect);
- rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL);
- rtgui_dc_draw_text(dc, view->items[old_item].name, &drawing_rect);
-
- /* update new item as selected */
- r = (view->current_item % view->page_items) / view->col_items;
- c = (view->current_item % view->page_items) % view->col_items;
- item_rect.y1 = rect.y1 + LIST_MARGIN + r * item_height;
- item_rect.x1 = rect.x1 + LIST_MARGIN + c * item_width;
- item_rect.x2 = item_rect.x1 + item_width;
- item_rect.y2 = item_rect.y1 + item_height;
- rtgui_theme_draw_selected(dc, &item_rect);
-
- /* draw image */
- drawing_rect.x1 = 0;
- drawing_rect.y1 = 3;
- drawing_rect.x2 = image->w;
- drawing_rect.y2 = 3 + image->h;
-
- rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL);
- rtgui_image_blit(view->items[view->current_item].image, dc, &drawing_rect);
-
- /* draw text */
- item_rect.y1 = drawing_rect.y2 + LIST_MARGIN;
- item_rect.x1 += 3; item_rect.x2 -=3;
- rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)),
- view->items[view->current_item].name,
- &drawing_rect);
- rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL);
- rtgui_dc_draw_text(dc, view->items[view->current_item].name, &drawing_rect);
-
- rtgui_dc_end_drawing(dc);
-}
-
-static void rtgui_list_view_onlistdraw(struct rtgui_list_view* view, struct rtgui_dc *dc)
-{
- rt_ubase_t index, page_index;
- rtgui_rect_t rect, item_rect, image_rect;
- const struct rtgui_list_item* item;
-
- rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
-
- /* get item base rect */
- item_rect = rect;
- item_rect.y1 += 2;
- item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height());
-
- /* get current page */
- page_index = (view->current_item / view->page_items) * view->page_items;
- for (index = 0; index < view->page_items; index ++)
- {
- if (page_index + index >= view->items_count) break;
-
- item = &(view->items[page_index + index]);
-
- if (page_index + index == view->current_item)
- {
- rtgui_theme_draw_selected(dc, &item_rect);
- }
- item_rect.x1 += LIST_MARGIN;
-
- if (item->image != RT_NULL)
- {
- /* blit on center */
- image_rect.x1 = 0; image_rect.y1 = 0;
- image_rect.x2 = item->image->w;
- image_rect.y2 = item->image->h;
-
- rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
- rtgui_image_blit(item->image, dc, &image_rect);
- item_rect.x1 += item->image->w + 2;
- }
- /* draw text */
- rtgui_dc_draw_text(dc, item->name, &item_rect);
-
- if (item->image != RT_NULL)
- item_rect.x1 -= (item->image->w + 2);
- item_rect.x1 -= LIST_MARGIN;
-
- /* move to next item position */
- item_rect.y1 += (rtgui_theme_get_selected_height() + 2);
- item_rect.y2 += (rtgui_theme_get_selected_height() + 2);
- }
-}
-
-void rtgui_list_view_update_list(struct rtgui_list_view* view, rt_int16_t old_item)
-{
- struct rtgui_dc* dc;
- const struct rtgui_list_item* item;
- rtgui_rect_t rect, item_rect;
-
- if (old_item/view->page_items != view->current_item/view->page_items)
- {
- /* it's not a same page, update all */
- rtgui_widget_update(RTGUI_WIDGET(view));
- return;
- }
-
- dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view));
- if (dc == RT_NULL) return;
-
- rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
-
- /* get old item's rect and draw old item */
- item_rect.x1 = rect.x1; item_rect.x2 = rect.x2;
- item_rect.y1 = rect.y1 + 2;
- item_rect.y1 += (old_item % view->page_items) * (2 + rtgui_theme_get_selected_height());
- item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height());
- rtgui_dc_fill_rect(dc, &item_rect);
-
- item_rect.x1 += LIST_MARGIN;
-
- item = &(view->items[old_item]);
- if (item->image != RT_NULL)
- {
- struct rtgui_rect image_rect;
-
- /* blit on center */
- image_rect.x1 = 0; image_rect.y1 = 0;
- image_rect.x2 = item->image->w;
- image_rect.y2 = item->image->h;
-
- rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
- rtgui_image_blit(item->image, dc, &image_rect);
- item_rect.x1 += item->image->w + 2;
- }
- rtgui_dc_draw_text(dc, item->name, &item_rect);
-
- /* draw current item */
- item_rect = rect;
- /* get current item's rect */
- item_rect.y1 += 2;
- item_rect.y1 += (view->current_item % view->page_items) * (2 + rtgui_theme_get_selected_height());
- item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height());
-
- /* draw current item */
- rtgui_theme_draw_selected(dc, &item_rect);
-
- item_rect.x1 += LIST_MARGIN;
-
- item = &(view->items[view->current_item]);
- if (item->image != RT_NULL)
- {
- struct rtgui_rect image_rect;
-
- /* blit on center */
- image_rect.x1 = 0; image_rect.y1 = 0;
- image_rect.x2 = item->image->w;
- image_rect.y2 = item->image->h;
-
- rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
- rtgui_image_blit(item->image, dc, &image_rect);
- item_rect.x1 += (item->image->w + 2);
- }
- rtgui_dc_draw_text(dc, item->name, &item_rect);
-
- rtgui_dc_end_drawing(dc);
-}
-
-void rtgui_list_view_ondraw(struct rtgui_list_view* view)
-{
- struct rtgui_rect rect;
- struct rtgui_dc* dc;
-
- dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view));
- if (dc == RT_NULL) return;
-
- rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
- rtgui_dc_fill_rect(dc, &rect);
-
- switch (view->flag)
- {
- case RTGUI_LIST_VIEW_LIST:
- rtgui_list_view_onlistdraw(view, dc);
- break;
-
- case RTGUI_LIST_VIEW_ICON:
- rtgui_list_view_onicondraw(view, dc);
- break;
- }
-
- rtgui_dc_end_drawing(dc);
-}
-
-static rt_bool_t rtgui_list_view_onmouse(struct rtgui_list_view* view, struct rtgui_event_mouse* emouse)
-{
- rtgui_rect_t rect;
-
- /* calculate selected item */
-
- /* get physical extent information */
- rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
- rtgui_widget_rect_to_device(RTGUI_WIDGET(view), &rect);
-
- if (rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK)
- {
- rt_uint16_t index;
- rt_uint16_t old_item;
-
- /* get old item */
- old_item = view->current_item;
-
- switch (view->flag)
- {
- case RTGUI_LIST_VIEW_LIST:
- index = (emouse->y - rect.y1) / (2 + rtgui_theme_get_selected_height());
-
- if ((index < view->items_count) && (index < view->page_items))
- {
- /* set selected item */
- view->current_item = (view->current_item/view->page_items) * view->page_items + index;
- if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN)
- {
- /* down event */
- rtgui_list_view_update_list(view, old_item);
- }
- else
- {
- /* up event */
- if (view->items[view->current_item].action != RT_NULL)
- {
- view->items[view->current_item].action(RTGUI_WIDGET(view),
- view->items[view->current_item].parameter);
- }
- }
- }
- break;
-
- case RTGUI_LIST_VIEW_ICON:
- {
- rt_uint16_t x, y;
- rt_uint16_t item_height, item_width;
- rt_ubase_t current_page;
-
- item_width = (rtgui_rect_width(rect) - 2 * LIST_MARGIN)/view->col_items;
- item_height = (rtgui_rect_height(rect) - 4)/view->row_items;
- x = emouse->x - rect.x1;
- y = emouse->y - rect.y1;
-
- index = (y / item_height * view->col_items) + x / item_width;
- current_page = view->current_item / view->page_items;
-
- if ((index + (current_page * view->page_items) < view->items_count))
- {
- if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN)
- {
- view->current_item = index + (current_page * view->page_items);
-
- /* down event */
- rtgui_list_view_update_icon(view, old_item);
- }
- else
- {
- /* up event */
- if (view->items[view->current_item].action != RT_NULL)
- {
- view->items[view->current_item].action(RTGUI_WIDGET(view),
- view->items[view->current_item].parameter);
- }
- }
- }
- }
- break;
-
- case RTGUI_LIST_VIEW_REPORT:
- break;
- }
-
- return RT_TRUE;
- }
-
- return RT_FALSE;
-}
-
-rt_bool_t rtgui_list_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
-{
- struct rtgui_list_view* view = RT_NULL;
-
- view = RTGUI_LIST_VIEW(widget);
- switch (event->type)
- {
- case RTGUI_EVENT_PAINT:
- rtgui_list_view_ondraw(view);
- return RT_FALSE;
-
- case RTGUI_EVENT_RESIZE:
- {
- struct rtgui_event_resize* resize;
-
- resize = (struct rtgui_event_resize*)event;
-
- /* recalculate page items */
- view->page_items = resize->h / (2 + rtgui_theme_get_selected_height());
- }
- break;
-
- case RTGUI_EVENT_MOUSE_BUTTON:
- {
- struct rtgui_event_mouse* emouse;
-
- emouse = (struct rtgui_event_mouse*)event;
- return rtgui_list_view_onmouse(view, emouse);
- }
-
- case RTGUI_EVENT_KBD:
- {
- struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
- if (ekbd->type == RTGUI_KEYDOWN)
- {
- rt_uint16_t old_item;
-
- if (view->current_item == -1)
- {
- /* set a initial item */
- if ((view->items_count > 0) &&
- (ekbd->key == RTGUIK_UP || ekbd->key == RTGUIK_DOWN))
- {
- view->current_item = 0;
- if (view->flag == RTGUI_LIST_VIEW_LIST)
- rtgui_list_view_update_list(view, -1);
- else
- rtgui_list_view_update_icon(view, -1);
- break;
- }
- else return RT_FALSE;
- }
-
- old_item = view->current_item;
- switch (ekbd->key)
- {
- case RTGUIK_LEFT:
- if (view->flag == RTGUI_LIST_VIEW_LIST)
- {
- if (view->current_item - view->page_items >= 0)
- view->current_item -= view->page_items;
-
- rtgui_list_view_update_list(view, old_item);
- }
- else if (view->flag == RTGUI_LIST_VIEW_ICON)
- {
- if (view->current_item > 0)
- view->current_item --;
- rtgui_list_view_update_icon(view, old_item);
- }
- return RT_FALSE;
-
- case RTGUIK_UP:
- if (view->flag == RTGUI_LIST_VIEW_LIST)
- {
- if (view->current_item > 0)
- view->current_item --;
- rtgui_list_view_update_list(view, old_item);
- }
- else if (view->flag == RTGUI_LIST_VIEW_ICON)
- {
- if (view->current_item >= view->col_items)
- view->current_item -= view->col_items;
- else
- view->current_item = 0;
-
- rtgui_list_view_update_icon(view, old_item);
- }
- return RT_FALSE;
-
- case RTGUIK_RIGHT:
- if (view->flag == RTGUI_LIST_VIEW_LIST)
- {
- if (view->current_item + view->page_items < view->items_count - 1)
- view->current_item += view->page_items;
-
- rtgui_list_view_update_list(view, old_item);
- }
- else if (view->flag == RTGUI_LIST_VIEW_ICON)
- {
- if (view->current_item < view->items_count - 1)
- view->current_item ++;
-
- rtgui_list_view_update_icon(view, old_item);
- }
- return RT_FALSE;
-
- case RTGUIK_DOWN:
- if (view->flag == RTGUI_LIST_VIEW_LIST)
- {
- if (view->current_item < view->items_count - 1)
- view->current_item ++;
-
- rtgui_list_view_update_list(view, old_item);
- }
- else if (view->flag == RTGUI_LIST_VIEW_ICON)
- {
- if (view->current_item + view->col_items <= (view->items_count - 1))
- view->current_item += view->col_items;
- else
- view->current_item = view->items_count - 1;
-
- rtgui_list_view_update_icon(view, old_item);
- }
- return RT_FALSE;
-
- case RTGUIK_RETURN:
- if (view->items[view->current_item].action != RT_NULL)
- {
- view->items[view->current_item].action(RTGUI_WIDGET(view),
- view->items[view->current_item].parameter);
- }
- return RT_FALSE;
-
- default:
- break;
- }
- }
- }
- return RT_FALSE;
- }
-
- /* use view event handler */
- return rtgui_view_event_handler(widget, event);
-}
-
-static void rtgui_list_view_calc(struct rtgui_list_view* view)
-{
- rtgui_rect_t rect;
- rt_uint32_t image_width, image_height;
- rt_ubase_t text_width, text_height;
- rt_ubase_t item_width, item_height;
-
- if (view->items_count == 0) return;
-
- /* get image width and height */
- if (view->items[0].image != RT_NULL)
- {
- image_width = view->items[0].image->w;
- image_height = view->items[0].image->h;
- }
- else
- {
- image_width = 0;
- image_height = 0;
- }
-
- rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), "HHHHHH", &rect);
-
- text_height = rtgui_rect_height(rect);
- text_width = rtgui_rect_width(rect);
-
- rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
-
- item_width = (image_width + LIST_MARGIN);
- if (item_width < (text_width + LIST_MARGIN)) item_width = text_width + LIST_MARGIN;
- item_height = image_height + 8 + text_height + LIST_MARGIN;
- if (item_width > item_height) item_height = item_width;
- else item_width = item_height;
-
- view->row_items = (rtgui_rect_height(rect) - 2 * LIST_MARGIN) / item_height;
- view->col_items = (rtgui_rect_width(rect) - 2 * LIST_MARGIN) / item_width;
- view->page_items = view->row_items * view->col_items;
-}
-
-rtgui_list_view_t* rtgui_list_view_create(const struct rtgui_list_item* items, rt_uint16_t count,
- rtgui_rect_t *rect, rt_uint16_t flag)
-{
- struct rtgui_list_view* view = RT_NULL;
-
- view = (struct rtgui_list_view*) rtgui_widget_create(RTGUI_LIST_VIEW_TYPE);
- if (view != RT_NULL)
- {
- view->items = items;
- view->items_count = count;
-
- view->flag = flag;
- rtgui_widget_set_rect(RTGUI_WIDGET(view), rect);
-
- if (flag == RTGUI_LIST_VIEW_LIST)
- view->page_items = rtgui_rect_height(*rect) / (2 + rtgui_theme_get_selected_height());
- else if ((flag == RTGUI_LIST_VIEW_ICON) && (count > 0))
- {
- rtgui_list_view_calc(view);
- }
- }
-
- return view;
-}
-
-void rtgui_list_view_destroy(rtgui_list_view_t* view)
-{
- /* destroy view */
- rtgui_widget_destroy(RTGUI_WIDGET(view));
-}
+/* + * File : list_view.c + * This file is part of RTGUI in RT-Thread RTOS + * COPYRIGHT (C) 2010, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2010-01-06 Bernard first version + */ + +#include <rtgui/rtgui_theme.h> +#include <rtgui/widgets/list_view.h> + +#define LIST_MARGIN 5 + +static void _rtgui_list_view_constructor(struct rtgui_list_view *view) +{ + /* default rect */ + struct rtgui_rect rect = {0, 0, 200, 200}; + + /* set default widget rect and set event handler */ + rtgui_object_set_event_handler(RTGUI_OBJECT(view),rtgui_list_view_event_handler); + rtgui_widget_set_rect(RTGUI_WIDGET(view), &rect); + + RTGUI_WIDGET(view)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE; + + view->flag = RTGUI_LIST_VIEW_LIST; + view->current_item = 0; + view->items_count = 0; + view->page_items = 0; + + RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(view)) = white; + RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(view)) = RTGUI_ALIGN_CENTER_VERTICAL; +} + +DEFINE_CLASS_TYPE(listview, "listview", + RTGUI_CONTAINER_TYPE, + _rtgui_list_view_constructor, + RT_NULL, + sizeof(struct rtgui_list_view)); + +static void rtgui_list_view_onicondraw(struct rtgui_list_view* view, struct rtgui_dc *dc) +{ + struct rtgui_rect rect, item_rect, drawing_rect; + rt_ubase_t c, r, item_index; /* col and row index */ + rt_ubase_t item_width, item_height; + rtgui_image_t* image; + + if (view->items_count == 0) return; + + rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); + item_index = (view->current_item / view->page_items) * view->page_items; + + item_width = (rtgui_rect_width(rect) - 2 * LIST_MARGIN)/view->col_items; + item_height = (rtgui_rect_height(rect) - 4)/view->row_items; + image = view->items[0].image; + + for (r = 0; r < view->row_items; r ++) + { + for (c = 0; c < view->col_items; c ++) + { + if (item_index < view->items_count) + { + item_rect.y1 = rect.y1 + LIST_MARGIN + r * item_height; + item_rect.x1 = rect.x1 + LIST_MARGIN + c * item_width; + item_rect.x2 = item_rect.x1 + item_width; + item_rect.y2 = item_rect.y1 + item_height; + + if (item_index == view->current_item) + { + rtgui_theme_draw_selected(dc, &item_rect); + } + + drawing_rect.x1 = drawing_rect.y1 = 0; + drawing_rect.x2 = image->w; + drawing_rect.y2 = image->h; + rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL); + drawing_rect.y1 += 5; drawing_rect.y2 += 5; + rtgui_image_blit(view->items[item_index].image, dc, &drawing_rect); + + item_rect.y1 = drawing_rect.y2 + LIST_MARGIN; + item_rect.x1 += 3; item_rect.x2 -=3; + rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), view->items[item_index].name, + &drawing_rect); + rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL); + rtgui_dc_draw_text(dc, view->items[item_index].name, &drawing_rect); + + item_index ++; + } + else break; + } + } +} + +static void rtgui_list_view_update_icon(struct rtgui_list_view* view, rt_uint16_t old_item) +{ + struct rtgui_rect rect, item_rect, drawing_rect; + rt_ubase_t c, r; /* col and row index */ + rt_ubase_t item_width, item_height; + rtgui_image_t* image; + struct rtgui_dc* dc; + + if ((view->items_count == 0) || + (old_item == view->current_item)) + return; + + if (old_item/view->page_items != view->current_item/view->page_items) + { + /* it's not a same page, update all */ + rtgui_widget_update(RTGUI_WIDGET(view)); + return; + } + + dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view)); + if (dc == RT_NULL) return; + + rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); + + item_width = (rtgui_rect_width(rect) - 2 * LIST_MARGIN)/view->col_items; + item_height = (rtgui_rect_height(rect) - 4)/view->row_items; + image = view->items[0].image; + + /* update old item */ + r = (old_item % view->page_items)/ view->col_items; + c = (old_item % view->page_items)% view->col_items; + item_rect.y1 = rect.y1 + LIST_MARGIN + r * item_height; + item_rect.x1 = rect.x1 + LIST_MARGIN + c * item_width; + item_rect.x2 = item_rect.x1 + item_width; + item_rect.y2 = item_rect.y1 + item_height; + rtgui_dc_fill_rect(dc, &item_rect); + + /* draw image */ + drawing_rect.x1 = drawing_rect.y1 = 0; + drawing_rect.x2 = image->w; + drawing_rect.y2 = image->h; + rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL); + drawing_rect.y1 += 5; drawing_rect.y2 += 5; + rtgui_image_blit(view->items[old_item].image, dc, &drawing_rect); + + /* draw text */ + item_rect.y1 = drawing_rect.y2 + LIST_MARGIN; + item_rect.x1 += 3; item_rect.x2 -=3; + rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), view->items[old_item].name, + &drawing_rect); + rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL); + rtgui_dc_draw_text(dc, view->items[old_item].name, &drawing_rect); + + /* update new item as selected */ + r = (view->current_item % view->page_items) / view->col_items; + c = (view->current_item % view->page_items) % view->col_items; + item_rect.y1 = rect.y1 + LIST_MARGIN + r * item_height; + item_rect.x1 = rect.x1 + LIST_MARGIN + c * item_width; + item_rect.x2 = item_rect.x1 + item_width; + item_rect.y2 = item_rect.y1 + item_height; + rtgui_theme_draw_selected(dc, &item_rect); + + /* draw image */ + drawing_rect.x1 = 0; + drawing_rect.y1 = 3; + drawing_rect.x2 = image->w; + drawing_rect.y2 = 3 + image->h; + + rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL); + rtgui_image_blit(view->items[view->current_item].image, dc, &drawing_rect); + + /* draw text */ + item_rect.y1 = drawing_rect.y2 + LIST_MARGIN; + item_rect.x1 += 3; item_rect.x2 -=3; + rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), + view->items[view->current_item].name, + &drawing_rect); + rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL); + rtgui_dc_draw_text(dc, view->items[view->current_item].name, &drawing_rect); + + rtgui_dc_end_drawing(dc); +} + +static void rtgui_list_view_onlistdraw(struct rtgui_list_view* view, struct rtgui_dc *dc) +{ + rt_ubase_t index, page_index; + rtgui_rect_t rect, item_rect, image_rect; + const struct rtgui_list_item* item; + + rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); + + /* get item base rect */ + item_rect = rect; + item_rect.y1 += 2; + item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height()); + + /* get current page */ + page_index = (view->current_item / view->page_items) * view->page_items; + for (index = 0; index < view->page_items; index ++) + { + if (page_index + index >= view->items_count) break; + + item = &(view->items[page_index + index]); + + if (page_index + index == view->current_item) + { + rtgui_theme_draw_selected(dc, &item_rect); + } + item_rect.x1 += LIST_MARGIN; + + if (item->image != RT_NULL) + { + /* blit on center */ + image_rect.x1 = 0; image_rect.y1 = 0; + image_rect.x2 = item->image->w; + image_rect.y2 = item->image->h; + + rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL); + rtgui_image_blit(item->image, dc, &image_rect); + item_rect.x1 += item->image->w + 2; + } + /* draw text */ + rtgui_dc_draw_text(dc, item->name, &item_rect); + + if (item->image != RT_NULL) + item_rect.x1 -= (item->image->w + 2); + item_rect.x1 -= LIST_MARGIN; + + /* move to next item position */ + item_rect.y1 += (rtgui_theme_get_selected_height() + 2); + item_rect.y2 += (rtgui_theme_get_selected_height() + 2); + } +} + +void rtgui_list_view_update_list(struct rtgui_list_view* view, rt_uint16_t old_item) +{ + struct rtgui_dc* dc; + const struct rtgui_list_item* item; + rtgui_rect_t rect, item_rect; + + if (old_item/view->page_items != view->current_item/view->page_items) + { + /* it's not a same page, update all */ + rtgui_widget_update(RTGUI_WIDGET(view)); + return; + } + + dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view)); + if (dc == RT_NULL) return; + + rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); + + /* get old item's rect and draw old item */ + item_rect.x1 = rect.x1; item_rect.x2 = rect.x2; + item_rect.y1 = rect.y1 + 2; + item_rect.y1 += (old_item % view->page_items) * (2 + rtgui_theme_get_selected_height()); + item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height()); + rtgui_dc_fill_rect(dc, &item_rect); + + item_rect.x1 += LIST_MARGIN; + + item = &(view->items[old_item]); + if (item->image != RT_NULL) + { + struct rtgui_rect image_rect; + + /* blit on center */ + image_rect.x1 = 0; image_rect.y1 = 0; + image_rect.x2 = item->image->w; + image_rect.y2 = item->image->h; + + rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL); + rtgui_image_blit(item->image, dc, &image_rect); + item_rect.x1 += item->image->w + 2; + } + rtgui_dc_draw_text(dc, item->name, &item_rect); + + /* draw current item */ + item_rect = rect; + /* get current item's rect */ + item_rect.y1 += 2; + item_rect.y1 += (view->current_item % view->page_items) * (2 + rtgui_theme_get_selected_height()); + item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height()); + + /* draw current item */ + rtgui_theme_draw_selected(dc, &item_rect); + + item_rect.x1 += LIST_MARGIN; + + item = &(view->items[view->current_item]); + if (item->image != RT_NULL) + { + struct rtgui_rect image_rect; + + /* blit on center */ + image_rect.x1 = 0; image_rect.y1 = 0; + image_rect.x2 = item->image->w; + image_rect.y2 = item->image->h; + + rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL); + rtgui_image_blit(item->image, dc, &image_rect); + item_rect.x1 += (item->image->w + 2); + } + rtgui_dc_draw_text(dc, item->name, &item_rect); + + rtgui_dc_end_drawing(dc); +} + +void rtgui_list_view_ondraw(struct rtgui_list_view* view) +{ + struct rtgui_rect rect; + struct rtgui_dc* dc; + + dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view)); + if (dc == RT_NULL) return; + + rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); + rtgui_dc_fill_rect(dc, &rect); + + switch (view->flag) + { + case RTGUI_LIST_VIEW_LIST: + rtgui_list_view_onlistdraw(view, dc); + break; + + case RTGUI_LIST_VIEW_ICON: + rtgui_list_view_onicondraw(view, dc); + break; + } + + rtgui_dc_end_drawing(dc); +} + +static rt_bool_t rtgui_list_view_onmouse(struct rtgui_list_view* view, struct rtgui_event_mouse* emouse) +{ + rtgui_rect_t rect; + + /* calculate selected item */ + + /* get physical extent information */ + rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); + rtgui_widget_rect_to_device(RTGUI_WIDGET(view), &rect); + + if (rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK) + { + rt_uint16_t index; + rt_uint16_t old_item; + + /* get old item */ + old_item = view->current_item; + + switch (view->flag) + { + case RTGUI_LIST_VIEW_LIST: + index = (emouse->y - rect.y1) / (2 + rtgui_theme_get_selected_height()); + + if ((index < view->items_count) && (index < view->page_items)) + { + /* set selected item */ + view->current_item = (view->current_item/view->page_items) * view->page_items + index; + if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN) + { + /* down event */ + rtgui_list_view_update_list(view, old_item); + } + else + { + /* up event */ + if (view->items[view->current_item].action != RT_NULL) + { + view->items[view->current_item].action(RTGUI_WIDGET(view), + view->items[view->current_item].parameter); + } + } + } + break; + + case RTGUI_LIST_VIEW_ICON: + { + rt_uint16_t x, y; + rt_uint16_t item_height, item_width; + rt_ubase_t current_page; + + item_width = (rtgui_rect_width(rect) - 2 * LIST_MARGIN)/view->col_items; + item_height = (rtgui_rect_height(rect) - 4)/view->row_items; + x = emouse->x - rect.x1; + y = emouse->y - rect.y1; + + index = (y / item_height * view->col_items) + x / item_width; + current_page = view->current_item / view->page_items; + + if ((index + (current_page * view->page_items) < view->items_count)) + { + if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN) + { + view->current_item = index + (current_page * view->page_items); + + /* down event */ + rtgui_list_view_update_icon(view, old_item); + } + else + { + /* up event */ + if (view->items[view->current_item].action != RT_NULL) + { + view->items[view->current_item].action(RTGUI_WIDGET(view), + view->items[view->current_item].parameter); + } + } + } + } + break; + + case RTGUI_LIST_VIEW_REPORT: + break; + } + + return RT_TRUE; + } + + return RT_FALSE; +} + +rt_bool_t rtgui_list_view_event_handler(struct rtgui_object* widget, struct rtgui_event* event) +{ + struct rtgui_list_view* view = RT_NULL; + + view = RTGUI_LIST_VIEW(widget); + switch (event->type) + { + case RTGUI_EVENT_PAINT: + rtgui_list_view_ondraw(view); + return RT_FALSE; + + case RTGUI_EVENT_RESIZE: + { + struct rtgui_event_resize* resize; + + resize = (struct rtgui_event_resize*)event; + + /* recalculate page items */ + view->page_items = resize->h / (2 + rtgui_theme_get_selected_height()); + } + break; + + case RTGUI_EVENT_MOUSE_BUTTON: + { + struct rtgui_event_mouse* emouse; + + emouse = (struct rtgui_event_mouse*)event; + return rtgui_list_view_onmouse(view, emouse); + } + + case RTGUI_EVENT_KBD: + { + struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event; + if (ekbd->type == RTGUI_KEYDOWN) + { + rt_uint16_t old_item; + + if (view->current_item == -1) + { + /* set a initial item */ + if ((view->items_count > 0) && + (ekbd->key == RTGUIK_UP || ekbd->key == RTGUIK_DOWN)) + { + view->current_item = 0; + if (view->flag == RTGUI_LIST_VIEW_LIST) + rtgui_list_view_update_list(view, -1); + else + rtgui_list_view_update_icon(view, -1); + break; + } + else return RT_FALSE; + } + + old_item = view->current_item; + switch (ekbd->key) + { + case RTGUIK_LEFT: + if (view->flag == RTGUI_LIST_VIEW_LIST) + { + if (view->current_item - view->page_items >= 0) + view->current_item -= view->page_items; + + rtgui_list_view_update_list(view, old_item); + } + else if (view->flag == RTGUI_LIST_VIEW_ICON) + { + if (view->current_item > 0) + view->current_item --; + rtgui_list_view_update_icon(view, old_item); + } + return RT_FALSE; + + case RTGUIK_UP: + if (view->flag == RTGUI_LIST_VIEW_LIST) + { + if (view->current_item > 0) + view->current_item --; + rtgui_list_view_update_list(view, old_item); + } + else if (view->flag == RTGUI_LIST_VIEW_ICON) + { + if (view->current_item >= view->col_items) + view->current_item -= view->col_items; + else + view->current_item = 0; + + rtgui_list_view_update_icon(view, old_item); + } + return RT_FALSE; + + case RTGUIK_RIGHT: + if (view->flag == RTGUI_LIST_VIEW_LIST) + { + if (view->current_item + view->page_items < view->items_count - 1) + view->current_item += view->page_items; + + rtgui_list_view_update_list(view, old_item); + } + else if (view->flag == RTGUI_LIST_VIEW_ICON) + { + if (view->current_item < view->items_count - 1) + view->current_item ++; + + rtgui_list_view_update_icon(view, old_item); + } + return RT_FALSE; + + case RTGUIK_DOWN: + if (view->flag == RTGUI_LIST_VIEW_LIST) + { + if (view->current_item < view->items_count - 1) + view->current_item ++; + + rtgui_list_view_update_list(view, old_item); + } + else if (view->flag == RTGUI_LIST_VIEW_ICON) + { + if (view->current_item + view->col_items <= (view->items_count - 1)) + view->current_item += view->col_items; + else + view->current_item = view->items_count - 1; + + rtgui_list_view_update_icon(view, old_item); + } + return RT_FALSE; + + case RTGUIK_RETURN: + if (view->items[view->current_item].action != RT_NULL) + { + view->items[view->current_item].action(RTGUI_WIDGET(view), + view->items[view->current_item].parameter); + } + return RT_FALSE; + + default: + break; + } + } + } + return RT_FALSE; + } + + /* use view event handler */ + return rtgui_container_event_handler(widget, event); +} + +static void rtgui_list_view_calc(struct rtgui_list_view* view) +{ + rtgui_rect_t rect; + rt_uint32_t image_width, image_height; + rt_ubase_t text_width, text_height; + rt_ubase_t item_width, item_height; + + if (view->items_count == 0) return; + + /* get image width and height */ + if (view->items[0].image != RT_NULL) + { + image_width = view->items[0].image->w; + image_height = view->items[0].image->h; + } + else + { + image_width = 0; + image_height = 0; + } + + rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), "HHHHHH", &rect); + + text_height = rtgui_rect_height(rect); + text_width = rtgui_rect_width(rect); + + rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect); + + item_width = (image_width + LIST_MARGIN); + if (item_width < (text_width + LIST_MARGIN)) item_width = text_width + LIST_MARGIN; + item_height = image_height + 8 + text_height + LIST_MARGIN; + if (item_width > item_height) item_height = item_width; + else item_width = item_height; + + view->row_items = (rtgui_rect_height(rect) - 2 * LIST_MARGIN) / item_height; + view->col_items = (rtgui_rect_width(rect) - 2 * LIST_MARGIN) / item_width; + view->page_items = view->row_items * view->col_items; +} + +rtgui_list_view_t* rtgui_list_view_create(const struct rtgui_list_item* items, rt_uint16_t count, + rtgui_rect_t *rect, rt_uint16_t flag) +{ + struct rtgui_list_view* view = RT_NULL; + + view = (struct rtgui_list_view*) rtgui_widget_create(RTGUI_LIST_VIEW_TYPE); + if (view != RT_NULL) + { + view->items = items; + view->items_count = count; + + view->flag = flag; + rtgui_widget_set_rect(RTGUI_WIDGET(view), rect); + + if (flag == RTGUI_LIST_VIEW_LIST) + view->page_items = rtgui_rect_height(*rect) / (2 + rtgui_theme_get_selected_height()); + else if ((flag == RTGUI_LIST_VIEW_ICON) && (count > 0)) + { + rtgui_list_view_calc(view); + } + } + + return view; +} + +void rtgui_list_view_destroy(rtgui_list_view_t* view) +{ + /* destroy view */ + rtgui_widget_destroy(RTGUI_WIDGET(view)); +} diff --git a/components/rtgui/widgets/listbox.c b/components/rtgui/widgets/listbox.c index 0ce5aebe32..859cbc1304 100644 --- a/components/rtgui/widgets/listbox.c +++ b/components/rtgui/widgets/listbox.c @@ -1,387 +1,388 @@ -/*
- * File : listbox.c
- * This file is part of RTGUI in RT-Thread RTOS
- * COPYRIGHT (C) 2010, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2010-01-06 Bernard first version
- */
-
-#include <rtgui/rtgui_theme.h>
-#include <rtgui/widgets/listbox.h>
-
-#define LIST_MARGIN 5
-
-static void _rtgui_listbox_constructor(struct rtgui_listbox *box)
-{
- /* set default widget rect and set event handler */
- rtgui_widget_set_event_handler(RTGUI_WIDGET(box),rtgui_listbox_event_handler);
-
- RTGUI_WIDGET(box)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
-
- box->current_item = -1;
- box->items_count = 0;
- box->page_items = 1;
- box->on_item = 0;
-
- RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(box)) = white;
- RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(box)) = RTGUI_ALIGN_CENTER_VERTICAL;
-}
-
-DEFINE_CLASS_TYPE(listbox, "listbox",
- RTGUI_WIDGET_TYPE,
- _rtgui_listbox_constructor,
- RT_NULL,
- sizeof(struct rtgui_listbox));
-
-void rtgui_listbox_ondraw(struct rtgui_listbox* box)
-{
- struct rtgui_dc* dc;
- rt_uint16_t page_index, index;
- const struct rtgui_listbox_item* item;
- struct rtgui_rect rect, item_rect, image_rect;
-
- dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(box));
- if (dc == RT_NULL) return;
-
- rtgui_widget_get_rect(RTGUI_WIDGET(box), &rect);
- rtgui_dc_fill_rect(dc, &rect);
-
- rect.x2 -= 1; rect.y2 -= 1;
- /* draw focused border */
- if (RTGUI_WIDGET_IS_FOCUSED(RTGUI_WIDGET(box)))
- rtgui_dc_draw_focus_rect(dc, &rect);
-
- /* get item base rect */
- item_rect = rect;
- item_rect.x1 += 1; item_rect.x2 -= 1;
- item_rect.y1 += 2;
- item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height());
-
- /* get current page */
- if (box->current_item == -1)
- page_index = 0;
- else
- page_index = (box->current_item / box->page_items) * box->page_items;
-
- for (index = 0; index < box->page_items; index ++)
- {
- if (page_index + index >= box->items_count) break;
-
- item = &(box->items[page_index + index]);
-
- if (page_index + index == box->current_item)
- {
- rtgui_theme_draw_selected(dc, &item_rect);
- }
- item_rect.x1 += LIST_MARGIN;
-
- if (item->image != RT_NULL)
- {
- rtgui_image_get_rect(item->image, &image_rect);
- rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
-
- rtgui_image_blit(item->image, dc, &image_rect);
- item_rect.x1 += item->image->w + 2;
- }
- /* draw text */
- rtgui_dc_draw_text(dc, item->name, &item_rect);
-
- if (item->image != RT_NULL)
- item_rect.x1 -= (item->image->w + 2);
- item_rect.x1 -= LIST_MARGIN;
-
- /* move to next item position */
- item_rect.y1 += (rtgui_theme_get_selected_height() + 2);
- item_rect.y2 += (rtgui_theme_get_selected_height() + 2);
- }
- rtgui_dc_end_drawing(dc);
-}
-
-static void rtgui_listbox_update_current(struct rtgui_listbox* box, rt_int16_t old_item)
-{
- struct rtgui_dc* dc;
- const struct rtgui_listbox_item* item;
- rtgui_rect_t rect, item_rect, image_rect;
-
- if ((old_item == -1) || (old_item/box->page_items != box->current_item/box->page_items))
- {
- /* it's not a same page, update all */
- rtgui_widget_update(RTGUI_WIDGET(box));
- return;
- }
-
- dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(box));
- if (dc == RT_NULL) return;
-
- rtgui_widget_get_rect(RTGUI_WIDGET(box), &rect);
- rect.x2 -= 1; rect.y2 -= 1;
-
- item_rect = rect;
- /* get old item's rect */
- item_rect.x1 += 1; item_rect.x2 -= 1;
- item_rect.y1 += 2;
- item_rect.y1 += (old_item % box->page_items) * (2 + rtgui_theme_get_selected_height());
- item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height());
-
- /* draw old item */
- rtgui_dc_fill_rect(dc, &item_rect);
-
- item_rect.x1 += LIST_MARGIN;
-
- item = &(box->items[old_item]);
- if (item->image != RT_NULL)
- {
- rtgui_image_get_rect(item->image, &image_rect);
- rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
-
- rtgui_image_blit(item->image, dc, &image_rect);
- item_rect.x1 += item->image->w + 2;
- }
- rtgui_dc_draw_text(dc, item->name, &item_rect);
-
- /* draw current item */
- item_rect = rect;
- /* get current item's rect */
- item_rect.x1 += 1; item_rect.x2 -= 1;
- item_rect.y1 += 2;
- item_rect.y1 += (box->current_item % box->page_items) * (2 + rtgui_theme_get_selected_height());
- item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height());
-
- /* draw current item */
- rtgui_theme_draw_selected(dc, &item_rect);
-
- item_rect.x1 += LIST_MARGIN;
-
- item = &(box->items[box->current_item]);
- if (item->image != RT_NULL)
- {
- rtgui_image_get_rect(item->image, &image_rect);
- rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
-
- rtgui_image_blit(item->image, dc, &image_rect);
- item_rect.x1 += (item->image->w + 2);
- }
- rtgui_dc_draw_text(dc, item->name, &item_rect);
-
- rtgui_dc_end_drawing(dc);
-}
-
-rt_bool_t rtgui_listbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
-{
- struct rtgui_listbox* box = RT_NULL;
-
- box = RTGUI_LISTBOX(widget);
- switch (event->type)
- {
- case RTGUI_EVENT_PAINT:
- rtgui_listbox_ondraw(box);
- return RT_FALSE;
-
- case RTGUI_EVENT_RESIZE:
- {
- struct rtgui_event_resize* resize;
-
- resize = (struct rtgui_event_resize*)event;
-
- /* recalculate page items */
- box->page_items = resize->h / (2 + rtgui_theme_get_selected_height());
- }
- break;
-
- case RTGUI_EVENT_MOUSE_BUTTON:
- {
- rtgui_rect_t rect;
- struct rtgui_event_mouse* emouse;
-
- emouse = (struct rtgui_event_mouse*)event;
-
- /* calculate selected item */
-
- /* get physical extent information */
- rtgui_widget_get_rect(widget, &rect);
- rtgui_widget_rect_to_device(widget, &rect);
-
- if ((rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK) && (box->items_count > 0))
- {
- rt_uint16_t index;
- index = (emouse->y - rect.y1) / (2 + rtgui_theme_get_selected_height());
-
- /* set focus */
- rtgui_widget_focus(widget);
- {
- struct rtgui_rect rect;
- struct rtgui_dc* dc;
-
- dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(box));
- if (dc != RT_NULL)
- {
- /* get widget rect */
- rtgui_widget_get_rect(RTGUI_WIDGET(box), &rect);
- /* update focus border */
- rect.x2 -= 1; rect.y2 -= 1;
- /* draw focused border */
- if (RTGUI_WIDGET_IS_FOCUSED(RTGUI_WIDGET(box)))
- rtgui_dc_draw_focus_rect(dc, &rect);
- rtgui_dc_end_drawing(dc);
- }
- }
-
- if ((index < box->items_count) && (index < box->page_items))
- {
- rt_uint16_t old_item;
-
- old_item = box->current_item;
-
- /* set selected item */
- box->current_item = (box->current_item/box->page_items) * box->page_items + index;
- if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN)
- {
- /* down event */
- rtgui_listbox_update_current(box, old_item);
- }
- else
- {
- /* up event */
- if (box->on_item != RT_NULL)
- {
- box->on_item(RTGUI_WIDGET(box), RT_NULL);
- }
- }
- }
- }
-
- return RT_TRUE;
- }
-
- case RTGUI_EVENT_KBD:
- {
- struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
- if ((ekbd->type == RTGUI_KEYDOWN) && (box->items_count > 0))
- {
- rt_int16_t old_item;
-
- if (box->current_item == -1)
- {
- /* set a initial item */
- if ((box->items_count > 0) &&
- (ekbd->key == RTGUIK_UP || ekbd->key == RTGUIK_DOWN))
- {
- box->current_item = 0;
- rtgui_listbox_update_current(box, -1);
- break;
- }
- else return RT_FALSE;
- }
- old_item = box->current_item;
-
- switch (ekbd->key)
- {
- case RTGUIK_LEFT:
- if (box->current_item - box->page_items >= 0)
- box->current_item -= box->page_items;
- rtgui_listbox_update_current(box, old_item);
- return RT_FALSE;
-
- case RTGUIK_UP:
- if (box->current_item > 0)
- box->current_item --;
- rtgui_listbox_update_current(box, old_item);
- return RT_FALSE;
-
- case RTGUIK_RIGHT:
- if (box->current_item + box->page_items < box->items_count - 1)
- box->current_item += box->page_items;
- rtgui_listbox_update_current(box, old_item);
- return RT_FALSE;
-
- case RTGUIK_DOWN:
- if (box->current_item < box->items_count - 1)
- box->current_item ++;
- rtgui_listbox_update_current(box, old_item);
- return RT_FALSE;
-
- case RTGUIK_RETURN:
- if (box->on_item != RT_NULL)
- {
- box->on_item(RTGUI_WIDGET(box), RT_NULL);
- }
- return RT_FALSE;
-
- default:
- break;
- }
- }
- }
- return RT_FALSE;
- }
-
- /* use box event handler */
- return rtgui_widget_event_handler(widget, event);
-}
-
-rtgui_listbox_t* rtgui_listbox_create(const struct rtgui_listbox_item* items, rt_uint16_t count, rtgui_rect_t *rect)
-{
- struct rtgui_listbox* box = RT_NULL;
-
- box = (struct rtgui_listbox*) rtgui_widget_create(RTGUI_LISTBOX_TYPE);
- if (box != RT_NULL)
- {
- box->items = items;
- box->items_count = count;
-
- box->page_items = rtgui_rect_height(*rect) / (2 + rtgui_theme_get_selected_height());
- if (box->page_items == 0) box->page_items = 1;
- rtgui_widget_set_rect(RTGUI_WIDGET(box), rect);
- }
-
- return box;
-}
-
-void rtgui_listbox_destroy(rtgui_listbox_t* box)
-{
- /* destroy box */
- rtgui_widget_destroy(RTGUI_WIDGET(box));
-}
-
-void rtgui_listbox_set_onitem(rtgui_listbox_t* box, rtgui_onitem_func_t func)
-{
- RT_ASSERT(box != RT_NULL);
-
- box->on_item = func;
-}
-
-void rtgui_listbox_set_items(rtgui_listbox_t* box, struct rtgui_listbox_item* items, rt_uint16_t count)
-{
- rtgui_rect_t rect;
-
- box->items = items;
- box->items_count = count;
- box->current_item = -1;
-
- rtgui_widget_get_rect(RTGUI_WIDGET(box), &rect);
- box->page_items = rtgui_rect_height(rect) / (2 + rtgui_theme_get_selected_height());
-
- rtgui_widget_update(RTGUI_WIDGET(box));
-}
-
-void rtgui_listbox_set_current_item(rtgui_listbox_t* box, int index)
-{
- RT_ASSERT(box != RT_NULL);
-
- if (index != box->current_item)
- {
- int old_item;
-
- old_item = box->current_item;
- box->current_item = index;
-
- rtgui_listbox_update_current(box, old_item);
- }
-}
-
+/* + * File : listbox.c + * This file is part of RTGUI in RT-Thread RTOS + * COPYRIGHT (C) 2010, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2010-01-06 Bernard first version + */ + +#include <rtgui/rtgui_theme.h> +#include <rtgui/widgets/listbox.h> + +#define LIST_MARGIN 5 + +static void _rtgui_listbox_constructor(struct rtgui_listbox *box) +{ + /* set default widget rect and set event handler */ + rtgui_object_set_event_handler(RTGUI_OBJECT(box), rtgui_listbox_event_handler); + + RTGUI_WIDGET(box)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE; + + box->current_item = -1; + box->items_count = 0; + box->page_items = 1; + box->on_item = 0; + + RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(box)) = white; + RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(box)) = RTGUI_ALIGN_CENTER_VERTICAL; +} + +DEFINE_CLASS_TYPE(listbox, "listbox", + RTGUI_WIDGET_TYPE, + _rtgui_listbox_constructor, + RT_NULL, + sizeof(struct rtgui_listbox)); + +void rtgui_listbox_ondraw(struct rtgui_listbox* box) +{ + struct rtgui_dc* dc; + rt_uint16_t page_index, index; + const struct rtgui_listbox_item* item; + struct rtgui_rect rect, item_rect, image_rect; + + dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(box)); + if (dc == RT_NULL) return; + + rtgui_widget_get_rect(RTGUI_WIDGET(box), &rect); + rtgui_dc_fill_rect(dc, &rect); + + rect.x2 -= 1; rect.y2 -= 1; + /* draw focused border */ + if (RTGUI_WIDGET_IS_FOCUSED(RTGUI_WIDGET(box))) + rtgui_dc_draw_focus_rect(dc, &rect); + + /* get item base rect */ + item_rect = rect; + item_rect.x1 += 1; item_rect.x2 -= 1; + item_rect.y1 += 2; + item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height()); + + /* get current page */ + if (box->current_item == -1) + page_index = 0; + else + page_index = (box->current_item / box->page_items) * box->page_items; + + for (index = 0; index < box->page_items; index ++) + { + if (page_index + index >= box->items_count) break; + + item = &(box->items[page_index + index]); + + if (page_index + index == box->current_item) + { + rtgui_theme_draw_selected(dc, &item_rect); + } + item_rect.x1 += LIST_MARGIN; + + if (item->image != RT_NULL) + { + rtgui_image_get_rect(item->image, &image_rect); + rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL); + + rtgui_image_blit(item->image, dc, &image_rect); + item_rect.x1 += item->image->w + 2; + } + /* draw text */ + rtgui_dc_draw_text(dc, item->name, &item_rect); + + if (item->image != RT_NULL) + item_rect.x1 -= (item->image->w + 2); + item_rect.x1 -= LIST_MARGIN; + + /* move to next item position */ + item_rect.y1 += (rtgui_theme_get_selected_height() + 2); + item_rect.y2 += (rtgui_theme_get_selected_height() + 2); + } + rtgui_dc_end_drawing(dc); +} + +static void rtgui_listbox_update_current(struct rtgui_listbox* box, rt_int16_t old_item) +{ + struct rtgui_dc* dc; + const struct rtgui_listbox_item* item; + rtgui_rect_t rect, item_rect, image_rect; + + if ((old_item == -1) || (old_item/box->page_items != box->current_item/box->page_items)) + { + /* it's not a same page, update all */ + rtgui_widget_update(RTGUI_WIDGET(box)); + return; + } + + dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(box)); + if (dc == RT_NULL) return; + + rtgui_widget_get_rect(RTGUI_WIDGET(box), &rect); + rect.x2 -= 1; rect.y2 -= 1; + + item_rect = rect; + /* get old item's rect */ + item_rect.x1 += 1; item_rect.x2 -= 1; + item_rect.y1 += 2; + item_rect.y1 += (old_item % box->page_items) * (2 + rtgui_theme_get_selected_height()); + item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height()); + + /* draw old item */ + rtgui_dc_fill_rect(dc, &item_rect); + + item_rect.x1 += LIST_MARGIN; + + item = &(box->items[old_item]); + if (item->image != RT_NULL) + { + rtgui_image_get_rect(item->image, &image_rect); + rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL); + + rtgui_image_blit(item->image, dc, &image_rect); + item_rect.x1 += item->image->w + 2; + } + rtgui_dc_draw_text(dc, item->name, &item_rect); + + /* draw current item */ + item_rect = rect; + /* get current item's rect */ + item_rect.x1 += 1; item_rect.x2 -= 1; + item_rect.y1 += 2; + item_rect.y1 += (box->current_item % box->page_items) * (2 + rtgui_theme_get_selected_height()); + item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height()); + + /* draw current item */ + rtgui_theme_draw_selected(dc, &item_rect); + + item_rect.x1 += LIST_MARGIN; + + item = &(box->items[box->current_item]); + if (item->image != RT_NULL) + { + rtgui_image_get_rect(item->image, &image_rect); + rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL); + + rtgui_image_blit(item->image, dc, &image_rect); + item_rect.x1 += (item->image->w + 2); + } + rtgui_dc_draw_text(dc, item->name, &item_rect); + + rtgui_dc_end_drawing(dc); +} + +rt_bool_t rtgui_listbox_event_handler(struct rtgui_object* object, struct rtgui_event* event) +{ + struct rtgui_listbox* box; + RTGUI_WIDGET_EVENT_HANDLER_PREPARE + + box = RTGUI_LISTBOX(object); + switch (event->type) + { + case RTGUI_EVENT_PAINT: + rtgui_listbox_ondraw(box); + return RT_FALSE; + + case RTGUI_EVENT_RESIZE: + { + struct rtgui_event_resize* resize; + + resize = (struct rtgui_event_resize*)event; + + /* recalculate page items */ + box->page_items = resize->h / (2 + rtgui_theme_get_selected_height()); + } + break; + + case RTGUI_EVENT_MOUSE_BUTTON: + { + rtgui_rect_t rect; + struct rtgui_event_mouse* emouse; + + emouse = (struct rtgui_event_mouse*)event; + + /* calculate selected item */ + + /* get physical extent information */ + rtgui_widget_get_rect(widget, &rect); + rtgui_widget_rect_to_device(widget, &rect); + + if ((rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK) && (box->items_count > 0)) + { + rt_uint16_t index; + index = (emouse->y - rect.y1) / (2 + rtgui_theme_get_selected_height()); + + /* set focus */ + rtgui_widget_focus(widget); + { + struct rtgui_rect rect; + struct rtgui_dc* dc; + + dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(box)); + if (dc != RT_NULL) + { + /* get widget rect */ + rtgui_widget_get_rect(RTGUI_WIDGET(box), &rect); + /* update focus border */ + rect.x2 -= 1; rect.y2 -= 1; + /* draw focused border */ + if (RTGUI_WIDGET_IS_FOCUSED(RTGUI_WIDGET(box))) + rtgui_dc_draw_focus_rect(dc, &rect); + rtgui_dc_end_drawing(dc); + } + } + + if ((index < box->items_count) && (index < box->page_items)) + { + rt_uint16_t old_item; + + old_item = box->current_item; + + /* set selected item */ + box->current_item = (box->current_item/box->page_items) * box->page_items + index; + if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN) + { + /* down event */ + rtgui_listbox_update_current(box, old_item); + } + else + { + /* up event */ + if (box->on_item != RT_NULL) + { + box->on_item(RTGUI_OBJECT(box), RT_NULL); + } + } + } + } + + return RT_TRUE; + } + + case RTGUI_EVENT_KBD: + { + struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event; + if ((ekbd->type == RTGUI_KEYDOWN) && (box->items_count > 0)) + { + rt_int16_t old_item; + + if (box->current_item == -1) + { + /* set a initial item */ + if ((box->items_count > 0) && + (ekbd->key == RTGUIK_UP || ekbd->key == RTGUIK_DOWN)) + { + box->current_item = 0; + rtgui_listbox_update_current(box, -1); + break; + } + else return RT_FALSE; + } + old_item = box->current_item; + + switch (ekbd->key) + { + case RTGUIK_LEFT: + if (box->current_item - box->page_items >= 0) + box->current_item -= box->page_items; + rtgui_listbox_update_current(box, old_item); + return RT_FALSE; + + case RTGUIK_UP: + if (box->current_item > 0) + box->current_item --; + rtgui_listbox_update_current(box, old_item); + return RT_FALSE; + + case RTGUIK_RIGHT: + if (box->current_item + box->page_items < box->items_count - 1) + box->current_item += box->page_items; + rtgui_listbox_update_current(box, old_item); + return RT_FALSE; + + case RTGUIK_DOWN: + if (box->current_item < box->items_count - 1) + box->current_item ++; + rtgui_listbox_update_current(box, old_item); + return RT_FALSE; + + case RTGUIK_RETURN: + if (box->on_item != RT_NULL) + { + box->on_item(RTGUI_OBJECT(box), RT_NULL); + } + return RT_FALSE; + + default: + break; + } + } + } + return RT_FALSE; + } + + /* use box event handler */ + return rtgui_widget_event_handler(RTGUI_OBJECT(widget), event); +} + +rtgui_listbox_t* rtgui_listbox_create(const struct rtgui_listbox_item* items, rt_uint16_t count, rtgui_rect_t *rect) +{ + struct rtgui_listbox* box = RT_NULL; + + box = (struct rtgui_listbox*) rtgui_widget_create(RTGUI_LISTBOX_TYPE); + if (box != RT_NULL) + { + box->items = items; + box->items_count = count; + + box->page_items = rtgui_rect_height(*rect) / (2 + rtgui_theme_get_selected_height()); + if (box->page_items == 0) box->page_items = 1; + rtgui_widget_set_rect(RTGUI_WIDGET(box), rect); + } + + return box; +} + +void rtgui_listbox_destroy(rtgui_listbox_t* box) +{ + /* destroy box */ + rtgui_widget_destroy(RTGUI_WIDGET(box)); +} + +void rtgui_listbox_set_onitem(rtgui_listbox_t* box, rtgui_event_handler_ptr func) +{ + RT_ASSERT(box != RT_NULL); + + box->on_item = func; +} + +void rtgui_listbox_set_items(rtgui_listbox_t* box, struct rtgui_listbox_item* items, rt_uint16_t count) +{ + rtgui_rect_t rect; + + box->items = items; + box->items_count = count; + box->current_item = -1; + + rtgui_widget_get_rect(RTGUI_WIDGET(box), &rect); + box->page_items = rtgui_rect_height(rect) / (2 + rtgui_theme_get_selected_height()); + + rtgui_widget_update(RTGUI_WIDGET(box)); +} + +void rtgui_listbox_set_current_item(rtgui_listbox_t* box, int index) +{ + RT_ASSERT(box != RT_NULL); + + if (index != box->current_item) + { + int old_item; + + old_item = box->current_item; + box->current_item = index; + + rtgui_listbox_update_current(box, old_item); + } +} + diff --git a/components/rtgui/widgets/listctrl.c b/components/rtgui/widgets/listctrl.c index 23e5c8696a..6fdc4028d6 100644 --- a/components/rtgui/widgets/listctrl.c +++ b/components/rtgui/widgets/listctrl.c @@ -1,426 +1,427 @@ -/*
- * File : listctrl.c
- * This file is part of RTGUI in RT-Thread RTOS
- * COPYRIGHT (C) 2010, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2010-01-06 Bernard first version
- */
-
-#include <rtgui/rtgui_theme.h>
-#include <rtgui/widgets/listctrl.h>
-
-static void rtgui_listctrl_update_current(struct rtgui_listctrl* ctrl, rt_uint16_t old_item);
-
-static void _rtgui_listctrl_constructor(struct rtgui_listctrl *ctrl)
-{
- /* set default widget rect and set event handler */
- rtgui_widget_set_event_handler(RTGUI_WIDGET(ctrl),rtgui_listctrl_event_handler);
-
- RTGUI_WIDGET(ctrl)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
-
- ctrl->current_item = -1;
- ctrl->items_count = 0;
- ctrl->page_items = 0;
- ctrl->on_item = 0;
- ctrl->on_item_draw = RT_NULL;
-
- RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(ctrl)) = white;
- RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(ctrl)) = RTGUI_ALIGN_CENTER_VERTICAL;
-}
-
-DEFINE_CLASS_TYPE(listctrl, "listctrl",
- RTGUI_WIDGET_TYPE,
- _rtgui_listctrl_constructor,
- RT_NULL,
- sizeof(struct rtgui_listctrl));
-
-static void _rtgui_listctrl_get_rect(struct rtgui_listctrl* ctrl, rtgui_rect_t* rect)
-{
- rtgui_widget_get_rect(RTGUI_WIDGET(ctrl), rect);
- if (ctrl->items_count > rtgui_rect_height(*rect)/rtgui_theme_get_selected_height())
- {
- rect->x2 = rect->x2 - 8;
- }
-}
-
-static void _rtgui_listctrl_get_scrollbar_rect(struct rtgui_listctrl* ctrl, rtgui_rect_t* rect)
-{
- rtgui_widget_get_rect(RTGUI_WIDGET(ctrl), rect);
- if (ctrl->items_count > rtgui_rect_height(*rect)/rtgui_theme_get_selected_height())
- {
- rect->x1 = rect->x2 - 8;
- }
- else
- {
- /* no scrollbar */
- rt_memset(rect, 0, sizeof(rtgui_rect_t));
- }
-}
-
-static void _rtgui_listctrl_scrollbar_ondraw(struct rtgui_listctrl* ctrl, struct rtgui_dc* dc)
-{
- rtgui_rect_t rect;
- rt_uint32_t height, y1;
-
- /* get scrollbar rect */
- _rtgui_listctrl_get_scrollbar_rect(ctrl, &rect);
- rtgui_dc_fill_rect(dc, &rect);
-
- height = rtgui_rect_height(rect);
-
- height = height / ((ctrl->items_count + (ctrl->page_items - 1))/ctrl->page_items);
- y1 = (ctrl->current_item / ctrl->page_items) * height;
-
- rect.y1 = rect.y1 + y1; rect.y2 = rect.y1 + height;
- rect.x1 -= 3;
- rtgui_theme_draw_selected(dc, &rect);
-}
-
-static void _rtgui_listctrl_scrollbar_onmouse(struct rtgui_listctrl* ctrl, struct rtgui_event_mouse* mouse)
-{
- rtgui_rect_t rect;
- rt_uint32_t height, y1;
- rt_uint16_t old_item;
-
- /* get scrollbar rect */
- _rtgui_listctrl_get_scrollbar_rect(ctrl, &rect);
- height = rtgui_rect_height(rect);
- height = height / ((ctrl->items_count + (ctrl->page_items - 1))/ctrl->page_items);
- y1 = (ctrl->current_item / ctrl->page_items) * height;
-
- rect.y1 = rect.y1 + y1; rect.y2 = rect.y1 + height;
- rtgui_widget_rect_to_device(RTGUI_WIDGET(ctrl), &rect);
-
- old_item = ctrl->current_item;
- if (mouse->y < rect.y1)
- {
- if (ctrl->current_item - ctrl->page_items >= 0)
- ctrl->current_item -= ctrl->page_items;
- rtgui_listctrl_update_current(ctrl, old_item);
- }
- else if (mouse->y > rect.y2)
- {
- if (ctrl->current_item + ctrl->page_items < ctrl->items_count - 1)
- ctrl->current_item += ctrl->page_items;
- else
- ctrl->current_item = ((ctrl->current_item / ctrl->page_items) + 1) * ctrl->page_items;
- rtgui_listctrl_update_current(ctrl, old_item);
- }
-}
-
-static void _rtgui_listctrl_ondraw(struct rtgui_listctrl* ctrl)
-{
- struct rtgui_rect rect, item_rect;
- struct rtgui_dc* dc;
- rt_uint16_t page_index, index;
-
- dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(ctrl));
- if (dc == RT_NULL) return;
-
- _rtgui_listctrl_get_rect(ctrl, &rect);
- rtgui_dc_fill_rect(dc, &rect);
-
- rect.x2 -= 1; rect.y2 -= 1;
-
- /* get item base rect */
- item_rect = rect;
- item_rect.x1 += 1; item_rect.x2 -= 1;
- item_rect.y1 += 2;
- item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height());
-
- /* get current page */
- page_index = (ctrl->current_item / ctrl->page_items) * ctrl->page_items;
- for (index = 0; index < ctrl->page_items; index ++)
- {
- if (page_index + index >= ctrl->items_count) break;
-
- if (page_index + index == ctrl->current_item)
- {
- rtgui_theme_draw_selected(dc, &item_rect);
- }
-
- if (ctrl->on_item_draw != RT_NULL)
- {
- ctrl->on_item_draw(ctrl, dc, &item_rect, page_index + index);
- }
-
- /* move to next item position */
- item_rect.y1 += (rtgui_theme_get_selected_height() + 2);
- item_rect.y2 += (rtgui_theme_get_selected_height() + 2);
- }
-
- /* draw scrollbar */
- _rtgui_listctrl_scrollbar_ondraw(ctrl, dc);
- rtgui_dc_end_drawing(dc);
-}
-
-void rtgui_listctrl_update_current(struct rtgui_listctrl* ctrl, rt_uint16_t old_item)
-{
- struct rtgui_dc* dc;
- rtgui_rect_t rect, item_rect;
-
- if (old_item/ctrl->page_items != ctrl->current_item/ctrl->page_items)
- {
- /* it's not a same page, update all */
- rtgui_widget_update(RTGUI_WIDGET(ctrl));
- return;
- }
-
- dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(ctrl));
- if (dc == RT_NULL) return;
-
- _rtgui_listctrl_get_rect(ctrl, &rect);
- rect.x2 -= 1; rect.y2 -= 1;
-
- item_rect = rect;
- /* get old item's rect */
- item_rect.x1 += 1; item_rect.x2 -= 1;
- item_rect.y1 += 2;
- item_rect.y1 += (old_item % ctrl->page_items) * (2 + rtgui_theme_get_selected_height());
- item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height());
-
- /* draw old item */
- rtgui_dc_fill_rect(dc, &item_rect);
- if (ctrl->on_item_draw != RT_NULL)
- ctrl->on_item_draw(ctrl, dc, &item_rect, old_item);
-
- /* draw current item */
- item_rect = rect;
- /* get current item's rect */
- item_rect.x1 += 1; item_rect.x2 -= 1;
- item_rect.y1 += 2;
- item_rect.y1 += (ctrl->current_item % ctrl->page_items) * (2 + rtgui_theme_get_selected_height());
- item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height());
-
- /* draw current item */
- rtgui_theme_draw_selected(dc, &item_rect);
- if (ctrl->on_item_draw != RT_NULL)
- ctrl->on_item_draw(ctrl, dc, &item_rect, ctrl->current_item);
-
- rtgui_dc_end_drawing(dc);
-}
-
-rt_bool_t rtgui_listctrl_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
-{
- struct rtgui_listctrl* ctrl = RT_NULL;
-
- ctrl = RTGUI_LISTCTRL(widget);
- switch (event->type)
- {
- case RTGUI_EVENT_PAINT:
- _rtgui_listctrl_ondraw(ctrl);
- return RT_FALSE;
-
- case RTGUI_EVENT_RESIZE:
- {
- struct rtgui_event_resize* resize;
-
- resize = (struct rtgui_event_resize*)event;
-
- /* recalculate page items */
- ctrl->page_items = resize->h / (2 + rtgui_theme_get_selected_height());
- }
- break;
-
- case RTGUI_EVENT_MOUSE_BUTTON:
- {
- rtgui_rect_t rect;
- struct rtgui_event_mouse* emouse;
-
- emouse = (struct rtgui_event_mouse*)event;
-
- /* get scrollbar rect */
- _rtgui_listctrl_get_scrollbar_rect(ctrl, &rect);
- rtgui_widget_rect_to_device(RTGUI_WIDGET(ctrl), &rect);
- if (rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK)
- {
- _rtgui_listctrl_scrollbar_onmouse(ctrl, emouse);
- return RT_TRUE;
- }
-
- /* calculate selected item */
-
- /* get physical extent information */
- _rtgui_listctrl_get_rect(ctrl, &rect);
- rtgui_widget_rect_to_device(widget, &rect);
-
- if ((rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK) &&
- (ctrl->items_count > 0))
- {
- rt_uint16_t index;
- index = (emouse->y - rect.y1) / (2 + rtgui_theme_get_selected_height());
-
- /* set focus */
- rtgui_widget_focus(widget);
- {
- struct rtgui_rect rect;
- struct rtgui_dc* dc;
-
- dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(ctrl));
- if (dc != RT_NULL)
- {
- /* get widget rect */
- rtgui_widget_get_rect(RTGUI_WIDGET(ctrl), &rect);
- /* update focus border */
- rect.x2 -= 1; rect.y2 -= 1;
- rtgui_dc_end_drawing(dc);
- }
- }
-
- if ((index < ctrl->page_items) &&
- (ctrl->current_item/ctrl->page_items)* ctrl->page_items + index < ctrl->items_count)
- {
- rt_uint16_t old_item;
-
- old_item = ctrl->current_item;
-
- /* set selected item */
- ctrl->current_item = (ctrl->current_item/ctrl->page_items) * ctrl->page_items + index;
- if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN)
- {
- /* down event */
- rtgui_listctrl_update_current(ctrl, old_item);
- }
- else
- {
- /* up event */
- if (ctrl->on_item != RT_NULL)
- {
- ctrl->on_item(RTGUI_WIDGET(ctrl), RT_NULL);
- }
- }
- }
- }
-
- return RT_TRUE;
- }
-
- case RTGUI_EVENT_KBD:
- {
- struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
- if ((ekbd->type == RTGUI_KEYDOWN) && (ctrl->items_count > 0))
- {
- rt_uint16_t old_item;
-
- old_item = ctrl->current_item;
- switch (ekbd->key)
- {
- case RTGUIK_LEFT:
- if (ctrl->current_item - ctrl->page_items >= 0)
- ctrl->current_item -= ctrl->page_items;
- rtgui_listctrl_update_current(ctrl, old_item);
- return RT_FALSE;
-
- case RTGUIK_UP:
- if (ctrl->current_item > 0)
- ctrl->current_item --;
- rtgui_listctrl_update_current(ctrl, old_item);
- return RT_FALSE;
-
- case RTGUIK_RIGHT:
- if (ctrl->current_item + ctrl->page_items < ctrl->items_count - 1)
- ctrl->current_item += ctrl->page_items;
- else
- {
- if ((((ctrl->current_item/ctrl->page_items) + 1) * ctrl->page_items) < ctrl->items_count - 1)
- ctrl->current_item = ((ctrl->current_item / ctrl->page_items) + 1) * ctrl->page_items;
- }
- rtgui_listctrl_update_current(ctrl, old_item);
- return RT_FALSE;
-
- case RTGUIK_DOWN:
- if (ctrl->current_item < ctrl->items_count - 1)
- ctrl->current_item ++;
- rtgui_listctrl_update_current(ctrl, old_item);
- return RT_FALSE;
-
- case RTGUIK_RETURN:
- if (ctrl->on_item != RT_NULL)
- {
- ctrl->on_item(RTGUI_WIDGET(ctrl), RT_NULL);
- }
- return RT_FALSE;
-
- default:
- break;
- }
- }
- }
- return RT_FALSE;
- }
-
- /* use ctrl event handler */
- return rtgui_widget_event_handler(widget, event);
-}
-
-rtgui_listctrl_t* rtgui_listctrl_create(rt_uint32_t items, rt_uint16_t count, rtgui_rect_t *rect,
- rtgui_onitem_draw_t ondraw)
-{
- struct rtgui_listctrl* ctrl = RT_NULL;
-
- ctrl = (struct rtgui_listctrl*) rtgui_widget_create(RTGUI_LISTCTRL_TYPE);
- if (ctrl != RT_NULL)
- {
- ctrl->items = items;
- ctrl->items_count = count;
- ctrl->on_item_draw = ondraw;
-
- ctrl->page_items = rtgui_rect_height(*rect) / (2 + rtgui_theme_get_selected_height());
- rtgui_widget_set_rect(RTGUI_WIDGET(ctrl), rect);
- }
-
- return ctrl;
-}
-
-void rtgui_listctrl_destroy(rtgui_listctrl_t* ctrl)
-{
- /* destroy ctrl */
- rtgui_widget_destroy(RTGUI_WIDGET(ctrl));
-}
-
-void rtgui_listctrl_set_onitem(rtgui_listctrl_t* ctrl, rtgui_onitem_func_t func)
-{
- RT_ASSERT(ctrl != RT_NULL);
-
- ctrl->on_item = func;
-}
-
-void rtgui_listctrl_set_items(rtgui_listctrl_t* ctrl, rt_uint32_t items, rt_uint16_t count)
-{
- rtgui_rect_t rect;
-
- ctrl->items = items;
- ctrl->items_count = count;
- ctrl->current_item = 0;
-
- rtgui_widget_get_rect(RTGUI_WIDGET(ctrl), &rect);
- ctrl->page_items = rtgui_rect_height(rect) / (2 + rtgui_theme_get_selected_height());
-
- rtgui_widget_update(RTGUI_WIDGET(ctrl));
-}
-
-rt_bool_t rtgui_listctrl_get_item_rect(rtgui_listctrl_t* ctrl, rt_uint16_t item, rtgui_rect_t* item_rect)
-{
- if (item < ctrl->items_count)
- {
- rt_uint16_t index;
-
- /* check whether this item in current page */
- index = (ctrl->current_item / ctrl->page_items) * ctrl->page_items;
- if (index > item || index + ctrl->page_items <= item) return RT_FALSE;
-
- rtgui_widget_get_extent(RTGUI_WIDGET(ctrl), item_rect);
- item_rect->y1 -= 2;
- item_rect->y1 += (item % ctrl->page_items) * (2 + rtgui_theme_get_selected_height());
- item_rect->y2 = item_rect->y1 + (2 + rtgui_theme_get_selected_height());
- return RT_TRUE;
- }
-
- return RT_FALSE;
-}
+/* + * File : listctrl.c + * This file is part of RTGUI in RT-Thread RTOS + * COPYRIGHT (C) 2010, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2010-01-06 Bernard first version + */ + +#include <rtgui/rtgui_theme.h> +#include <rtgui/widgets/listctrl.h> + +static void rtgui_listctrl_update_current(struct rtgui_listctrl* ctrl, rt_uint16_t old_item); + +static void _rtgui_listctrl_constructor(struct rtgui_listctrl *ctrl) +{ + /* set default widget rect and set event handler */ + rtgui_object_set_event_handler(RTGUI_OBJECT(ctrl), rtgui_listctrl_event_handler); + + RTGUI_WIDGET(ctrl)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE; + + ctrl->current_item = -1; + ctrl->items_count = 0; + ctrl->page_items = 0; + ctrl->on_item = 0; + ctrl->on_item_draw = RT_NULL; + + RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(ctrl)) = white; + RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(ctrl)) = RTGUI_ALIGN_CENTER_VERTICAL; +} + +DEFINE_CLASS_TYPE(listctrl, "listctrl", + RTGUI_WIDGET_TYPE, + _rtgui_listctrl_constructor, + RT_NULL, + sizeof(struct rtgui_listctrl)); + +static void _rtgui_listctrl_get_rect(struct rtgui_listctrl* ctrl, rtgui_rect_t* rect) +{ + rtgui_widget_get_rect(RTGUI_WIDGET(ctrl), rect); + if (ctrl->items_count > rtgui_rect_height(*rect)/rtgui_theme_get_selected_height()) + { + rect->x2 = rect->x2 - 8; + } +} + +static void _rtgui_listctrl_get_scrollbar_rect(struct rtgui_listctrl* ctrl, rtgui_rect_t* rect) +{ + rtgui_widget_get_rect(RTGUI_WIDGET(ctrl), rect); + if (ctrl->items_count > rtgui_rect_height(*rect)/rtgui_theme_get_selected_height()) + { + rect->x1 = rect->x2 - 8; + } + else + { + /* no scrollbar */ + rt_memset(rect, 0, sizeof(rtgui_rect_t)); + } +} + +static void _rtgui_listctrl_scrollbar_ondraw(struct rtgui_listctrl* ctrl, struct rtgui_dc* dc) +{ + rtgui_rect_t rect; + rt_uint32_t height, y1; + + /* get scrollbar rect */ + _rtgui_listctrl_get_scrollbar_rect(ctrl, &rect); + rtgui_dc_fill_rect(dc, &rect); + + height = rtgui_rect_height(rect); + + height = height / ((ctrl->items_count + (ctrl->page_items - 1))/ctrl->page_items); + y1 = (ctrl->current_item / ctrl->page_items) * height; + + rect.y1 = rect.y1 + y1; rect.y2 = rect.y1 + height; + rect.x1 -= 3; + rtgui_theme_draw_selected(dc, &rect); +} + +static void _rtgui_listctrl_scrollbar_onmouse(struct rtgui_listctrl* ctrl, struct rtgui_event_mouse* mouse) +{ + rtgui_rect_t rect; + rt_uint32_t height, y1; + rt_uint16_t old_item; + + /* get scrollbar rect */ + _rtgui_listctrl_get_scrollbar_rect(ctrl, &rect); + height = rtgui_rect_height(rect); + height = height / ((ctrl->items_count + (ctrl->page_items - 1))/ctrl->page_items); + y1 = (ctrl->current_item / ctrl->page_items) * height; + + rect.y1 = rect.y1 + y1; rect.y2 = rect.y1 + height; + rtgui_widget_rect_to_device(RTGUI_WIDGET(ctrl), &rect); + + old_item = ctrl->current_item; + if (mouse->y < rect.y1) + { + if (ctrl->current_item - ctrl->page_items >= 0) + ctrl->current_item -= ctrl->page_items; + rtgui_listctrl_update_current(ctrl, old_item); + } + else if (mouse->y > rect.y2) + { + if (ctrl->current_item + ctrl->page_items < ctrl->items_count - 1) + ctrl->current_item += ctrl->page_items; + else + ctrl->current_item = ((ctrl->current_item / ctrl->page_items) + 1) * ctrl->page_items; + rtgui_listctrl_update_current(ctrl, old_item); + } +} + +static void _rtgui_listctrl_ondraw(struct rtgui_listctrl* ctrl) +{ + struct rtgui_rect rect, item_rect; + struct rtgui_dc* dc; + rt_uint16_t page_index, index; + + dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(ctrl)); + if (dc == RT_NULL) return; + + _rtgui_listctrl_get_rect(ctrl, &rect); + rtgui_dc_fill_rect(dc, &rect); + + rect.x2 -= 1; rect.y2 -= 1; + + /* get item base rect */ + item_rect = rect; + item_rect.x1 += 1; item_rect.x2 -= 1; + item_rect.y1 += 2; + item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height()); + + /* get current page */ + page_index = (ctrl->current_item / ctrl->page_items) * ctrl->page_items; + for (index = 0; index < ctrl->page_items; index ++) + { + if (page_index + index >= ctrl->items_count) break; + + if (page_index + index == ctrl->current_item) + { + rtgui_theme_draw_selected(dc, &item_rect); + } + + if (ctrl->on_item_draw != RT_NULL) + { + ctrl->on_item_draw(ctrl, dc, &item_rect, page_index + index); + } + + /* move to next item position */ + item_rect.y1 += (rtgui_theme_get_selected_height() + 2); + item_rect.y2 += (rtgui_theme_get_selected_height() + 2); + } + + /* draw scrollbar */ + _rtgui_listctrl_scrollbar_ondraw(ctrl, dc); + rtgui_dc_end_drawing(dc); +} + +void rtgui_listctrl_update_current(struct rtgui_listctrl* ctrl, rt_uint16_t old_item) +{ + struct rtgui_dc* dc; + rtgui_rect_t rect, item_rect; + + if (old_item/ctrl->page_items != ctrl->current_item/ctrl->page_items) + { + /* it's not a same page, update all */ + rtgui_widget_update(RTGUI_WIDGET(ctrl)); + return; + } + + dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(ctrl)); + if (dc == RT_NULL) return; + + _rtgui_listctrl_get_rect(ctrl, &rect); + rect.x2 -= 1; rect.y2 -= 1; + + item_rect = rect; + /* get old item's rect */ + item_rect.x1 += 1; item_rect.x2 -= 1; + item_rect.y1 += 2; + item_rect.y1 += (old_item % ctrl->page_items) * (2 + rtgui_theme_get_selected_height()); + item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height()); + + /* draw old item */ + rtgui_dc_fill_rect(dc, &item_rect); + if (ctrl->on_item_draw != RT_NULL) + ctrl->on_item_draw(ctrl, dc, &item_rect, old_item); + + /* draw current item */ + item_rect = rect; + /* get current item's rect */ + item_rect.x1 += 1; item_rect.x2 -= 1; + item_rect.y1 += 2; + item_rect.y1 += (ctrl->current_item % ctrl->page_items) * (2 + rtgui_theme_get_selected_height()); + item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height()); + + /* draw current item */ + rtgui_theme_draw_selected(dc, &item_rect); + if (ctrl->on_item_draw != RT_NULL) + ctrl->on_item_draw(ctrl, dc, &item_rect, ctrl->current_item); + + rtgui_dc_end_drawing(dc); +} + +rt_bool_t rtgui_listctrl_event_handler(struct rtgui_object* object, struct rtgui_event* event) +{ + struct rtgui_listctrl* ctrl; + RTGUI_WIDGET_EVENT_HANDLER_PREPARE + + ctrl = RTGUI_LISTCTRL(object); + switch (event->type) + { + case RTGUI_EVENT_PAINT: + _rtgui_listctrl_ondraw(ctrl); + return RT_FALSE; + + case RTGUI_EVENT_RESIZE: + { + struct rtgui_event_resize* resize; + + resize = (struct rtgui_event_resize*)event; + + /* recalculate page items */ + ctrl->page_items = resize->h / (2 + rtgui_theme_get_selected_height()); + } + break; + + case RTGUI_EVENT_MOUSE_BUTTON: + { + rtgui_rect_t rect; + struct rtgui_event_mouse* emouse; + + emouse = (struct rtgui_event_mouse*)event; + + /* get scrollbar rect */ + _rtgui_listctrl_get_scrollbar_rect(ctrl, &rect); + rtgui_widget_rect_to_device(RTGUI_WIDGET(ctrl), &rect); + if (rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK) + { + _rtgui_listctrl_scrollbar_onmouse(ctrl, emouse); + return RT_TRUE; + } + + /* calculate selected item */ + + /* get physical extent information */ + _rtgui_listctrl_get_rect(ctrl, &rect); + rtgui_widget_rect_to_device(widget, &rect); + + if ((rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK) && + (ctrl->items_count > 0)) + { + rt_uint16_t index; + index = (emouse->y - rect.y1) / (2 + rtgui_theme_get_selected_height()); + + /* set focus */ + rtgui_widget_focus(widget); + { + struct rtgui_rect rect; + struct rtgui_dc* dc; + + dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(ctrl)); + if (dc != RT_NULL) + { + /* get widget rect */ + rtgui_widget_get_rect(RTGUI_WIDGET(ctrl), &rect); + /* update focus border */ + rect.x2 -= 1; rect.y2 -= 1; + rtgui_dc_end_drawing(dc); + } + } + + if ((index < ctrl->page_items) && + (ctrl->current_item/ctrl->page_items)* ctrl->page_items + index < ctrl->items_count) + { + rt_uint16_t old_item; + + old_item = ctrl->current_item; + + /* set selected item */ + ctrl->current_item = (ctrl->current_item/ctrl->page_items) * ctrl->page_items + index; + if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN) + { + /* down event */ + rtgui_listctrl_update_current(ctrl, old_item); + } + else + { + /* up event */ + if (ctrl->on_item != RT_NULL) + { + ctrl->on_item(RTGUI_OBJECT(ctrl), RT_NULL); + } + } + } + } + + return RT_TRUE; + } + + case RTGUI_EVENT_KBD: + { + struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event; + if ((ekbd->type == RTGUI_KEYDOWN) && (ctrl->items_count > 0)) + { + rt_uint16_t old_item; + + old_item = ctrl->current_item; + switch (ekbd->key) + { + case RTGUIK_LEFT: + if (ctrl->current_item - ctrl->page_items >= 0) + ctrl->current_item -= ctrl->page_items; + rtgui_listctrl_update_current(ctrl, old_item); + return RT_FALSE; + + case RTGUIK_UP: + if (ctrl->current_item > 0) + ctrl->current_item --; + rtgui_listctrl_update_current(ctrl, old_item); + return RT_FALSE; + + case RTGUIK_RIGHT: + if (ctrl->current_item + ctrl->page_items < ctrl->items_count - 1) + ctrl->current_item += ctrl->page_items; + else + { + if ((((ctrl->current_item/ctrl->page_items) + 1) * ctrl->page_items) < ctrl->items_count - 1) + ctrl->current_item = ((ctrl->current_item / ctrl->page_items) + 1) * ctrl->page_items; + } + rtgui_listctrl_update_current(ctrl, old_item); + return RT_FALSE; + + case RTGUIK_DOWN: + if (ctrl->current_item < ctrl->items_count - 1) + ctrl->current_item ++; + rtgui_listctrl_update_current(ctrl, old_item); + return RT_FALSE; + + case RTGUIK_RETURN: + if (ctrl->on_item != RT_NULL) + { + ctrl->on_item(RTGUI_OBJECT(ctrl), RT_NULL); + } + return RT_FALSE; + + default: + break; + } + } + } + return RT_FALSE; + } + + /* use ctrl event handler */ + return rtgui_widget_event_handler(RTGUI_OBJECT(widget), event); +} + +rtgui_listctrl_t* rtgui_listctrl_create(rt_uint32_t items, rt_uint16_t count, rtgui_rect_t *rect, + rtgui_onitem_draw_t ondraw) +{ + struct rtgui_listctrl* ctrl = RT_NULL; + + ctrl = (struct rtgui_listctrl*) rtgui_widget_create(RTGUI_LISTCTRL_TYPE); + if (ctrl != RT_NULL) + { + ctrl->items = items; + ctrl->items_count = count; + ctrl->on_item_draw = ondraw; + + ctrl->page_items = rtgui_rect_height(*rect) / (2 + rtgui_theme_get_selected_height()); + rtgui_widget_set_rect(RTGUI_WIDGET(ctrl), rect); + } + + return ctrl; +} + +void rtgui_listctrl_destroy(rtgui_listctrl_t* ctrl) +{ + /* destroy ctrl */ + rtgui_widget_destroy(RTGUI_WIDGET(ctrl)); +} + +void rtgui_listctrl_set_onitem(rtgui_listctrl_t* ctrl, rtgui_event_handler_ptr func) +{ + RT_ASSERT(ctrl != RT_NULL); + + ctrl->on_item = func; +} + +void rtgui_listctrl_set_items(rtgui_listctrl_t* ctrl, rt_uint32_t items, rt_uint16_t count) +{ + rtgui_rect_t rect; + + ctrl->items = items; + ctrl->items_count = count; + ctrl->current_item = 0; + + rtgui_widget_get_rect(RTGUI_WIDGET(ctrl), &rect); + ctrl->page_items = rtgui_rect_height(rect) / (2 + rtgui_theme_get_selected_height()); + + rtgui_widget_update(RTGUI_WIDGET(ctrl)); +} + +rt_bool_t rtgui_listctrl_get_item_rect(rtgui_listctrl_t* ctrl, rt_uint16_t item, rtgui_rect_t* item_rect) +{ + if (item < ctrl->items_count) + { + rt_uint16_t index; + + /* check whether this item in current page */ + index = (ctrl->current_item / ctrl->page_items) * ctrl->page_items; + if (index > item || index + ctrl->page_items <= item) return RT_FALSE; + + rtgui_widget_get_extent(RTGUI_WIDGET(ctrl), item_rect); + item_rect->y1 -= 2; + item_rect->y1 += (item % ctrl->page_items) * (2 + rtgui_theme_get_selected_height()); + item_rect->y2 = item_rect->y1 + (2 + rtgui_theme_get_selected_height()); + return RT_TRUE; + } + + return RT_FALSE; +} diff --git a/components/rtgui/widgets/menu.c b/components/rtgui/widgets/menu.c index 7d8b02dd3b..c56041db83 100644 --- a/components/rtgui/widgets/menu.c +++ b/components/rtgui/widgets/menu.c @@ -1,275 +1,287 @@ -#include <rtgui/dc.h>
-#include <rtgui/widgets/menu.h>
-#include <rtgui/rtgui_theme.h>
-
-static rt_bool_t rtgui_menu_on_deactivate(rtgui_widget_t* widget, rtgui_event_t* event);
-const static rt_uint8_t right_arrow[] = {0x80, 0xc0, 0xe0, 0xf0, 0xe0, 0xc0, 0x80};
-
-static void _rtgui_menu_constructor(rtgui_menu_t *menu)
-{
- /* set window style */
- RTGUI_WIN(menu)->style = RTGUI_WIN_STYLE_NO_TITLE;
-
- /* set deactivate handler */
- rtgui_win_set_ondeactivate(RTGUI_WIN(menu), rtgui_menu_on_deactivate);
-
- /* set proper of control */
- menu->parent_menu = RT_NULL;
- menu->sub_menu = RT_NULL;
-
- menu->items = RT_NULL;
- menu->items_count = 0;
- menu->items_list = RT_NULL;
-
- menu->on_menupop = RT_NULL;
- menu->on_menuhide = RT_NULL;
-}
-
-static void _rtgui_menu_destructor(rtgui_menu_t* menu)
-{
- if (menu->sub_menu != RT_NULL)
- {
- rtgui_menu_destroy(menu->sub_menu);
- menu->sub_menu = RT_NULL;
- }
-
- rtgui_listctrl_destroy(menu->items_list);
- menu->items_list = RT_NULL;
-}
-
-static void _rtgui_menu_onitem(struct rtgui_widget* widget, struct rtgui_event* event)
-{
- struct rtgui_menu* menu;
-
- /* get menu */
- menu = RTGUI_MENU(rtgui_widget_get_toplevel(widget));
- if (menu->items[menu->items_list->current_item].type == RTGUI_ITEM_SUBMENU)
- {
- const rtgui_menu_item_t* items;
- rt_uint16_t count;
- rtgui_rect_t item_rect;
-
- items = (rtgui_menu_item_t*)menu->items[menu->items_list->current_item].submenu;
- count = menu->items[menu->items_list->current_item].submenu_count;
- if (menu->sub_menu != RT_NULL)
- {
- if (menu->sub_menu->items == items)
- {
- if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(menu->sub_menu)))
- {
- /* hide this sub menu */
- rtgui_win_hiden(RTGUI_WIN(menu->sub_menu));
- return;
- }
-
- /* show this sub menu */
- rtgui_listctrl_get_item_rect(menu->items_list, menu->items_list->current_item, &item_rect);
- rtgui_menu_pop(menu->sub_menu, item_rect.x2, item_rect.y1);
- return;
- }
-
- /* delete sub menu */
- rtgui_menu_destroy(menu->sub_menu);
- menu->sub_menu = RT_NULL;
- }
-
- /* create sub menu */
- menu->sub_menu = rtgui_menu_create("submenu", menu, items, count);
-
- rtgui_listctrl_get_item_rect(menu->items_list, menu->items_list->current_item, &item_rect);
- rtgui_menu_pop(menu->sub_menu, item_rect.x2 + 5, item_rect.y1);
- }
- else /* other menu item */
- {
- /* invoke action */
- if (menu->items[menu->items_list->current_item].on_menuaction != RT_NULL)
- menu->items[menu->items_list->current_item].on_menuaction(RTGUI_WIDGET(menu), RT_NULL);
-
- /* hide sub-menu */
- if (menu->sub_menu != RT_NULL)
- {
- rtgui_menu_hiden(menu->sub_menu);
- }
- rtgui_menu_hiden(menu);
- }
-}
-
-static void _rtgui_menu_item_ondraw(struct rtgui_listctrl *list, struct rtgui_dc* dc, rtgui_rect_t* rect, rt_uint16_t index)
-{
- rtgui_rect_t item_rect;
- struct rtgui_menu_item* item;
-
- item_rect = *rect;
- item_rect.x1 += 5;
-
- /* re-fill item */
- if (list->current_item == index)
- {
- rtgui_color_t bc;
-
- bc = RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(list));
- RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(list)) = blue;
- rtgui_dc_fill_rect(dc, rect);
- RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(list)) = bc;
- }
-
- /* get menu item */
- item = (rtgui_menu_item_t*)list->items;
- item = &item[index];
-
- if (item->type == RTGUI_ITEM_SUBMENU)
- {
- rtgui_rect_t r = {0, 0, 8, 8};
- rtgui_dc_draw_text(dc, item->label, &item_rect);
- item_rect.x1 = item_rect.x2 - 16; item_rect.x2 -= 8;
- rtgui_rect_moveto_align(&item_rect, &r, RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL);
- rtgui_dc_draw_byte(dc, r.x1, r.y1, 8, right_arrow);
- }
- else if (item->type == RTGUI_ITEM_SEPARATOR)
- {
- rtgui_dc_draw_horizontal_line(dc, item_rect.x1, item_rect.x2, (item_rect.y2 + item_rect.y1)/2);
- }
- else if (item->type == RTGUI_ITEM_CHECK)
- {
- /* not support right now */
- }
- else
- {
- /* normal menu item */
- rtgui_dc_draw_text(dc, item->label, &item_rect);
- if (item->image != RT_NULL)
- rtgui_image_blit(item->image, dc, &item_rect);
- }
-}
-
-DEFINE_CLASS_TYPE(menu, "menu",
- RTGUI_WIN_TYPE,
- _rtgui_menu_constructor,
- _rtgui_menu_destructor,
- sizeof(struct rtgui_menu));
-
-static rt_bool_t rtgui_menu_on_deactivate(rtgui_widget_t* widget, rtgui_event_t* event)
-{
- rtgui_menu_t* menu = (rtgui_menu_t*) widget;
-
- if (menu->parent_menu != RT_NULL)
- {
- /* whether click on parent menu */
- if (rtgui_win_is_activated(RTGUI_WIN(menu->parent_menu)) == RT_TRUE &&
- menu->parent_menu->items[menu->parent_menu->items_list->current_item].submenu == (struct rtgui_menu_item_t *)menu->items)
- return RT_TRUE;
- }
-
- /* submenu is activate */
- if (menu->items[menu->items_list->current_item].type == RTGUI_ITEM_SUBMENU)
- {
- /* if sub menu activated, not hide menu */
- if (menu->sub_menu != RT_NULL &&
- rtgui_win_is_activated(RTGUI_WIN(menu->sub_menu)) == RT_TRUE)
- return RT_TRUE;
- }
-
- rtgui_win_hiden(RTGUI_WIN(menu));
- if (menu->on_menuhide != RT_NULL)
- {
- menu->on_menuhide(RTGUI_WIDGET(menu), RT_NULL);
- }
-
- /* un-select item */
- menu->items_list->current_item = -1;
-
- /* if it's a submenu, try to hide parent menu */
- if (menu->parent_menu != RT_NULL &&
- rtgui_win_is_activated(RTGUI_WIN(menu->parent_menu)) == RT_FALSE)
- {
- rtgui_menu_on_deactivate(RTGUI_WIDGET(menu->parent_menu), event);
- }
-
- return RT_TRUE;
-}
-
-struct rtgui_menu* rtgui_menu_create(const char* title, struct rtgui_menu* parent_menu,
- const struct rtgui_menu_item* items, rt_uint16_t count)
-{
- rtgui_rect_t rect = {0, 0, 100, 100};
- struct rtgui_menu* menu;
-
- menu = (struct rtgui_menu*) rtgui_widget_create ( RTGUI_MENU_TYPE );
- if (menu != RT_NULL)
- {
- rtgui_win_set_title(RTGUI_WIN(menu), title);
- menu->parent_menu = parent_menu;
- menu->items = items;
- menu->items_count = count;
-
- rtgui_widget_set_rect(RTGUI_WIDGET(menu), &rect);
- rtgui_rect_inflate(&rect, -1);
- /* create menu item list */
- menu->items_list = rtgui_listctrl_create((rt_uint32_t)items, count, &rect, _rtgui_menu_item_ondraw);
- RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(menu->items_list)) = rtgui_theme_default_bc();
- rtgui_container_add_child(RTGUI_CONTAINER(menu), RTGUI_WIDGET(menu->items_list));
- rtgui_listctrl_set_onitem(menu->items_list, _rtgui_menu_onitem);
- }
-
- return menu;
-}
-
-void rtgui_menu_destroy(struct rtgui_menu* menu)
-{
- rtgui_widget_destroy (RTGUI_WIDGET(menu));
-}
-
-void rtgui_menu_set_onmenupop(struct rtgui_menu* menu, rtgui_event_handler_ptr handler)
-{
- if (menu == RT_NULL) return;
-
- menu->on_menupop = handler;
-}
-
-void rtgui_menu_set_onmenuhide(struct rtgui_menu* menu, rtgui_event_handler_ptr handler)
-{
- if (menu == RT_NULL) return;
-
- menu->on_menuhide = handler;
-}
-
-void rtgui_menu_pop(struct rtgui_menu* menu, int x, int y)
-{
- rtgui_rect_t rect;
- struct rtgui_event_resize eresize;
-
- if (menu == RT_NULL) return;
-
- /* set window extent */
- rect.x1 = 0; rect.y1 = 0;
- rect.x2 = 100; rect.y2 = menu->items_count * (rtgui_theme_get_selected_height() + 2) + 5;
- rtgui_rect_moveto(&rect, x, y);
- rtgui_win_set_rect(RTGUI_WIN(menu), &rect);
- rtgui_rect_inflate(&rect, -1);
- rtgui_widget_set_rect(RTGUI_WIDGET(menu->items_list), &rect);
-
- eresize.parent.type = RTGUI_EVENT_RESIZE;
- eresize.x = rect.x1; eresize.y = rect.y1;
- eresize.h = rect.y2 - rect.y1; eresize.w = rect.x2 - rect.x1;
- rtgui_listctrl_event_handler(RTGUI_WIDGET(menu->items_list), &(eresize.parent));
-
- /* on menu pop handler */
- if (menu->on_menupop != RT_NULL)
- {
- menu->on_menupop(RTGUI_WIDGET(menu), RT_NULL);
- }
-
- /* show menu window */
- rtgui_win_show(RTGUI_WIN(menu), RT_FALSE);
-}
-
-void rtgui_menu_hiden(struct rtgui_menu* menu)
-{
- rtgui_win_hiden(RTGUI_WIN(menu));
- /* un-select item */
- menu->items_list->current_item = -1;
-
- if (menu->parent_menu != RT_NULL)
- rtgui_menu_hiden(menu->parent_menu);
-}
-
+#include <rtgui/dc.h> +#include <rtgui/widgets/menu.h> +#include <rtgui/rtgui_theme.h> + +static rt_bool_t rtgui_menu_on_deactivate(struct rtgui_object* object, rtgui_event_t* event); +const static rt_uint8_t right_arrow[] = {0x80, 0xc0, 0xe0, 0xf0, 0xe0, 0xc0, 0x80}; + +static void _rtgui_menu_constructor(rtgui_menu_t *menu) +{ + /* set window style */ + RTGUI_WIN(menu)->style = RTGUI_WIN_STYLE_NO_TITLE; + + /* set deactivate handler */ + rtgui_win_set_ondeactivate(RTGUI_WIN(menu), rtgui_menu_on_deactivate); + + /* set proper of control */ + menu->parent_menu = RT_NULL; + menu->sub_menu = RT_NULL; + + menu->items = RT_NULL; + menu->items_count = 0; + menu->items_list = RT_NULL; + + menu->on_menupop = RT_NULL; + menu->on_menuhide = RT_NULL; +} + +static void _rtgui_menu_destructor(rtgui_menu_t* menu) +{ + if (menu->sub_menu != RT_NULL) + { + rtgui_menu_destroy(menu->sub_menu); + menu->sub_menu = RT_NULL; + } + + rtgui_listctrl_destroy(menu->items_list); + menu->items_list = RT_NULL; +} + +static rt_bool_t _rtgui_menu_onitem(struct rtgui_object* object, struct rtgui_event* event) +{ + struct rtgui_menu* menu; + RTGUI_WIDGET_EVENT_HANDLER_PREPARE + + /* get menu */ + menu = RTGUI_MENU(rtgui_widget_get_toplevel(widget)); + if (menu->items[menu->items_list->current_item].type == RTGUI_ITEM_SUBMENU) + { + const rtgui_menu_item_t* items; + rt_uint16_t count; + rtgui_rect_t item_rect; + + items = (rtgui_menu_item_t*)menu->items[menu->items_list->current_item].submenu; + count = menu->items[menu->items_list->current_item].submenu_count; + if (menu->sub_menu != RT_NULL) + { + if (menu->sub_menu->items == items) + { + if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(menu->sub_menu))) + { + /* hide this sub menu */ + rtgui_win_hiden(RTGUI_WIN(menu->sub_menu)); + return RT_FALSE; + } + + /* show this sub menu */ + rtgui_listctrl_get_item_rect(menu->items_list, menu->items_list->current_item, &item_rect); + rtgui_menu_pop(menu->sub_menu, item_rect.x2, item_rect.y1); + return RT_FALSE; + } + + /* delete sub menu */ + rtgui_menu_destroy(menu->sub_menu); + menu->sub_menu = RT_NULL; + } + + /* create sub menu */ + menu->sub_menu = rtgui_menu_create("submenu", menu, items, count); + + rtgui_listctrl_get_item_rect(menu->items_list, menu->items_list->current_item, &item_rect); + rtgui_menu_pop(menu->sub_menu, item_rect.x2 + 5, item_rect.y1); + } + else /* other menu item */ + { + /* invoke action */ + if (menu->items[menu->items_list->current_item].on_menuaction != RT_NULL) + menu->items[menu->items_list->current_item].on_menuaction(RTGUI_WIDGET(menu), RT_NULL); + + /* hide sub-menu */ + if (menu->sub_menu != RT_NULL) + { + rtgui_menu_hiden(menu->sub_menu); + } + rtgui_menu_hiden(menu); + } + return RT_FALSE; +} + +static void _rtgui_menu_item_ondraw(struct rtgui_listctrl *list, + struct rtgui_dc* dc, + rtgui_rect_t* rect, + rt_uint16_t index) +{ + rtgui_rect_t item_rect; + struct rtgui_menu_item* item; + + item_rect = *rect; + item_rect.x1 += 5; + + /* re-fill item */ + if (list->current_item == index) + { + rtgui_color_t bc; + + bc = RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(list)); + RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(list)) = blue; + rtgui_dc_fill_rect(dc, rect); + RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(list)) = bc; + } + + /* get menu item */ + item = (rtgui_menu_item_t*)list->items; + item = &item[index]; + + if (item->type == RTGUI_ITEM_SUBMENU) + { + rtgui_rect_t r = {0, 0, 8, 8}; + rtgui_dc_draw_text(dc, item->label, &item_rect); + item_rect.x1 = item_rect.x2 - 16; item_rect.x2 -= 8; + rtgui_rect_moveto_align(&item_rect, &r, RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL); + rtgui_dc_draw_byte(dc, r.x1, r.y1, 8, right_arrow); + } + else if (item->type == RTGUI_ITEM_SEPARATOR) + { + rtgui_dc_draw_horizontal_line(dc, item_rect.x1, item_rect.x2, (item_rect.y2 + item_rect.y1)/2); + } + else if (item->type == RTGUI_ITEM_CHECK) + { + /* not support right now */ + } + else + { + /* normal menu item */ + rtgui_dc_draw_text(dc, item->label, &item_rect); + if (item->image != RT_NULL) + rtgui_image_blit(item->image, dc, &item_rect); + } +} + +DEFINE_CLASS_TYPE(menu, "menu", + RTGUI_WIN_TYPE, + _rtgui_menu_constructor, + _rtgui_menu_destructor, + sizeof(struct rtgui_menu)); + +static rt_bool_t rtgui_menu_on_deactivate(struct rtgui_object *object, rtgui_event_t* event) +{ + rtgui_menu_t* menu; + RTGUI_WIDGET_EVENT_HANDLER_PREPARE + + menu = RTGUI_MENU(object); + if (menu->parent_menu != RT_NULL) + { + /* whether click on parent menu */ + if (rtgui_win_is_activated(RTGUI_WIN(menu->parent_menu)) == RT_TRUE && + menu->parent_menu->items[menu->parent_menu->items_list->current_item].submenu + == (struct rtgui_menu_item_t *)menu->items) + return RT_TRUE; + } + + /* submenu is activate */ + if (menu->items[menu->items_list->current_item].type == RTGUI_ITEM_SUBMENU) + { + /* if sub menu activated, not hide menu. But we cannot use the + * activated flag as criteria since the old window is deactivated + * before the new window got activated. But the window will be shown in + * this context, so use 'is not hide'. */ + if (menu->sub_menu != RT_NULL && + !RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(menu->sub_menu))) + return RT_TRUE; + } + + rtgui_win_hiden(RTGUI_WIN(menu)); + if (menu->on_menuhide != RT_NULL) + { + menu->on_menuhide(RTGUI_OBJECT(menu), RT_NULL); + } + + /* un-select item */ + menu->items_list->current_item = -1; + + /* if it's a submenu, try to hide parent menu */ + if (menu->parent_menu != RT_NULL && + rtgui_win_is_activated(RTGUI_WIN(menu->parent_menu)) == RT_FALSE) + { + rtgui_menu_on_deactivate(RTGUI_OBJECT(menu->parent_menu), event); + } + + return RT_TRUE; +} + +struct rtgui_menu* rtgui_menu_create(const char* title, struct rtgui_menu* parent_menu, + const struct rtgui_menu_item* items, rt_uint16_t count) +{ + rtgui_rect_t rect = {0, 0, 100, 100}; + struct rtgui_menu* menu; + + menu = (struct rtgui_menu*) rtgui_widget_create ( RTGUI_MENU_TYPE ); + if (menu != RT_NULL) + { + rtgui_win_set_title(RTGUI_WIN(menu), title); + menu->parent_menu = parent_menu; + menu->items = items; + menu->items_count = count; + + rtgui_widget_set_rect(RTGUI_WIDGET(menu), &rect); + rtgui_rect_inflate(&rect, -1); + /* create menu item list */ + menu->items_list = rtgui_listctrl_create((rt_uint32_t)items, count, &rect, _rtgui_menu_item_ondraw); + RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(menu->items_list)) = rtgui_theme_default_bc(); + rtgui_container_add_child(RTGUI_CONTAINER(menu), RTGUI_WIDGET(menu->items_list)); + rtgui_listctrl_set_onitem(menu->items_list, _rtgui_menu_onitem); + } + + return menu; +} + +void rtgui_menu_destroy(struct rtgui_menu* menu) +{ + rtgui_widget_destroy (RTGUI_WIDGET(menu)); +} + +void rtgui_menu_set_onmenupop(struct rtgui_menu* menu, rtgui_event_handler_ptr handler) +{ + if (menu == RT_NULL) return; + + menu->on_menupop = handler; +} + +void rtgui_menu_set_onmenuhide(struct rtgui_menu* menu, rtgui_event_handler_ptr handler) +{ + if (menu == RT_NULL) return; + + menu->on_menuhide = handler; +} + +void rtgui_menu_pop(struct rtgui_menu* menu, int x, int y) +{ + rtgui_rect_t rect; + struct rtgui_event_resize eresize; + + if (menu == RT_NULL) + return; + + /* set window extent */ + rect.x1 = 0; rect.y1 = 0; + rect.x2 = 100; rect.y2 = menu->items_count * (rtgui_theme_get_selected_height() + 2) + 5; + rtgui_rect_moveto(&rect, x, y); + rtgui_win_set_rect(RTGUI_WIN(menu), &rect); + rtgui_rect_inflate(&rect, -1); + rtgui_widget_set_rect(RTGUI_WIDGET(menu->items_list), &rect); + + eresize.parent.type = RTGUI_EVENT_RESIZE; + eresize.x = rect.x1; eresize.y = rect.y1; + eresize.h = rect.y2 - rect.y1; eresize.w = rect.x2 - rect.x1; + rtgui_listctrl_event_handler(RTGUI_OBJECT(menu->items_list), &(eresize.parent)); + + /* on menu pop handler */ + if (menu->on_menupop != RT_NULL) + { + menu->on_menupop(RTGUI_OBJECT(menu), RT_NULL); + } + + /* show menu window */ + rtgui_win_show(RTGUI_WIN(menu), RT_FALSE); +} + +void rtgui_menu_hiden(struct rtgui_menu* menu) +{ + rtgui_win_hiden(RTGUI_WIN(menu)); + /* un-select item */ + menu->items_list->current_item = -1; + + if (menu->parent_menu != RT_NULL) + rtgui_menu_hiden(menu->parent_menu); +} + diff --git a/components/rtgui/widgets/notebook.c b/components/rtgui/widgets/notebook.c index 667baa9ec2..c928cd268d 100644 --- a/components/rtgui/widgets/notebook.c +++ b/components/rtgui/widgets/notebook.c @@ -1,330 +1,356 @@ -#include <rtgui/dc.h>
-#include <rtgui/rtgui.h>
-#include <rtgui/rtgui_system.h>
-#include <rtgui/widgets/notebook.h>
-
-#define RTGUI_NOTEBOOK_TAB_WIDTH 80
-
-static void _rtgui_notebook_get_bar_rect(rtgui_notebook_t *notebook, struct rtgui_rect* rect);
-static void _rtgui_notebook_get_page_rect(rtgui_notebook_t *notebook, struct rtgui_rect* rect);
-
-static void _rtgui_notebook_constructor(rtgui_notebook_t *notebook)
-{
- notebook->flag = 0;
- notebook->childs = RT_NULL;
- notebook->count = 0;
- notebook->current = RTGUI_NOT_FOUND;
-
- RTGUI_WIDGET(notebook)->gc.textalign = RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL;
- rtgui_widget_set_event_handler(RTGUI_WIDGET(notebook), rtgui_notebook_event_handler);
-}
-
-static void _rtgui_notebook_destructor(rtgui_notebook_t *notebook)
-{
- int index;
-
- if (notebook->childs != RT_NULL)
- {
- for (index = 0; index < notebook->count; index ++)
- {
- rtgui_widget_destroy(notebook->childs[index].widget);
- rt_free(notebook->childs[index].title);
- }
-
- rtgui_free(notebook->childs);
- }
-}
-
-/* Draw tab bars of @param notebook. @param dc should be initialized and
- * finished outside this function. Don't pass @param notebook or @param dc as
- * RT_NULL, it should be checked outside.
- */
-static void _rtgui_notebook_draw_bar(struct rtgui_notebook *notebook,
- struct rtgui_dc *dc)
-{
- struct rtgui_rect rect;
- int index;
-
- RT_ASSERT((notebook != RT_NULL) && (dc != RT_NULL));
-
- _rtgui_notebook_get_bar_rect(notebook, &rect);
- rtgui_dc_fill_rect(dc, &rect);
-
- rect.x2 = rect.x1 + RTGUI_NOTEBOOK_TAB_WIDTH;
- /* draw tab bar */
- for (index = 0; index < notebook->count; index++)
- {
- if (notebook->current == index)
- rtgui_dc_draw_border(dc, &rect, RTGUI_BORDER_SUNKEN);
- else
- rtgui_dc_draw_border(dc, &rect, RTGUI_BORDER_BOX);
-
- rtgui_dc_draw_text(dc, notebook->childs[index].title, &rect);
- rect.x1 += RTGUI_NOTEBOOK_TAB_WIDTH;
- rect.x2 += RTGUI_NOTEBOOK_TAB_WIDTH;
- }
-
-}
-
-static void _rtgui_notebook_ondraw(rtgui_notebook_t *notebook)
-{
- struct rtgui_dc* dc;
-
- dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(notebook));
- if (dc == RT_NULL) return;
-
- if (notebook->count == 0)
- {
- rtgui_rect_t rect;
- rtgui_widget_get_rect(RTGUI_WIDGET(notebook), &rect);
- rtgui_dc_fill_rect(dc, &rect);
- }
- else
- {
- if (notebook->current == RTGUI_NOT_FOUND)
- notebook->current = 0;
-
- _rtgui_notebook_draw_bar(notebook, dc);
-
- /* draw current tab */
- rtgui_widget_update(notebook->childs[notebook->current].widget);
- }
- rtgui_dc_end_drawing(dc);
-}
-
-static void _rtgui_notebook_onmouse(rtgui_notebook_t *notebook, struct rtgui_event_mouse* emouse)
-{
- rtgui_rect_t rect;
-
- /* handle notebook bar */
- _rtgui_notebook_get_bar_rect(notebook, &rect);
- rtgui_widget_rect_to_device(RTGUI_WIDGET(notebook), &rect);
- if (rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK)
- {
- int index;
- struct rtgui_dc* dc;
-
- index = (emouse->x - rect.x1) / RTGUI_NOTEBOOK_TAB_WIDTH;
- if (index < notebook->count && index != notebook->current)
- {
- /* update tab bar */
- dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(notebook));
- if (dc == RT_NULL) return;
-
- rtgui_notebook_set_current_by_index(notebook, index);
-
- _rtgui_notebook_draw_bar(notebook, dc);
-
- rtgui_dc_end_drawing(dc);
- }
- }
- else
- {
- /* handle on page */
- if (notebook->childs[notebook->current].widget->event_handler != RT_NULL)
- notebook->childs[notebook->current].widget->event_handler(
- notebook->childs[notebook->current].widget,
- &(emouse->parent));
- }
-}
-
-static void _rtgui_notebook_get_page_rect(rtgui_notebook_t *notebook, struct rtgui_rect* rect)
-{
- RT_ASSERT(notebook != RT_NULL);
- RT_ASSERT(rect != RT_NULL);
-
- rtgui_widget_get_rect(RTGUI_WIDGET(notebook), rect);
-
- if (notebook->flag == RTGUI_NOTEBOOK_NOTAB) return;
- else if (notebook->flag == RTGUI_NOTEBOOK_TOP)
- rect->y1 = rect->y1 + 25;
- else if (notebook->flag == RTGUI_NOTEBOOK_BOTTOM)
- rect->y2 = rect->y2 - 25;
-}
-
-static void _rtgui_notebook_get_bar_rect(rtgui_notebook_t *notebook, struct rtgui_rect* rect)
-{
- RT_ASSERT(notebook != RT_NULL);
- RT_ASSERT(rect != RT_NULL);
-
- rtgui_widget_get_rect(RTGUI_WIDGET(notebook), rect);
- if (notebook->flag == RTGUI_NOTEBOOK_NOTAB) return;
- else if (notebook->flag == RTGUI_NOTEBOOK_TOP)
- rect->y2 = rect->y1 + 25;
- else if (notebook->flag == RTGUI_NOTEBOOK_BOTTOM)
- rect->y1 = rect->y2 - 25;
-}
-
-DEFINE_CLASS_TYPE(notebook, "notebook",
- RTGUI_CONTAINER_TYPE,
- _rtgui_notebook_constructor,
- _rtgui_notebook_destructor,
- sizeof(struct rtgui_notebook));
-
-rtgui_notebook_tab_t *tabs;
-struct rtgui_notebook *_notebook;
-rtgui_notebook_t* rtgui_notebook_create(const rtgui_rect_t* rect, rt_uint8_t style)
-{
- struct rtgui_notebook* notebook;
-
- notebook = (struct rtgui_notebook*) rtgui_widget_create (RTGUI_NOTEBOOK_TYPE);
- if (notebook != RT_NULL)
- {
- notebook->flag = style;
- rtgui_widget_set_rect(RTGUI_WIDGET(notebook), rect);
- }
-
- _notebook = notebook;
- return notebook;
-}
-
-void rtgui_notebook_destroy(rtgui_notebook_t* notebook)
-{
- rtgui_widget_destroy(RTGUI_WIDGET(notebook));
-}
-
-void rtgui_notebook_add(rtgui_notebook_t* notebook, const char* label, rtgui_widget_t* child)
-{
- rtgui_rect_t rect;
- RT_ASSERT(notebook != RT_NULL);
-
- notebook->count += 1;
- notebook->childs = (struct rtgui_notebook_tab*) rtgui_realloc(notebook->childs,
- sizeof(struct rtgui_notebook_tab) * notebook->count);
-
- notebook->childs[notebook->count - 1].title = rt_strdup(label);
- notebook->childs[notebook->count - 1].widget = child;
-
- tabs = notebook->childs;
-
- /* set parent */
- rtgui_widget_set_parent(child, RTGUI_WIDGET(notebook));
-
- _rtgui_notebook_get_page_rect(notebook, &rect);
- rtgui_widget_rect_to_device(RTGUI_WIDGET(notebook), &rect);
- rtgui_widget_set_rect(child, &rect);
-}
-
-void rtgui_notebook_remove(rtgui_notebook_t* notebook, rt_uint16_t index)
-{
- struct rtgui_notebook_tab tab;
- RT_ASSERT(notebook != RT_NULL);
-
- if (index < notebook->count)
- {
- if (notebook->count == 1)
- {
- tab = notebook->childs[0];
- rtgui_free(notebook->childs);
- notebook->childs = RT_NULL;
- notebook->count = 0;
- }
- else
- {
- tab = notebook->childs[index];
- for (;index < notebook->count - 1; index ++)
- {
- notebook->childs[index] = notebook->childs[index + 1];
- }
-
- notebook->count -= 1;
- notebook->childs = (struct rtgui_notebook_tab*) rtgui_realloc(notebook->childs,
- sizeof(struct rtgui_notebook_tab) * notebook->count);
- }
-
- rtgui_widget_destroy(tab.widget);
- rtgui_free(tab.title);
-
- if (notebook->current == index)
- {
- /* update tab */
- if (notebook->current > notebook->count - 1)
- notebook->current = notebook->count - 1;
- rtgui_widget_update(RTGUI_WIDGET(notebook));
- }
- }
-}
-
-int rtgui_notebook_get_count(rtgui_notebook_t* notebook)
-{
- return notebook->count;
-}
-
-rtgui_widget_t* rtgui_notebook_get_current(rtgui_notebook_t* notebook)
-{
- RT_ASSERT(notebook != RT_NULL);
- if (notebook->current != RTGUI_NOT_FOUND)
- return notebook->childs[notebook->current].widget;
-
- return RT_NULL;
-}
-void rtgui_notebook_set_current(rtgui_notebook_t* notebook, rtgui_widget_t* widget)
-{
- rt_int16_t index;
-
- RT_ASSERT(notebook != RT_NULL);
-
- for (index = 0; index < notebook->count; index ++)
- {
- if (widget == notebook->childs[index].widget)
- {
- rtgui_notebook_set_current_by_index(notebook, index);
- return;
- }
- }
-}
-
-void rtgui_notebook_set_current_by_index(rtgui_notebook_t* notebook, rt_uint16_t index)
-{
- RT_ASSERT(notebook != RT_NULL);
-
- if ((index < notebook->count) && (notebook->current != index))
- {
- if (notebook->current != RTGUI_NOT_FOUND)
- rtgui_widget_hide(notebook->childs[notebook->current].widget);
-
- notebook->current = index;
- rtgui_widget_show(notebook->childs[notebook->current].widget);
- rtgui_widget_update(notebook->childs[notebook->current].widget);
- }
-}
-
-rtgui_widget_t* rtgui_notebook_get_index(rtgui_notebook_t* notebook, rt_uint16_t index)
-{
- RT_ASSERT(notebook != RT_NULL);
- if (index < notebook->count)
- return notebook->childs[index].widget;
-
- return RT_NULL;
-}
-
-rt_bool_t rtgui_notebook_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
-{
- struct rtgui_notebook* notebook;
-
- notebook = RTGUI_NOTEBOOK(widget);
- if (event->type == RTGUI_EVENT_PAINT)
- {
- _rtgui_notebook_ondraw(notebook);
- }
- else if (event->type == RTGUI_EVENT_MOUSE_BUTTON)
- {
- _rtgui_notebook_onmouse(notebook, (struct rtgui_event_mouse*)event);
- }
- else if (event->type == RTGUI_EVENT_KBD)
- {
- if (notebook->current != RTGUI_NOT_FOUND)
- {
- if (notebook->childs[notebook->current].widget->event_handler != RT_NULL)
- return notebook->childs[notebook->current].widget->event_handler(notebook->childs[notebook->current].widget,
- event);
- }
- }
- else
- {
- /* use parent event handler */
- return rtgui_widget_event_handler(widget, event);
- }
-
- return RT_FALSE;
-}
+#include <rtgui/dc.h> +#include <rtgui/rtgui.h> +#include <rtgui/rtgui_system.h> +#include <rtgui/widgets/notebook.h> + +#define RTGUI_NOTEBOOK_TAB_WIDTH 80 + +struct rtgui_notebook_tab +{ + struct rtgui_widget *widget; + char *title; +}; + +static void _rtgui_notebook_get_bar_rect(struct rtgui_notebook *notebook, struct rtgui_rect* rect); +static void _rtgui_notebook_get_page_rect(struct rtgui_notebook *notebook, struct rtgui_rect* rect); + +static void _rtgui_notebook_constructor(struct rtgui_notebook *notebook) +{ + notebook->flag = 0; + notebook->childs = RT_NULL; + notebook->count = 0; + notebook->current = 0; + + RTGUI_WIDGET(notebook)->gc.textalign = RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL; + rtgui_object_set_event_handler(RTGUI_OBJECT(notebook), rtgui_notebook_event_handler); +} + +static void _rtgui_notebook_destructor(struct rtgui_notebook *notebook) +{ + int index; + + if (notebook->childs != RT_NULL) + { + for (index = 0; index < notebook->count; index ++) + { + rtgui_widget_destroy(notebook->childs[index].widget); + rt_free(notebook->childs[index].title); + } + + rtgui_free(notebook->childs); + } +} + +DEFINE_CLASS_TYPE(notebook, "notebook", + RTGUI_WIDGET_TYPE, + _rtgui_notebook_constructor, + _rtgui_notebook_destructor, + sizeof(struct rtgui_notebook)); + +/* Draw tab bars of @param notebook. @param dc should be initialized and + * finished outside this function. Don't pass @param notebook or @param dc as + * RT_NULL, it should be checked outside. + */ +static void _rtgui_notebook_draw_bar(struct rtgui_notebook *notebook, + struct rtgui_dc *dc) +{ + struct rtgui_rect rect; + int index; + + RT_ASSERT((notebook != RT_NULL) && (dc != RT_NULL)); + + if (notebook->flag & RTGUI_NOTEBOOK_NOTAB) + return; + + _rtgui_notebook_get_bar_rect(notebook, &rect); + rtgui_dc_fill_rect(dc, &rect); + + rect.x2 = rect.x1 + RTGUI_NOTEBOOK_TAB_WIDTH; + /* draw tab bar */ + for (index = 0; index < notebook->count; index++) + { + if (notebook->current == index) + rtgui_dc_draw_border(dc, &rect, RTGUI_BORDER_SUNKEN); + else + rtgui_dc_draw_border(dc, &rect, RTGUI_BORDER_BOX); + + rtgui_dc_draw_text(dc, notebook->childs[index].title, &rect); + rect.x1 += RTGUI_NOTEBOOK_TAB_WIDTH; + rect.x2 += RTGUI_NOTEBOOK_TAB_WIDTH; + } + +} + +static void _rtgui_notebook_ondraw(struct rtgui_notebook *notebook) +{ + struct rtgui_dc* dc; + + dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(notebook)); + if (dc == RT_NULL) return; + + if (notebook->count == 0) + { + rtgui_rect_t rect; + rtgui_widget_get_rect(RTGUI_WIDGET(notebook), &rect); + rtgui_dc_fill_rect(dc, &rect); + } + else + { + if (notebook->current == RTGUI_NOT_FOUND) + notebook->current = 0; + + _rtgui_notebook_draw_bar(notebook, dc); + + /* draw current tab */ + rtgui_widget_update(notebook->childs[notebook->current].widget); + } + rtgui_dc_end_drawing(dc); +} + +static void _rtgui_notebook_onmouse(struct rtgui_notebook *notebook, struct rtgui_event_mouse* emouse) +{ + rtgui_rect_t rect; + + /* handle notebook bar */ + _rtgui_notebook_get_bar_rect(notebook, &rect); + rtgui_widget_rect_to_device(RTGUI_WIDGET(notebook), &rect); + if (rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK) + { + int index; + struct rtgui_dc* dc; + + index = (emouse->x - rect.x1) / RTGUI_NOTEBOOK_TAB_WIDTH; + if (index < notebook->count && index != notebook->current) + { + /* update tab bar */ + dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(notebook)); + if (dc == RT_NULL) return; + + rtgui_notebook_set_current_by_index(notebook, index); + + _rtgui_notebook_draw_bar(notebook, dc); + + rtgui_dc_end_drawing(dc); + } + } + else + { + /* handle on page */ + if (RTGUI_OBJECT(notebook->childs[notebook->current].widget)->event_handler != RT_NULL) + RTGUI_OBJECT(notebook->childs[notebook->current].widget)->event_handler( + RTGUI_OBJECT(notebook->childs[notebook->current].widget), + &(emouse->parent)); + } +} + +static void _rtgui_notebook_get_page_rect(struct rtgui_notebook *notebook, struct rtgui_rect* rect) +{ + RT_ASSERT(notebook != RT_NULL); + RT_ASSERT(rect != RT_NULL); + + rtgui_widget_get_rect(RTGUI_WIDGET(notebook), rect); + + if (notebook->flag == RTGUI_NOTEBOOK_NOTAB) + return; + else if (notebook->flag == RTGUI_NOTEBOOK_TOP) + rect->y1 = rect->y1 + 25; + else if (notebook->flag == RTGUI_NOTEBOOK_BOTTOM) + rect->y2 = rect->y2 - 25; +} + +static void _rtgui_notebook_get_bar_rect(struct rtgui_notebook *notebook, struct rtgui_rect* rect) +{ + RT_ASSERT(notebook != RT_NULL); + RT_ASSERT(rect != RT_NULL); + + rtgui_widget_get_rect(RTGUI_WIDGET(notebook), rect); + if (notebook->flag == RTGUI_NOTEBOOK_NOTAB) + { + rect->x1 = rect->y1 = rect->x2 = rect->y2 = 0; + } + else if (notebook->flag == RTGUI_NOTEBOOK_TOP) + rect->y2 = rect->y1 + 25; + else if (notebook->flag == RTGUI_NOTEBOOK_BOTTOM) + rect->y1 = rect->y2 - 25; +} + +struct rtgui_notebook* rtgui_notebook_create(const rtgui_rect_t* rect, rt_uint8_t style) +{ + struct rtgui_notebook* notebook; + + notebook = (struct rtgui_notebook*) rtgui_widget_create(RTGUI_NOTEBOOK_TYPE); + if (notebook != RT_NULL) + { + notebook->flag = style; + rtgui_widget_set_rect(RTGUI_WIDGET(notebook), rect); + } + + return notebook; +} + +void rtgui_notebook_destroy(struct rtgui_notebook* notebook) +{ + rtgui_widget_destroy(RTGUI_WIDGET(notebook)); +} + +void rtgui_notebook_add(struct rtgui_notebook* notebook, const char* label, struct rtgui_widget* child) +{ + rtgui_rect_t rect; + RT_ASSERT(notebook != RT_NULL); + + notebook->count += 1; + notebook->childs = (struct rtgui_notebook_tab*) + rtgui_realloc(notebook->childs, + sizeof(struct rtgui_notebook_tab) * notebook->count); + + notebook->childs[notebook->count - 1].title = rt_strdup(label); + notebook->childs[notebook->count - 1].widget = child; + + /* set parent */ + rtgui_widget_set_parent(child, RTGUI_WIDGET(notebook)); + + _rtgui_notebook_get_page_rect(notebook, &rect); + rtgui_widget_rect_to_device(RTGUI_WIDGET(notebook), &rect); + rtgui_widget_set_rect(child, &rect); + + if (notebook->count - 1 != notebook->current) + rtgui_widget_hide(child); +} + +void rtgui_notebook_remove(struct rtgui_notebook* notebook, rt_uint16_t index) +{ + struct rtgui_notebook_tab tab; + RT_ASSERT(notebook != RT_NULL); + + if (index < notebook->count) + { + if (notebook->count == 1) + { + tab = notebook->childs[0]; + rtgui_free(notebook->childs); + notebook->childs = RT_NULL; + notebook->count = 0; + } + else + { + tab = notebook->childs[index]; + for (;index < notebook->count - 1; index ++) + { + notebook->childs[index] = notebook->childs[index + 1]; + } + + notebook->count -= 1; + notebook->childs = (struct rtgui_notebook_tab*) rtgui_realloc(notebook->childs, + sizeof(struct rtgui_notebook_tab) * notebook->count); + } + + // FIXME: do we really want to destroy it? + rtgui_widget_destroy(tab.widget); + rtgui_free(tab.title); + + if (notebook->current == index) + { + /* update tab */ + if (notebook->current > notebook->count - 1) + notebook->current = notebook->count - 1; + rtgui_widget_update(RTGUI_WIDGET(notebook)); + } + } +} + +int rtgui_notebook_get_count(struct rtgui_notebook* notebook) +{ + RT_ASSERT(notebook != RT_NULL); + return notebook->count; +} + +struct rtgui_widget* rtgui_notebook_get_current(struct rtgui_notebook* notebook) +{ + RT_ASSERT(notebook != RT_NULL); + if (notebook->current != RTGUI_NOT_FOUND) + return notebook->childs[notebook->current].widget; + + return RT_NULL; +} + +rt_int16_t rtgui_notebook_get_current_index(struct rtgui_notebook* notebook) +{ + RT_ASSERT(notebook != RT_NULL); + return notebook->current; +} + +void rtgui_notebook_set_current(struct rtgui_notebook* notebook, struct rtgui_widget* widget) +{ + rt_int16_t index; + + RT_ASSERT(notebook != RT_NULL); + + for (index = 0; index < notebook->count; index ++) + { + if (widget == notebook->childs[index].widget) + { + rtgui_notebook_set_current_by_index(notebook, index); + return; + } + } +} + +void rtgui_notebook_set_current_by_index(struct rtgui_notebook* notebook, rt_uint16_t index) +{ + RT_ASSERT(notebook != RT_NULL); + + if ((index < notebook->count) && (notebook->current != index)) + { + if (notebook->current != RTGUI_NOT_FOUND) + rtgui_widget_hide(notebook->childs[notebook->current].widget); + + notebook->current = index; + rtgui_widget_show(notebook->childs[notebook->current].widget); + rtgui_widget_update(notebook->childs[notebook->current].widget); + } +} + +struct rtgui_widget* rtgui_notebook_get_widget_at(struct rtgui_notebook* notebook, rt_uint16_t index) +{ + RT_ASSERT(notebook != RT_NULL); + if (index < notebook->count) + return notebook->childs[index].widget; + + return RT_NULL; +} + +rt_bool_t rtgui_notebook_event_handler(struct rtgui_object* object, struct rtgui_event* event) +{ + struct rtgui_notebook* notebook; + + RT_ASSERT(object != RT_NULL); + RT_ASSERT(event != RT_NULL); + + notebook = RTGUI_NOTEBOOK(object); + + switch (event->type) + { + case RTGUI_EVENT_PAINT: + _rtgui_notebook_ondraw(notebook); + break; + case RTGUI_EVENT_MOUSE_BUTTON: + _rtgui_notebook_onmouse(notebook, (struct rtgui_event_mouse*)event); + break; + case RTGUI_EVENT_KBD: + if (notebook->current != RTGUI_NOT_FOUND) + { + if (RTGUI_OBJECT(notebook->childs[notebook->current].widget + )->event_handler != RT_NULL) + return RTGUI_OBJECT(notebook->childs[notebook->current].widget + )->event_handler( + RTGUI_OBJECT(notebook->childs[notebook->current].widget), + event); + } + break; + default: + /* use parent event handler */ + return rtgui_widget_event_handler(object, event); + } + + return RT_FALSE; +} diff --git a/components/rtgui/widgets/progressbar.c b/components/rtgui/widgets/progressbar.c index 84e2adea1d..c42f2a3688 100644 --- a/components/rtgui/widgets/progressbar.c +++ b/components/rtgui/widgets/progressbar.c @@ -1,101 +1,104 @@ -#include <rtgui/dc.h>
-#include <rtgui/rtgui_theme.h>
-#include <rtgui/widgets/progressbar.h>
-
-#define RTGUI_PROGRESSBAR_DEFAULT_RANGE 100
-
-static void _rtgui_progressbar_constructor(rtgui_progressbar_t *bar)
-{
- rtgui_rect_t rect = {0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT};
-
- rtgui_widget_set_event_handler(RTGUI_WIDGET(bar), rtgui_progressbar_event_handler);
- rtgui_widget_set_rect(RTGUI_WIDGET(bar), &rect);
-
- bar->orient = RTGUI_HORIZONTAL;
- bar->range = RTGUI_PROGRESSBAR_DEFAULT_RANGE;
- bar->position = 0;
-
- /* set gc */
- RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(bar)) = RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL;
-}
-
-DEFINE_CLASS_TYPE(progressbar, "progressbar",
- RTGUI_WIDGET_TYPE,
- _rtgui_progressbar_constructor,
- RT_NULL,
- sizeof(struct rtgui_progressbar));
-
-rt_bool_t rtgui_progressbar_event_handler(struct rtgui_widget* widget,
- struct rtgui_event* event)
-{
- struct rtgui_progressbar* bar = (struct rtgui_progressbar*)widget;
-
- switch (event->type)
- {
- case RTGUI_EVENT_PAINT:
- rtgui_theme_draw_progressbar(bar);
- break;
- }
-
- return RT_FALSE;
-}
-
-struct rtgui_progressbar* rtgui_progressbar_create(int orientation, int range,
- rtgui_rect_t* r)
-{
- struct rtgui_progressbar* bar;
-
- bar = (struct rtgui_progressbar*) rtgui_widget_create (RTGUI_PROGRESSBAR_TYPE);
- if (bar != RT_NULL)
- {
- if (r != RT_NULL)
- rtgui_widget_set_rect(RTGUI_WIDGET(bar), r);
-
- bar->orient = orientation;
- bar->range = range;
- }
-
- return bar;
-}
-
-void rtgui_progressbar_destroy(struct rtgui_progressbar* bar)
-{
- rtgui_widget_destroy(RTGUI_WIDGET(bar));
-}
-
-void rtgui_progressbar_set_value(struct rtgui_progressbar *bar, int value)
-{
- RT_ASSERT(bar != RT_NULL);
-
- if (!RTGUI_WIDGET_IS_ENABLE(RTGUI_WIDGET(bar))) return;
-
- bar->position = value;
-
- rtgui_theme_draw_progressbar(bar);
- return;
-}
-
-int rtgui_progressbar_get_value(struct rtgui_progressbar *bar)
-{
- RT_ASSERT(bar != RT_NULL);
-
- return bar->position;
-}
-
-void rtgui_progressbar_set_range(struct rtgui_progressbar *bar, int range)
-{
- RT_ASSERT(bar != RT_NULL);
-
- bar->range = range;
-
- rtgui_theme_draw_progressbar(bar);
- return;
-}
-
-int rtgui_progressbar_get_range(struct rtgui_progressbar *bar)
-{
- RT_ASSERT(bar != RT_NULL);
-
- return bar->range;
-}
-
+#include <rtgui/dc.h> +#include <rtgui/rtgui_theme.h> +#include <rtgui/widgets/progressbar.h> + +#define RTGUI_PROGRESSBAR_DEFAULT_RANGE 100 + +static void _rtgui_progressbar_constructor(rtgui_progressbar_t *bar) +{ + rtgui_rect_t rect = {0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT}; + + rtgui_object_set_event_handler(RTGUI_OBJECT(bar), rtgui_progressbar_event_handler); + rtgui_widget_set_rect(RTGUI_WIDGET(bar), &rect); + + bar->orient = RTGUI_HORIZONTAL; + bar->range = RTGUI_PROGRESSBAR_DEFAULT_RANGE; + bar->position = 0; + + /* set gc */ + RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(bar)) = RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL; +} + +DEFINE_CLASS_TYPE(progressbar, "progressbar", + RTGUI_WIDGET_TYPE, + _rtgui_progressbar_constructor, + RT_NULL, + sizeof(struct rtgui_progressbar)); + +rt_bool_t rtgui_progressbar_event_handler(struct rtgui_object* object, + struct rtgui_event* event) +{ + struct rtgui_progressbar* bar; + RTGUI_WIDGET_EVENT_HANDLER_PREPARE + + bar = RTGUI_PROGRESSBAR(object); + + switch (event->type) + { + case RTGUI_EVENT_PAINT: + rtgui_theme_draw_progressbar(bar); + break; + } + + return RT_FALSE; +} + +struct rtgui_progressbar* rtgui_progressbar_create(int orientation, int range, + rtgui_rect_t* r) +{ + struct rtgui_progressbar* bar; + + bar = (struct rtgui_progressbar*) rtgui_widget_create (RTGUI_PROGRESSBAR_TYPE); + if (bar != RT_NULL) + { + if (r != RT_NULL) + rtgui_widget_set_rect(RTGUI_WIDGET(bar), r); + + bar->orient = orientation; + bar->range = range; + } + + return bar; +} + +void rtgui_progressbar_destroy(struct rtgui_progressbar* bar) +{ + rtgui_widget_destroy(RTGUI_WIDGET(bar)); +} + +void rtgui_progressbar_set_value(struct rtgui_progressbar *bar, int value) +{ + RT_ASSERT(bar != RT_NULL); + + if (!RTGUI_WIDGET_IS_ENABLE(RTGUI_WIDGET(bar))) return; + + bar->position = value; + + rtgui_theme_draw_progressbar(bar); + return; +} + +int rtgui_progressbar_get_value(struct rtgui_progressbar *bar) +{ + RT_ASSERT(bar != RT_NULL); + + return bar->position; +} + +void rtgui_progressbar_set_range(struct rtgui_progressbar *bar, int range) +{ + RT_ASSERT(bar != RT_NULL); + + bar->range = range; + + rtgui_theme_draw_progressbar(bar); + return; +} + +int rtgui_progressbar_get_range(struct rtgui_progressbar *bar) +{ + RT_ASSERT(bar != RT_NULL); + + return bar->range; +} + diff --git a/components/rtgui/widgets/radiobox.c b/components/rtgui/widgets/radiobox.c index a4f1f7de94..b886c584c4 100644 --- a/components/rtgui/widgets/radiobox.c +++ b/components/rtgui/widgets/radiobox.c @@ -1,244 +1,246 @@ -#include <rtgui/dc.h>
-#include <rtgui/rtgui_theme.h>
-#include <rtgui/widgets/radiobox.h>
-
-#define RTGUI_RADIOBOX_DEFAULT_WIDTH 100
-#define RTGUI_RADIOBOX_DEFAULT_HEIGHT 20
-
-static void _rtgui_radiobox_constructor(rtgui_radiobox_t *radiobox)
-{
- rtgui_rect_t rect = {0, 0, RTGUI_RADIOBOX_DEFAULT_WIDTH, RTGUI_RADIOBOX_DEFAULT_HEIGHT};
-
- /* init widget and set event handler */
- RTGUI_WIDGET(radiobox)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
- RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(radiobox)) = RTGUI_ALIGN_LEFT | RTGUI_ALIGN_CENTER_VERTICAL;
- rtgui_widget_set_rect(RTGUI_WIDGET(radiobox), &rect);
- rtgui_widget_set_event_handler(RTGUI_WIDGET(radiobox), rtgui_radiobox_event_handler);
-
- /* set proper of control */
- radiobox->items = RT_NULL;
- radiobox->item_count = 0;
- radiobox->item_selection = -1;
- radiobox->orient = RTGUI_HORIZONTAL;
-}
-
-DEFINE_CLASS_TYPE(radiobox, "radiobox",
- RTGUI_WIDGET_TYPE,
- _rtgui_radiobox_constructor,
- RT_NULL,
- sizeof(struct rtgui_radiobox));
-
-static void rtgui_radiobox_onmouse(struct rtgui_radiobox* radiobox, struct rtgui_event_mouse* event)
-{
- RT_ASSERT(radiobox != RT_NULL);
- RT_ASSERT(event != RT_NULL);
-
- /* widget is hide, return */
- if (RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(radiobox)) ||
- !RTGUI_WIDGET_IS_ENABLE(RTGUI_WIDGET(radiobox))) return;
-
- if (event->button & RTGUI_MOUSE_BUTTON_DOWN &&
- event->button & RTGUI_MOUSE_BUTTON_LEFT)
- {
- int bord_size;
- struct rtgui_rect rect;
-
- /* focus widgets */
- rtgui_widget_focus(RTGUI_WIDGET(radiobox));
-
- /* get widget physical rect */
- rtgui_widget_get_rect(RTGUI_WIDGET(radiobox), &rect);
- rtgui_widget_rect_to_device(RTGUI_WIDGET(radiobox), &rect);
-
- /* get board size */
- if (radiobox->orient == RTGUI_VERTICAL)
- bord_size = radiobox->item_size;
- else
- {
- struct rtgui_rect bord_rect;
-
- rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(radiobox)), "H", &bord_rect);
- bord_size = rtgui_rect_height(bord_rect);
- }
- rtgui_rect_inflate(&rect, - bord_size);
- if (rtgui_rect_contains_point(&rect, event->x, event->y) != RT_EOK) return;
-
- if (radiobox->orient == RTGUI_VERTICAL)
- {
- int delta_y = event->y - rect.y1;
- rtgui_radiobox_set_selection(radiobox, delta_y / radiobox->item_size);
- }
- else
- {
- int delta_x = event->x - rect.x1;
- rtgui_radiobox_set_selection(radiobox, delta_x / radiobox->item_size);
- }
- }
-}
-
-rt_bool_t rtgui_radiobox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
-{
- struct rtgui_radiobox* radiobox = (struct rtgui_radiobox*)widget;
-
- switch (event->type)
- {
- case RTGUI_EVENT_PAINT:
-#ifndef RTGUI_USING_SMALL_SIZE
- if (widget->on_draw != RT_NULL) widget->on_draw(widget, event);
- else
-#endif
- {
- rtgui_theme_draw_radiobox(radiobox);
- }
-
- break;
-
- case RTGUI_EVENT_KBD:
- if (RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(radiobox))) return RT_FALSE;
-
-#ifndef RTGUI_USING_SMALL_SIZE
- if (widget->on_key != RT_NULL) widget->on_key(widget, event);
- else
-#endif
- {
- struct rtgui_event_kbd *e = (struct rtgui_event_kbd*)event;
-
- /* set focused */
- rtgui_widget_focus(RTGUI_WIDGET(radiobox));
- if (!(RTGUI_KBD_IS_UP(e))) return RT_FALSE;
-
- if (radiobox->orient == RTGUI_VERTICAL)
- {
- if (e->key == RTGUIK_UP)
- {
- if (radiobox->item_selection > 0)
- rtgui_radiobox_set_selection(radiobox, radiobox->item_selection - 1);
- }
- else if (e->key == RTGUIK_DOWN)
- {
- if (radiobox->item_selection < radiobox->item_count - 1)
- rtgui_radiobox_set_selection(radiobox, radiobox->item_selection + 1);
- }
- }
- else
- {
- if (e->key == RTGUIK_LEFT)
- {
- if (radiobox->item_selection > 0)
- rtgui_radiobox_set_selection(radiobox, radiobox->item_selection - 1);
- }
- else if (e->key == RTGUIK_RIGHT)
- {
- if (radiobox->item_selection < radiobox->item_count - 1)
- rtgui_radiobox_set_selection(radiobox, radiobox->item_selection + 1);
- }
- }
- }
- break;
-
- case RTGUI_EVENT_MOUSE_BUTTON:
-#ifndef RTGUI_USING_SMALL_SIZE
- if (widget->on_mouseclick != RT_NULL) widget->on_mouseclick(widget, event);
- else
-#endif
- {
- rtgui_radiobox_onmouse(radiobox, (struct rtgui_event_mouse*)event);
- }
- break;
- }
-
- return RT_FALSE;
-}
-
-struct rtgui_radiobox* rtgui_radiobox_create(const char* label, int orient, char** radio_items, int number)
-{
- struct rtgui_radiobox* radiobox;
-
- radiobox = (struct rtgui_radiobox*) rtgui_widget_create (RTGUI_RADIOBOX_TYPE);
- if (radiobox != RT_NULL)
- {
- rt_uint8_t board_size;
- struct rtgui_rect rect;
-
- radiobox->items = radio_items;
- radiobox->item_count = number;
- radiobox->item_selection = -1;
- radiobox->text = rt_strdup(label);
-
- /* set proper of control */
- rtgui_radiobox_set_orientation(radiobox, orient);
- rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(radiobox)), "H", &rect);
- board_size = rtgui_rect_height(rect);
-
- if (orient == RTGUI_VERTICAL)
- {
- radiobox->item_size = board_size;
- }
- else
- {
- int index;
- struct rtgui_font* font;
- struct rtgui_rect rect;
-
- /* set init item size */
- radiobox->item_size = 0;
-
- font = RTGUI_WIDGET_FONT(RTGUI_WIDGET(radiobox));
- for (index = 0; index < number; index ++)
- {
- rtgui_font_get_metrics(font, radio_items[index], &rect);
- if ( (board_size + 3 + rtgui_rect_width(rect)) > radiobox->item_size)
- radiobox->item_size = board_size + 3 + rtgui_rect_width(rect);
- }
- }
-
- if (radiobox->item_size < RADIO_BOX_H + 2)
- radiobox->item_size = RADIO_BOX_H + 2;
- }
-
- return radiobox;
-}
-
-void rtgui_radiobox_set_orientation(struct rtgui_radiobox* radiobox, int orientation)
-{
- RT_ASSERT(radiobox != RT_NULL);
-
- /* set orientation */
- radiobox->orient = orientation;
-#ifndef RTGUI_USING_SMALL_SIZE
- if (radiobox->orient == RTGUI_HORIZONTAL)
- {
- /* HORIZONTAL */
- rtgui_widget_set_miniheight(RTGUI_WIDGET(radiobox), RTGUI_RADIOBOX_DEFAULT_HEIGHT);
- rtgui_widget_set_miniwidth(RTGUI_WIDGET(radiobox), RTGUI_RADIOBOX_DEFAULT_WIDTH);
- }
- else
- {
- /* VERTICAL */
- rtgui_widget_set_miniwidth(RTGUI_WIDGET(radiobox), RTGUI_RADIOBOX_DEFAULT_HEIGHT);
- rtgui_widget_set_miniheight(RTGUI_WIDGET(radiobox), RTGUI_RADIOBOX_DEFAULT_WIDTH);
- }
-#endif
-}
-
-void rtgui_radiobox_set_selection(struct rtgui_radiobox* radiobox, int selection)
-{
- rt_uint16_t old_item;
-
- if (selection == radiobox->item_selection) return;
-
- old_item = radiobox->item_selection;
- if (selection >= 0 && selection < radiobox->item_count)
- {
- radiobox->item_selection = selection;
- }
-
- /* update radiobox widget */
- rtgui_theme_draw_radiobutton(radiobox, old_item);
- rtgui_theme_draw_radiobutton(radiobox, radiobox->item_selection);
-}
-
-int rtgui_radiobox_get_selection(struct rtgui_radiobox* radiobox)
-{
- return radiobox->item_selection;
-}
+#include <rtgui/dc.h> +#include <rtgui/rtgui_theme.h> +#include <rtgui/widgets/radiobox.h> + +#define RTGUI_RADIOBOX_DEFAULT_WIDTH 100 +#define RTGUI_RADIOBOX_DEFAULT_HEIGHT 20 + +static void _rtgui_radiobox_constructor(rtgui_radiobox_t *radiobox) +{ + rtgui_rect_t rect = {0, 0, RTGUI_RADIOBOX_DEFAULT_WIDTH, RTGUI_RADIOBOX_DEFAULT_HEIGHT}; + + /* init widget and set event handler */ + RTGUI_WIDGET(radiobox)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE; + RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(radiobox)) = RTGUI_ALIGN_LEFT | RTGUI_ALIGN_CENTER_VERTICAL; + rtgui_widget_set_rect(RTGUI_WIDGET(radiobox), &rect); + rtgui_object_set_event_handler(RTGUI_OBJECT(radiobox), rtgui_radiobox_event_handler); + + /* set proper of control */ + radiobox->items = RT_NULL; + radiobox->item_count = 0; + radiobox->item_selection = -1; + radiobox->orient = RTGUI_HORIZONTAL; +} + +DEFINE_CLASS_TYPE(radiobox, "radiobox", + RTGUI_WIDGET_TYPE, + _rtgui_radiobox_constructor, + RT_NULL, + sizeof(struct rtgui_radiobox)); + +static void rtgui_radiobox_onmouse(struct rtgui_radiobox* radiobox, struct rtgui_event_mouse* event) +{ + RT_ASSERT(radiobox != RT_NULL); + RT_ASSERT(event != RT_NULL); + + /* widget is hide, return */ + if (RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(radiobox)) || + !RTGUI_WIDGET_IS_ENABLE(RTGUI_WIDGET(radiobox))) return; + + if (event->button & RTGUI_MOUSE_BUTTON_DOWN && + event->button & RTGUI_MOUSE_BUTTON_LEFT) + { + int bord_size; + struct rtgui_rect rect; + + /* focus widgets */ + rtgui_widget_focus(RTGUI_WIDGET(radiobox)); + + /* get widget physical rect */ + rtgui_widget_get_rect(RTGUI_WIDGET(radiobox), &rect); + rtgui_widget_rect_to_device(RTGUI_WIDGET(radiobox), &rect); + + /* get board size */ + if (radiobox->orient == RTGUI_VERTICAL) + bord_size = radiobox->item_size; + else + { + struct rtgui_rect bord_rect; + + rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(radiobox)), "H", &bord_rect); + bord_size = rtgui_rect_height(bord_rect); + } + rtgui_rect_inflate(&rect, - bord_size); + if (rtgui_rect_contains_point(&rect, event->x, event->y) != RT_EOK) return; + + if (radiobox->orient == RTGUI_VERTICAL) + { + int delta_y = event->y - rect.y1; + rtgui_radiobox_set_selection(radiobox, delta_y / radiobox->item_size); + } + else + { + int delta_x = event->x - rect.x1; + rtgui_radiobox_set_selection(radiobox, delta_x / radiobox->item_size); + } + } +} + +rt_bool_t rtgui_radiobox_event_handler(struct rtgui_object* object, struct rtgui_event* event) +{ + struct rtgui_radiobox* radiobox; + RTGUI_WIDGET_EVENT_HANDLER_PREPARE + + radiobox = RTGUI_RADIOBOX(object); + switch (event->type) + { + case RTGUI_EVENT_PAINT: +#ifndef RTGUI_USING_SMALL_SIZE + if (widget->on_draw != RT_NULL) widget->on_draw(widget, event); + else +#endif + { + rtgui_theme_draw_radiobox(radiobox); + } + + break; + + case RTGUI_EVENT_KBD: + if (RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(radiobox))) return RT_FALSE; + +#ifndef RTGUI_USING_SMALL_SIZE + if (widget->on_key != RT_NULL) widget->on_key(widget, event); + else +#endif + { + struct rtgui_event_kbd *e = (struct rtgui_event_kbd*)event; + + /* set focused */ + rtgui_widget_focus(RTGUI_WIDGET(radiobox)); + if (!(RTGUI_KBD_IS_UP(e))) return RT_FALSE; + + if (radiobox->orient == RTGUI_VERTICAL) + { + if (e->key == RTGUIK_UP) + { + if (radiobox->item_selection > 0) + rtgui_radiobox_set_selection(radiobox, radiobox->item_selection - 1); + } + else if (e->key == RTGUIK_DOWN) + { + if (radiobox->item_selection < radiobox->item_count - 1) + rtgui_radiobox_set_selection(radiobox, radiobox->item_selection + 1); + } + } + else + { + if (e->key == RTGUIK_LEFT) + { + if (radiobox->item_selection > 0) + rtgui_radiobox_set_selection(radiobox, radiobox->item_selection - 1); + } + else if (e->key == RTGUIK_RIGHT) + { + if (radiobox->item_selection < radiobox->item_count - 1) + rtgui_radiobox_set_selection(radiobox, radiobox->item_selection + 1); + } + } + } + break; + + case RTGUI_EVENT_MOUSE_BUTTON: +#ifndef RTGUI_USING_SMALL_SIZE + if (widget->on_mouseclick != RT_NULL) widget->on_mouseclick(widget, event); + else +#endif + { + rtgui_radiobox_onmouse(radiobox, (struct rtgui_event_mouse*)event); + } + break; + } + + return RT_FALSE; +} + +struct rtgui_radiobox* rtgui_radiobox_create(const char* label, int orient, char** radio_items, int number) +{ + struct rtgui_radiobox* radiobox; + + radiobox = (struct rtgui_radiobox*) rtgui_widget_create (RTGUI_RADIOBOX_TYPE); + if (radiobox != RT_NULL) + { + rt_uint8_t board_size; + struct rtgui_rect rect; + + radiobox->items = radio_items; + radiobox->item_count = number; + radiobox->item_selection = -1; + radiobox->text = rt_strdup(label); + + /* set proper of control */ + rtgui_radiobox_set_orientation(radiobox, orient); + rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(radiobox)), "H", &rect); + board_size = rtgui_rect_height(rect); + + if (orient == RTGUI_VERTICAL) + { + radiobox->item_size = board_size; + } + else + { + int index; + struct rtgui_font* font; + struct rtgui_rect rect; + + /* set init item size */ + radiobox->item_size = 0; + + font = RTGUI_WIDGET_FONT(RTGUI_WIDGET(radiobox)); + for (index = 0; index < number; index ++) + { + rtgui_font_get_metrics(font, radio_items[index], &rect); + if ( (board_size + 3 + rtgui_rect_width(rect)) > radiobox->item_size) + radiobox->item_size = board_size + 3 + rtgui_rect_width(rect); + } + } + + if (radiobox->item_size < RADIO_BOX_H + 2) + radiobox->item_size = RADIO_BOX_H + 2; + } + + return radiobox; +} + +void rtgui_radiobox_set_orientation(struct rtgui_radiobox* radiobox, int orientation) +{ + RT_ASSERT(radiobox != RT_NULL); + + /* set orientation */ + radiobox->orient = orientation; +#ifndef RTGUI_USING_SMALL_SIZE + if (radiobox->orient == RTGUI_HORIZONTAL) + { + /* HORIZONTAL */ + rtgui_widget_set_miniheight(RTGUI_WIDGET(radiobox), RTGUI_RADIOBOX_DEFAULT_HEIGHT); + rtgui_widget_set_miniwidth(RTGUI_WIDGET(radiobox), RTGUI_RADIOBOX_DEFAULT_WIDTH); + } + else + { + /* VERTICAL */ + rtgui_widget_set_miniwidth(RTGUI_WIDGET(radiobox), RTGUI_RADIOBOX_DEFAULT_HEIGHT); + rtgui_widget_set_miniheight(RTGUI_WIDGET(radiobox), RTGUI_RADIOBOX_DEFAULT_WIDTH); + } +#endif +} + +void rtgui_radiobox_set_selection(struct rtgui_radiobox* radiobox, int selection) +{ + rt_uint16_t old_item; + + if (selection == radiobox->item_selection) return; + + old_item = radiobox->item_selection; + if (selection >= 0 && selection < radiobox->item_count) + { + radiobox->item_selection = selection; + } + + /* update radiobox widget */ + rtgui_theme_draw_radiobutton(radiobox, old_item); + rtgui_theme_draw_radiobutton(radiobox, radiobox->item_selection); +} + +int rtgui_radiobox_get_selection(struct rtgui_radiobox* radiobox) +{ + return radiobox->item_selection; +} diff --git a/components/rtgui/widgets/scrollbar.c b/components/rtgui/widgets/scrollbar.c index 5581ba0560..58a3017b3c 100644 --- a/components/rtgui/widgets/scrollbar.c +++ b/components/rtgui/widgets/scrollbar.c @@ -1,415 +1,419 @@ -/*
- * File : scrollbar.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2010-08-09 Bernard first version
- */
-#include <rtgui/dc.h>
-#include <rtgui/rtgui_theme.h>
-#include <rtgui/widgets/scrollbar.h>
-
-static void _rtgui_scrollbar_constructor(rtgui_scrollbar_t *bar)
-{
- struct rtgui_rect rect = {0, 0, RTGUI_DEFAULT_SB_WIDTH, RTGUI_DEFAULT_SB_HEIGHT};
-
- /* set event handler */
- rtgui_widget_set_event_handler(RTGUI_WIDGET(bar), rtgui_scrollbar_event_handler);
-
- rtgui_scrollbar_set_range(bar, 0, 100);
- rtgui_scrollbar_set_page_step(bar, 20);
- rtgui_scrollbar_set_line_step(bar, 10);
-
- bar->status = 0;
- bar->thumb_position = 0;
- bar->thumb_size = 16;
- bar->on_scroll = RT_NULL;
-
- bar->orient = RTGUI_HORIZONTAL;
- rtgui_widget_set_rect(RTGUI_WIDGET(bar), &rect);
-
- /* set gc */
- RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(bar)) = RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL;
-}
-
-rt_inline rt_uint32_t _rtgui_scrollbar_get_length(rtgui_scrollbar_t *bar)
-{
- struct rtgui_rect rect;
-
- rtgui_widget_get_rect(RTGUI_WIDGET(bar), &rect);
-
- if (bar->orient & RTGUI_VERTICAL)
- return rect.y2 - 2 * (rect.x2 - rect.x1);
-
- return rect.x2 - 2 * (rect.y2 - rect.y1);
-}
-
-rt_inline rt_uint32_t _rtgui_scrollbar_get_thumb_position(rtgui_scrollbar_t* bar)
-{
- rt_uint32_t thumb_position;
-
- /* calculate thumb position */
- thumb_position = (rtgui_scrollbar_get_value(bar) - bar->min_position) * _rtgui_scrollbar_get_length(bar) /
- (bar->max_position - bar->min_position);
-
- return thumb_position;
-}
-
-void rtgui_scrollbar_get_thumb_rect(rtgui_scrollbar_t *bar, rtgui_rect_t *rect)
-{
- struct rtgui_rect scrollbar_rect;
-
- rtgui_widget_get_rect(RTGUI_WIDGET(bar), &scrollbar_rect);
- if (bar->orient & RTGUI_VERTICAL)
- {
- rt_uint32_t btn_width = scrollbar_rect.x2 - scrollbar_rect.x1;
-
- /* vertical scroll bar */
- rect->x1 = scrollbar_rect.x1;
- rect->x2 = scrollbar_rect.x2;
- rect->y1 = scrollbar_rect.y1 + btn_width + _rtgui_scrollbar_get_thumb_position(bar);
- rect->y2 = rect->y1 + btn_width;
- }
- else
- {
- rt_uint32_t btn_height = scrollbar_rect.y2 - scrollbar_rect.y1;
-
- /* horizontal scroll bar */
- rect->x1 = scrollbar_rect.x1 + btn_height + _rtgui_scrollbar_get_thumb_position(bar);
- rect->x2 = rect->x1 + btn_height;
-
- rect->y1 = scrollbar_rect.y1;
- rect->y2 = scrollbar_rect.y2;
- }
-}
-
-DEFINE_CLASS_TYPE(scrollbar, "scrollbar",
- RTGUI_WIDGET_TYPE,
- _rtgui_scrollbar_constructor,
- RT_NULL,
- sizeof(struct rtgui_scrollbar));
-
-static void _rtgui_scrollbar_on_mouseclick(struct rtgui_widget * widget, struct rtgui_event * event)
-{
- rtgui_rect_t btn_rect, bar_rect;
- rt_uint32_t thumb_size, thumb_position;
- struct rtgui_scrollbar* bar = (struct rtgui_scrollbar*)widget;
- struct rtgui_event_mouse* mouse = (struct rtgui_event_mouse*)event;
-
- /* get the thumb size and position */
- thumb_size = bar->thumb_size * (bar->max_position - bar->min_position) / _rtgui_scrollbar_get_length(bar);
- thumb_position = _rtgui_scrollbar_get_thumb_position(bar);
-
- if (bar->orient == RTGUI_VERTICAL)
- {
- /* get up arrow button rect */
- btn_rect.x1 = widget->extent.x1;
- btn_rect.x2 = widget->extent.x2;
- btn_rect.y1 = widget->extent.y1;
- btn_rect.y2 = widget->extent.y1 + (widget->extent.x2 - widget->extent.x1);
- if (rtgui_rect_contains_point(&btn_rect, mouse->x, mouse->y) == RT_EOK)
- {
- if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) ==
- (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN))
- {
- bar->status |= SBS_UPARROW;
-
- /* line step */
- bar->thumb_position -= bar->line_step;
- if (bar->thumb_position < bar->min_position) bar->thumb_position = bar->min_position;
- }
- else if (mouse->button & RTGUI_MOUSE_BUTTON_UP)
- {
- bar->status = 0;
- }
- goto __exit;
- }
-
- /* get bar rect */
- bar_rect.x1 = widget->extent.x1;
- bar_rect.x2 = widget->extent.x2;
- bar_rect.y1 = widget->extent.y1 + (widget->extent.x2 - widget->extent.x1);
- bar_rect.y2 = widget->extent.y2 - (widget->extent.x2 - widget->extent.x1);
- if (rtgui_rect_contains_point(&bar_rect, mouse->x, mouse->y) == RT_EOK)
- {
- if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) ==
- (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN))
- {
- /* page step */
- if (mouse->y < bar_rect.y1 + thumb_position)
- {
- bar->thumb_position -= bar->page_step;
- if (bar->thumb_position < bar->min_position)
- bar->thumb_position = bar->min_position;
- }
- else if (mouse->y > thumb_position + bar->thumb_size)
- {
- bar->thumb_position += bar->page_step;
- if (bar->thumb_position > bar->max_position - thumb_size)
- bar->thumb_position = bar->max_position - thumb_size;
- }
- }
- goto __exit;
- }
-
- /* get down arrow button rect */
- btn_rect.y1 = widget->extent.y2 - (widget->extent.x2 - widget->extent.x1);
- btn_rect.y2 = widget->extent.y2;
- bar_rect.y1 = widget->extent.y1 + ((widget->extent.y2 - widget->extent.y1)/2);
- bar_rect.y2 = widget->extent.y2 - (widget->extent.x2 - widget->extent.x1);
- if (rtgui_rect_contains_point(&btn_rect, mouse->x, mouse->y) == RT_EOK)
- {
- if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) ==
- (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN))
- {
- bar->status |= SBS_DOWNARROW;
-
- /* line step */
- bar->thumb_position += bar->line_step;
- if (bar->thumb_position > bar->max_position - thumb_size)
- bar->thumb_position = bar->max_position - thumb_size;
- }
- else if (mouse->button & RTGUI_MOUSE_BUTTON_UP)
- bar->status = 0;
- }
- }
- else
- {
- /* get left arrow button rect */
- btn_rect.x1 = widget->extent.x1;
- btn_rect.x2 = widget->extent.x1 + (widget->extent.y2 - widget->extent.y1);
- btn_rect.y1 = widget->extent.y1;
- btn_rect.y2 = widget->extent.y2;
- if (rtgui_rect_contains_point(&btn_rect, mouse->x, mouse->y) == RT_EOK)
- {
- if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) ==
- (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN))
- {
- bar->status |= SBS_LEFTARROW;
-
- /* line step */
- bar->thumb_position -= bar->line_step;
- if (bar->thumb_position < bar->min_position) bar->thumb_position = bar->min_position;
- }
- else if (mouse->button & RTGUI_MOUSE_BUTTON_UP)
- bar->status = 0;
- goto __exit;
- }
-
- /* get bar rect */
- bar_rect.x1 = widget->extent.x1 + (widget->extent.y2 - widget->extent.y1);
- bar_rect.x2 = widget->extent.x2 - (widget->extent.y2 - widget->extent.y1);
- bar_rect.y1 = widget->extent.y1;
- bar_rect.y2 = widget->extent.y2;
- if (rtgui_rect_contains_point(&bar_rect, mouse->x, mouse->y) == RT_EOK)
- {
- if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) ==
- (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN))
- {
- /* page step */
- if (mouse->x < bar_rect.x1 + thumb_position)
- {
- bar->thumb_position -= bar->page_step;
- if (bar->thumb_position < bar->min_position)
- bar->thumb_position = bar->min_position;
- }
- else if (mouse->x > thumb_position + bar->thumb_size)
- {
- bar->thumb_position += bar->page_step;
- if (bar->thumb_position > bar->max_position - thumb_size)
- bar->thumb_position = bar->max_position - thumb_size;
- }
- }
- goto __exit;
- }
-
- /* get right arrow button rect */
- btn_rect.x1 = widget->extent.x2 - (widget->extent.y2 - widget->extent.y1);
- btn_rect.x2 = widget->extent.x2;
- bar_rect.x1 = widget->extent.x1 + ((widget->extent.x2 - widget->extent.x1)/2);
- bar_rect.x2 = widget->extent.x2 - (widget->extent.y2 - widget->extent.y1);
- if (rtgui_rect_contains_point(&btn_rect,
- mouse->x, mouse->y) == RT_EOK)
- {
- if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) ==
- (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN))
- {
- bar->status |= SBS_RIGHTARROW;
-
- /* line step */
- bar->thumb_position += bar->line_step;
- if (bar->thumb_position > bar->max_position - bar->line_step)
- bar->thumb_position = bar->max_position - bar->line_step;
- }
- else if (mouse->button & RTGUI_MOUSE_BUTTON_UP)
- bar->status = 0;
- }
- }
-
-__exit:
- rtgui_theme_draw_scrollbar(bar);
- if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) ==
- (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN))
- {
- if (bar->on_scroll != RT_NULL) bar->on_scroll(widget, RT_NULL);
- }
-}
-
-rt_bool_t rtgui_scrollbar_event_handler(struct rtgui_widget * widget,
- struct rtgui_event * event)
-{
- struct rtgui_scrollbar* bar = (struct rtgui_scrollbar*)widget;
-
- switch (event->type)
- {
- case RTGUI_EVENT_PAINT:
-#ifndef RTGUI_USING_SMALL_SIZE
- if (widget->on_draw != RT_NULL) widget->on_draw(widget, event);
- else
-#endif
- {
- rtgui_theme_draw_scrollbar(bar);
- }
-
- break;
-
- case RTGUI_EVENT_MOUSE_BUTTON:
- if (RTGUI_WIDGET_IS_ENABLE(widget) && !RTGUI_WIDGET_IS_HIDE(widget))
- {
-#ifndef RTGUI_USING_SMALL_SIZE
- if (widget->on_mouseclick != RT_NULL)
- {
- widget->on_mouseclick(widget, event);
- }
- else
-#endif
- {
- _rtgui_scrollbar_on_mouseclick(widget, event);
- }
- }
-
- break;
-
- default:
- break;
- }
-
- return RT_FALSE;
-}
-
-struct rtgui_scrollbar* rtgui_scrollbar_create(int orient, rtgui_rect_t* r)
-{
- struct rtgui_scrollbar* bar;
-
- bar = (struct rtgui_scrollbar*) rtgui_widget_create (RTGUI_SCROLLBAR_TYPE);
- if (bar != RT_NULL)
- {
- if (r != RT_NULL)
- {
- rtgui_widget_set_rect(RTGUI_WIDGET(bar), r);
- if (orient == RTGUI_VERTICAL)
- bar->thumb_size = (r->x2 - r->x1);
- else
- bar->thumb_size = (r->y2 - r->y1);
- }
-
- bar->orient = orient;
- }
-
- return bar;
-}
-
-void rtgui_scrollbar_destroy(struct rtgui_scrollbar* bar)
-{
- rtgui_widget_destroy(RTGUI_WIDGET(bar));
-}
-
-void rtgui_scrollbar_set_orientation(rtgui_scrollbar_t* bar, int orientation)
-{
- RT_ASSERT(bar != RT_NULL);
-
- bar->orient = orientation;
-#ifndef RTGUI_USING_SMALL_SIZE
- if (bar->orient == RTGUI_HORIZONTAL)
- {
- /* horizontal */
- rtgui_widget_set_miniwidth(RTGUI_WIDGET(bar), RTGUI_DEFAULT_SB_WIDTH);
- rtgui_widget_set_miniheight(RTGUI_WIDGET(bar), RTGUI_DEFAULT_SB_HEIGHT);
- }
- else
- {
- /* vertical */
- rtgui_widget_set_miniwidth(RTGUI_WIDGET(bar), RTGUI_DEFAULT_SB_HEIGHT);
- rtgui_widget_set_miniheight(RTGUI_WIDGET(bar), RTGUI_DEFAULT_SB_WIDTH);
- }
-#endif
-}
-
-void rtgui_scrollbar_set_range(struct rtgui_scrollbar* bar, int min, int max)
-{
- RT_ASSERT(bar != RT_NULL);
-
- if (min >= max )
- {
- RTGUI_WIDGET_DISABLE(RTGUI_WIDGET(bar));
- return;
- }
-
- bar->min_position = (rt_int16_t)min;
- bar->max_position = (rt_int16_t)max;
-}
-
-void rtgui_scrollbar_set_page_step(struct rtgui_scrollbar* bar, int step)
-{
- RT_ASSERT(bar != RT_NULL);
-
- bar->page_step = step;
-
- /* disable or enable scrollbar */
- if (bar->page_step > (bar->max_position - bar->min_position))
- {
- /* disable bar */
- RTGUI_WIDGET_DISABLE(RTGUI_WIDGET(bar));
- }
- else
- {
- /* enable bar */
- RTGUI_WIDGET_ENABLE(RTGUI_WIDGET(bar));
- }
-}
-
-void rtgui_scrollbar_set_line_step(struct rtgui_scrollbar* bar, int step)
-{
- RT_ASSERT(bar != RT_NULL);
-
- bar->line_step = step;
-}
-
-rt_int16_t rtgui_scrollbar_get_value(struct rtgui_scrollbar* bar)
-{
- RT_ASSERT(bar != RT_NULL);
-
- return bar->thumb_position;
-}
-
-void rtgui_scrollbar_set_value(struct rtgui_scrollbar* bar, rt_int16_t position)
-{
- RT_ASSERT(bar != RT_NULL);
-
- bar->thumb_position = position;
- rtgui_widget_update(RTGUI_WIDGET(bar));
-}
-
-void rtgui_scrollbar_set_onscroll(struct rtgui_scrollbar* bar,
- rtgui_event_handler_ptr handler)
-{
- if (bar == RT_NULL || handler == RT_NULL) return;
-
- bar->on_scroll = handler;
-}
+/* + * File : scrollbar.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2010-08-09 Bernard first version + */ +#include <rtgui/dc.h> +#include <rtgui/rtgui_theme.h> +#include <rtgui/widgets/scrollbar.h> + +static void _rtgui_scrollbar_constructor(rtgui_scrollbar_t *bar) +{ + struct rtgui_rect rect = {0, 0, RTGUI_DEFAULT_SB_WIDTH, RTGUI_DEFAULT_SB_HEIGHT}; + + /* set event handler */ + rtgui_object_set_event_handler(RTGUI_OBJECT(bar), rtgui_scrollbar_event_handler); + + rtgui_scrollbar_set_range(bar, 0, 100); + rtgui_scrollbar_set_page_step(bar, 20); + rtgui_scrollbar_set_line_step(bar, 10); + + bar->status = 0; + bar->thumb_position = 0; + bar->thumb_size = 16; + bar->on_scroll = RT_NULL; + + bar->orient = RTGUI_HORIZONTAL; + rtgui_widget_set_rect(RTGUI_WIDGET(bar), &rect); + + /* set gc */ + RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(bar)) = RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL; +} + +rt_inline rt_uint32_t _rtgui_scrollbar_get_length(rtgui_scrollbar_t *bar) +{ + struct rtgui_rect rect; + + rtgui_widget_get_rect(RTGUI_WIDGET(bar), &rect); + + if (bar->orient & RTGUI_VERTICAL) + return rect.y2 - 2 * (rect.x2 - rect.x1); + + return rect.x2 - 2 * (rect.y2 - rect.y1); +} + +rt_inline rt_uint32_t _rtgui_scrollbar_get_thumb_position(rtgui_scrollbar_t* bar) +{ + rt_uint32_t thumb_position; + + /* calculate thumb position */ + thumb_position = (rtgui_scrollbar_get_value(bar) - bar->min_position) * _rtgui_scrollbar_get_length(bar) / + (bar->max_position - bar->min_position); + + return thumb_position; +} + +void rtgui_scrollbar_get_thumb_rect(rtgui_scrollbar_t *bar, rtgui_rect_t *rect) +{ + struct rtgui_rect scrollbar_rect; + + rtgui_widget_get_rect(RTGUI_WIDGET(bar), &scrollbar_rect); + if (bar->orient & RTGUI_VERTICAL) + { + rt_uint32_t btn_width = scrollbar_rect.x2 - scrollbar_rect.x1; + + /* vertical scroll bar */ + rect->x1 = scrollbar_rect.x1; + rect->x2 = scrollbar_rect.x2; + rect->y1 = scrollbar_rect.y1 + btn_width + _rtgui_scrollbar_get_thumb_position(bar); + rect->y2 = rect->y1 + btn_width; + } + else + { + rt_uint32_t btn_height = scrollbar_rect.y2 - scrollbar_rect.y1; + + /* horizontal scroll bar */ + rect->x1 = scrollbar_rect.x1 + btn_height + _rtgui_scrollbar_get_thumb_position(bar); + rect->x2 = rect->x1 + btn_height; + + rect->y1 = scrollbar_rect.y1; + rect->y2 = scrollbar_rect.y2; + } +} + +DEFINE_CLASS_TYPE(scrollbar, "scrollbar", + RTGUI_WIDGET_TYPE, + _rtgui_scrollbar_constructor, + RT_NULL, + sizeof(struct rtgui_scrollbar)); + +static void _rtgui_scrollbar_on_mouseclick(struct rtgui_widget * widget, struct rtgui_event * event) +{ + rtgui_rect_t btn_rect, bar_rect; + rt_uint32_t thumb_size, thumb_position; + struct rtgui_scrollbar* bar = (struct rtgui_scrollbar*)widget; + struct rtgui_event_mouse* mouse = (struct rtgui_event_mouse*)event; + + /* get the thumb size and position */ + thumb_size = bar->thumb_size * (bar->max_position - bar->min_position) / _rtgui_scrollbar_get_length(bar); + thumb_position = _rtgui_scrollbar_get_thumb_position(bar); + + if (bar->orient == RTGUI_VERTICAL) + { + /* get up arrow button rect */ + btn_rect.x1 = widget->extent.x1; + btn_rect.x2 = widget->extent.x2; + btn_rect.y1 = widget->extent.y1; + btn_rect.y2 = widget->extent.y1 + (widget->extent.x2 - widget->extent.x1); + if (rtgui_rect_contains_point(&btn_rect, mouse->x, mouse->y) == RT_EOK) + { + if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) == + (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) + { + bar->status |= SBS_UPARROW; + + /* line step */ + bar->thumb_position -= bar->line_step; + if (bar->thumb_position < bar->min_position) bar->thumb_position = bar->min_position; + } + else if (mouse->button & RTGUI_MOUSE_BUTTON_UP) + { + bar->status = 0; + } + goto __exit; + } + + /* get bar rect */ + bar_rect.x1 = widget->extent.x1; + bar_rect.x2 = widget->extent.x2; + bar_rect.y1 = widget->extent.y1 + (widget->extent.x2 - widget->extent.x1); + bar_rect.y2 = widget->extent.y2 - (widget->extent.x2 - widget->extent.x1); + if (rtgui_rect_contains_point(&bar_rect, mouse->x, mouse->y) == RT_EOK) + { + if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) == + (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) + { + /* page step */ + if (mouse->y < bar_rect.y1 + thumb_position) + { + bar->thumb_position -= bar->page_step; + if (bar->thumb_position < bar->min_position) + bar->thumb_position = bar->min_position; + } + else if (mouse->y > thumb_position + bar->thumb_size) + { + bar->thumb_position += bar->page_step; + if (bar->thumb_position > bar->max_position - thumb_size) + bar->thumb_position = bar->max_position - thumb_size; + } + } + goto __exit; + } + + /* get down arrow button rect */ + btn_rect.y1 = widget->extent.y2 - (widget->extent.x2 - widget->extent.x1); + btn_rect.y2 = widget->extent.y2; + bar_rect.y1 = widget->extent.y1 + ((widget->extent.y2 - widget->extent.y1)/2); + bar_rect.y2 = widget->extent.y2 - (widget->extent.x2 - widget->extent.x1); + if (rtgui_rect_contains_point(&btn_rect, mouse->x, mouse->y) == RT_EOK) + { + if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) == + (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) + { + bar->status |= SBS_DOWNARROW; + + /* line step */ + bar->thumb_position += bar->line_step; + if (bar->thumb_position > bar->max_position - thumb_size) + bar->thumb_position = bar->max_position - thumb_size; + } + else if (mouse->button & RTGUI_MOUSE_BUTTON_UP) + bar->status = 0; + } + } + else + { + /* get left arrow button rect */ + btn_rect.x1 = widget->extent.x1; + btn_rect.x2 = widget->extent.x1 + (widget->extent.y2 - widget->extent.y1); + btn_rect.y1 = widget->extent.y1; + btn_rect.y2 = widget->extent.y2; + if (rtgui_rect_contains_point(&btn_rect, mouse->x, mouse->y) == RT_EOK) + { + if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) == + (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) + { + bar->status |= SBS_LEFTARROW; + + /* line step */ + bar->thumb_position -= bar->line_step; + if (bar->thumb_position < bar->min_position) bar->thumb_position = bar->min_position; + } + else if (mouse->button & RTGUI_MOUSE_BUTTON_UP) + bar->status = 0; + goto __exit; + } + + /* get bar rect */ + bar_rect.x1 = widget->extent.x1 + (widget->extent.y2 - widget->extent.y1); + bar_rect.x2 = widget->extent.x2 - (widget->extent.y2 - widget->extent.y1); + bar_rect.y1 = widget->extent.y1; + bar_rect.y2 = widget->extent.y2; + if (rtgui_rect_contains_point(&bar_rect, mouse->x, mouse->y) == RT_EOK) + { + if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) == + (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) + { + /* page step */ + if (mouse->x < bar_rect.x1 + thumb_position) + { + bar->thumb_position -= bar->page_step; + if (bar->thumb_position < bar->min_position) + bar->thumb_position = bar->min_position; + } + else if (mouse->x > thumb_position + bar->thumb_size) + { + bar->thumb_position += bar->page_step; + if (bar->thumb_position > bar->max_position - thumb_size) + bar->thumb_position = bar->max_position - thumb_size; + } + } + goto __exit; + } + + /* get right arrow button rect */ + btn_rect.x1 = widget->extent.x2 - (widget->extent.y2 - widget->extent.y1); + btn_rect.x2 = widget->extent.x2; + bar_rect.x1 = widget->extent.x1 + ((widget->extent.x2 - widget->extent.x1)/2); + bar_rect.x2 = widget->extent.x2 - (widget->extent.y2 - widget->extent.y1); + if (rtgui_rect_contains_point(&btn_rect, + mouse->x, mouse->y) == RT_EOK) + { + if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) == + (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) + { + bar->status |= SBS_RIGHTARROW; + + /* line step */ + bar->thumb_position += bar->line_step; + if (bar->thumb_position > bar->max_position - bar->line_step) + bar->thumb_position = bar->max_position - bar->line_step; + } + else if (mouse->button & RTGUI_MOUSE_BUTTON_UP) + bar->status = 0; + } + } + +__exit: + rtgui_theme_draw_scrollbar(bar); + if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) == + (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) + { + if (bar->on_scroll != RT_NULL) + bar->on_scroll(RTGUI_OBJECT(widget), RT_NULL); + } +} + +rt_bool_t rtgui_scrollbar_event_handler(struct rtgui_object *object, + struct rtgui_event *event) +{ + struct rtgui_scrollbar* bar; + RTGUI_WIDGET_EVENT_HANDLER_PREPARE + + bar = RTGUI_SCROLLBAR(object); + + switch (event->type) + { + case RTGUI_EVENT_PAINT: +#ifndef RTGUI_USING_SMALL_SIZE + if (widget->on_draw != RT_NULL) widget->on_draw(widget, event); + else +#endif + { + rtgui_theme_draw_scrollbar(bar); + } + + break; + + case RTGUI_EVENT_MOUSE_BUTTON: + if (RTGUI_WIDGET_IS_ENABLE(widget) && !RTGUI_WIDGET_IS_HIDE(widget)) + { +#ifndef RTGUI_USING_SMALL_SIZE + if (widget->on_mouseclick != RT_NULL) + { + widget->on_mouseclick(widget, event); + } + else +#endif + { + _rtgui_scrollbar_on_mouseclick(widget, event); + } + } + + break; + + default: + break; + } + + return RT_FALSE; +} + +struct rtgui_scrollbar* rtgui_scrollbar_create(int orient, rtgui_rect_t* r) +{ + struct rtgui_scrollbar* bar; + + bar = (struct rtgui_scrollbar*) rtgui_widget_create (RTGUI_SCROLLBAR_TYPE); + if (bar != RT_NULL) + { + if (r != RT_NULL) + { + rtgui_widget_set_rect(RTGUI_WIDGET(bar), r); + if (orient == RTGUI_VERTICAL) + bar->thumb_size = (r->x2 - r->x1); + else + bar->thumb_size = (r->y2 - r->y1); + } + + bar->orient = orient; + } + + return bar; +} + +void rtgui_scrollbar_destroy(struct rtgui_scrollbar* bar) +{ + rtgui_widget_destroy(RTGUI_WIDGET(bar)); +} + +void rtgui_scrollbar_set_orientation(rtgui_scrollbar_t* bar, int orientation) +{ + RT_ASSERT(bar != RT_NULL); + + bar->orient = orientation; +#ifndef RTGUI_USING_SMALL_SIZE + if (bar->orient == RTGUI_HORIZONTAL) + { + /* horizontal */ + rtgui_widget_set_miniwidth(RTGUI_WIDGET(bar), RTGUI_DEFAULT_SB_WIDTH); + rtgui_widget_set_miniheight(RTGUI_WIDGET(bar), RTGUI_DEFAULT_SB_HEIGHT); + } + else + { + /* vertical */ + rtgui_widget_set_miniwidth(RTGUI_WIDGET(bar), RTGUI_DEFAULT_SB_HEIGHT); + rtgui_widget_set_miniheight(RTGUI_WIDGET(bar), RTGUI_DEFAULT_SB_WIDTH); + } +#endif +} + +void rtgui_scrollbar_set_range(struct rtgui_scrollbar* bar, int min, int max) +{ + RT_ASSERT(bar != RT_NULL); + + if (min >= max ) + { + RTGUI_WIDGET_DISABLE(RTGUI_WIDGET(bar)); + return; + } + + bar->min_position = (rt_int16_t)min; + bar->max_position = (rt_int16_t)max; +} + +void rtgui_scrollbar_set_page_step(struct rtgui_scrollbar* bar, int step) +{ + RT_ASSERT(bar != RT_NULL); + + bar->page_step = step; + + /* disable or enable scrollbar */ + if (bar->page_step > (bar->max_position - bar->min_position)) + { + /* disable bar */ + RTGUI_WIDGET_DISABLE(RTGUI_WIDGET(bar)); + } + else + { + /* enable bar */ + RTGUI_WIDGET_ENABLE(RTGUI_WIDGET(bar)); + } +} + +void rtgui_scrollbar_set_line_step(struct rtgui_scrollbar* bar, int step) +{ + RT_ASSERT(bar != RT_NULL); + + bar->line_step = step; +} + +rt_int16_t rtgui_scrollbar_get_value(struct rtgui_scrollbar* bar) +{ + RT_ASSERT(bar != RT_NULL); + + return bar->thumb_position; +} + +void rtgui_scrollbar_set_value(struct rtgui_scrollbar* bar, rt_int16_t position) +{ + RT_ASSERT(bar != RT_NULL); + + bar->thumb_position = position; + rtgui_widget_update(RTGUI_WIDGET(bar)); +} + +void rtgui_scrollbar_set_onscroll(struct rtgui_scrollbar* bar, + rtgui_event_handler_ptr handler) +{ + if (bar == RT_NULL || handler == RT_NULL) return; + + bar->on_scroll = handler; +} diff --git a/components/rtgui/widgets/slider.c b/components/rtgui/widgets/slider.c index d44954f9b4..30d29d84f9 100644 --- a/components/rtgui/widgets/slider.c +++ b/components/rtgui/widgets/slider.c @@ -1,241 +1,266 @@ -/*
- * File : slider.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2009-10-16 Bernard first version
- * 2010-09-10 Bernard fix hide issue
- */
-#include <rtgui/dc.h>
-#include <rtgui/rtgui_theme.h>
-#include <rtgui/widgets/slider.h>
-
-#define RTGUI_SLIDER_DEFAULT_WIDTH 100
-#define RTGUI_SLIDER_DEFAULT_HEIGHT 20
-#define RTGUI_SLIDER_DEFAULT_MIN 0
-#define RTGUI_SLIDER_DEFAULT_MAX 100
-
-static void _rtgui_slider_constructor(rtgui_slider_t *slider)
-{
- rtgui_rect_t rect = {0, 0, RTGUI_SLIDER_DEFAULT_WIDTH, RTGUI_SLIDER_DEFAULT_HEIGHT};
-
- /* init widget and set event handler */
- RTGUI_WIDGET(slider)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
- rtgui_widget_set_rect(RTGUI_WIDGET(slider), &rect);
- rtgui_widget_set_event_handler(RTGUI_WIDGET(slider), rtgui_slider_event_handler);
-
- /* set proper of control */
- slider->min = RTGUI_SLIDER_DEFAULT_MIN;
- slider->max = RTGUI_SLIDER_DEFAULT_MAX;
- slider->value = RTGUI_SLIDER_DEFAULT_MIN;
- slider->orient = RTGUI_HORIZONTAL;
-
- slider->ticks = 10;
- slider->thumb_width = 8;
- slider->on_changed = RT_NULL;
-}
-
-DEFINE_CLASS_TYPE(slider, "slider",
- RTGUI_WIDGET_TYPE,
- _rtgui_slider_constructor,
- RT_NULL,
- sizeof(struct rtgui_slider));
-
-static void rtgui_slider_onmouse(struct rtgui_slider* slider, struct rtgui_event_mouse* event)
-{
- RT_ASSERT(slider != RT_NULL);
- RT_ASSERT(event != RT_NULL);
-
- if (event->button & RTGUI_MOUSE_BUTTON_DOWN &&
- event->button & RTGUI_MOUSE_BUTTON_LEFT)
- {
- int sel;
- int range = slider->max - slider->min;
- int x0, xsize;
- int x;
- x0 = 1 + slider->thumb_width/2;
-
- if (slider->orient == RTGUI_VERTICAL)
- {
- x = event->y - RTGUI_WIDGET(slider)->extent.y1;
- x -= x0;
- xsize = rtgui_rect_height(RTGUI_WIDGET(slider)->extent) - 2 * x0;
- }
- else
- {
- x = event->x - RTGUI_WIDGET(slider)->extent.x1;
- x -= x0;
- xsize = rtgui_rect_width(RTGUI_WIDGET(slider)->extent) - 2 * x0;
- }
-
- if (x <= 0)
- {
- sel = slider->min;
- }
- else if (x >= xsize)
- {
- sel = slider->max;
- }
- else
- {
- sel = ((range * x) + xsize/2) / xsize;
- sel += slider->min;
- }
-
- rtgui_widget_focus(RTGUI_WIDGET(slider));
- rtgui_slider_set_value(slider, sel);
- if (slider->on_changed != RT_NULL) /* invoke callback function */
- slider->on_changed(RTGUI_WIDGET(slider), RT_NULL);
- }
-}
-
-static void rtgui_slider_onkey(struct rtgui_slider* slider, struct rtgui_event_kbd *event)
-{
- RT_ASSERT(slider != RT_NULL);
- RT_ASSERT(event != RT_NULL);
-
- if (!(RTGUI_KBD_IS_UP(event))) return;
-
- if (event->key == RTGUIK_LEFT)
- {
- if (slider->value > slider->min)
- slider->value ++;
- }
-
- if (event->key == RTGUIK_RIGHT)
- {
- if (slider->value < slider->max)
- slider->value --;
- }
-
- /* update widget */
- rtgui_widget_update(RTGUI_WIDGET(slider));
- if (slider->on_changed != RT_NULL) /* invoke callback function */
- slider->on_changed(RTGUI_WIDGET(slider), RT_NULL);
-}
-
-rt_bool_t rtgui_slider_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
-{
- struct rtgui_slider* slider = (struct rtgui_slider*)widget;
-
- switch (event->type)
- {
- case RTGUI_EVENT_PAINT:
-#ifndef RTGUI_USING_SMALL_SIZE
- if (widget->on_draw != RT_NULL) widget->on_draw(widget, event);
- else
-#endif
- {
- rtgui_theme_draw_slider(slider);
- }
-
- break;
-
- case RTGUI_EVENT_KBD:
- if (!RTGUI_WIDGET_IS_ENABLE(widget) || RTGUI_WIDGET_IS_HIDE(widget)) return RT_FALSE;
-
-#ifndef RTGUI_USING_SMALL_SIZE
- if (widget->on_key != RT_NULL) widget->on_key(widget, event);
- else
-#endif
- {
- rtgui_slider_onkey(slider, (struct rtgui_event_kbd *)event);
- }
- break;
-
- case RTGUI_EVENT_MOUSE_BUTTON:
- if (!RTGUI_WIDGET_IS_ENABLE(widget) || RTGUI_WIDGET_IS_HIDE(widget)) return RT_FALSE;
-
-#ifndef RTGUI_USING_SMALL_SIZE
- if (widget->on_mouseclick != RT_NULL) widget->on_mouseclick(widget, event);
- else
-#endif
- {
- rtgui_slider_onmouse(slider, (struct rtgui_event_mouse*)event);
- }
- break;
- }
-
- return RT_FALSE;
-}
-
-struct rtgui_slider* rtgui_slider_create(rt_size_t min, rt_size_t max, int orient)
-{
- struct rtgui_slider* slider;
-
- slider = (struct rtgui_slider*) rtgui_widget_create (RTGUI_SLIDER_TYPE);
- if (slider != RT_NULL)
- {
- /* set proper of control */
- slider->min = min;
- slider->max = max;
- slider->value = min;
-
- slider->ticks = 10;
- slider->thumb_width = 8;
-
- rtgui_slider_set_orientation(slider, orient);
- }
-
- return slider;
-}
-
-void rtgui_slider_set_range(struct rtgui_slider* slider, rt_size_t min, rt_size_t max)
-{
- RT_ASSERT(slider != RT_NULL);
-
- slider->max = max;
- slider->min = min;
-}
-
-void rtgui_slider_set_value(struct rtgui_slider* slider, rt_size_t value)
-{
- RT_ASSERT(slider != RT_NULL);
-
- if (RTGUI_WIDGET_IS_ENABLE(RTGUI_WIDGET(slider)))
- {
- if (value < slider->min) value = slider->min;
- if (value > slider->max) value = slider->max;
-
- if (slider->value != value)
- {
- slider->value = value;
- rtgui_theme_draw_slider(slider);
- }
- }
-}
-
-void rtgui_slider_set_orientation(struct rtgui_slider* slider, int orientation)
-{
- RT_ASSERT(slider != RT_NULL);
-
- /* set orientation */
- slider->orient = orientation;
-#ifndef RTGUI_USING_SMALL_SIZE
- if (slider->orient == RTGUI_HORIZONTAL)
- {
- /* HORIZONTAL */
- rtgui_widget_set_miniheight(RTGUI_WIDGET(slider), RTGUI_SLIDER_DEFAULT_HEIGHT);
- rtgui_widget_set_miniwidth(RTGUI_WIDGET(slider), RTGUI_SLIDER_DEFAULT_WIDTH);
- }
- else
- {
- /* VERTICAL */
- rtgui_widget_set_miniwidth(RTGUI_WIDGET(slider), RTGUI_SLIDER_DEFAULT_HEIGHT);
- rtgui_widget_set_miniheight(RTGUI_WIDGET(slider), RTGUI_SLIDER_DEFAULT_WIDTH);
- }
-#endif
-}
-
-rt_size_t rtgui_slider_get_value(struct rtgui_slider* slider)
-{
- RT_ASSERT(slider != RT_NULL);
-
- return slider->value;
-}
+/* + * File : slider.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + * 2010-09-10 Bernard fix hide issue + */ +#include <rtgui/dc.h> +#include <rtgui/rtgui_theme.h> +#include <rtgui/widgets/slider.h> + +#define RTGUI_SLIDER_DEFAULT_WIDTH 100 +#define RTGUI_SLIDER_DEFAULT_HEIGHT 20 +#define RTGUI_SLIDER_DEFAULT_MIN 0 +#define RTGUI_SLIDER_DEFAULT_MAX 100 + +static void _rtgui_slider_constructor(rtgui_slider_t *slider) +{ + rtgui_rect_t rect = {0, 0, RTGUI_SLIDER_DEFAULT_WIDTH, RTGUI_SLIDER_DEFAULT_HEIGHT}; + + /* init widget and set event handler */ + RTGUI_WIDGET(slider)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE; + rtgui_widget_set_rect(RTGUI_WIDGET(slider), &rect); + rtgui_object_set_event_handler(RTGUI_OBJECT(slider), rtgui_slider_event_handler); + + /* set proper of control */ + slider->min = RTGUI_SLIDER_DEFAULT_MIN; + slider->max = RTGUI_SLIDER_DEFAULT_MAX; + slider->value = RTGUI_SLIDER_DEFAULT_MIN; + slider->orient = RTGUI_HORIZONTAL; + + slider->ticks = 10; + slider->thumb_width = 8; + slider->on_changed = RT_NULL; +} + +DEFINE_CLASS_TYPE(slider, "slider", + RTGUI_WIDGET_TYPE, + _rtgui_slider_constructor, + RT_NULL, + sizeof(struct rtgui_slider)); + +static void rtgui_slider_onmouse(struct rtgui_slider* slider, struct rtgui_event_mouse* event) +{ + RT_ASSERT(slider != RT_NULL); + RT_ASSERT(event != RT_NULL); + + if (event->button & RTGUI_MOUSE_BUTTON_DOWN && + event->button & RTGUI_MOUSE_BUTTON_LEFT) + { + int sel; + int range = slider->max - slider->min; + int x0, xsize; + int x; + x0 = 1 + slider->thumb_width/2; + + if (slider->orient == RTGUI_VERTICAL) + { + x = event->y - RTGUI_WIDGET(slider)->extent.y1; + x -= x0; + xsize = rtgui_rect_height(RTGUI_WIDGET(slider)->extent) - 2 * x0; + } + else + { + x = event->x - RTGUI_WIDGET(slider)->extent.x1; + x -= x0; + xsize = rtgui_rect_width(RTGUI_WIDGET(slider)->extent) - 2 * x0; + } + + if (x <= 0) + { + sel = slider->min; + } + else if (x >= xsize) + { + sel = slider->max; + } + else + { + sel = ((range * x) + xsize/2) / xsize; + sel += slider->min; + } + + rtgui_widget_focus(RTGUI_WIDGET(slider)); + rtgui_slider_set_value(slider, sel); + if (slider->on_changed != RT_NULL) /* invoke callback function */ + slider->on_changed(RTGUI_WIDGET(slider), RT_NULL); + } +} + +static rt_bool_t rtgui_slider_onkey(struct rtgui_slider* slider, struct rtgui_event_kbd *event) +{ + RT_ASSERT(slider != RT_NULL); + RT_ASSERT(event != RT_NULL); + + if (!(RTGUI_KBD_IS_UP(event))) + return RT_TRUE; + + if (slider->orient == RTGUI_HORIZONTAL) + { + if (event->key == RTGUIK_RIGHT) + { + if (slider->value > slider->min) + slider->value++; + } + else if (event->key == RTGUIK_LEFT) + { + if (slider->value < slider->max) + slider->value--; + } + } + else + { + if (event->key == RTGUIK_UP) + { + if (slider->value > slider->min) + slider->value--; + } + else if (event->key == RTGUIK_DOWN) + { + if (slider->value < slider->max) + slider->value++; + } + } + + /* update widget */ + rtgui_widget_update(RTGUI_WIDGET(slider)); + if (slider->on_changed != RT_NULL) /* invoke callback function */ + slider->on_changed(RTGUI_WIDGET(slider), RT_NULL); + + return RT_TRUE; +} + +rt_bool_t rtgui_slider_event_handler(struct rtgui_object *object, struct rtgui_event *event) +{ + struct rtgui_widget *widget; + struct rtgui_slider* slider; + + RT_ASSERT(object != RT_NULL); + RT_ASSERT(event != RT_NULL); + + widget = RTGUI_WIDGET(object); + slider = RTGUI_SLIDER(object); + + switch (event->type) + { + case RTGUI_EVENT_PAINT: +#ifndef RTGUI_USING_SMALL_SIZE + if (widget->on_draw != RT_NULL) widget->on_draw(widget, event); + else +#endif + { + rtgui_theme_draw_slider(slider); + } + + break; + + case RTGUI_EVENT_KBD: + if (!RTGUI_WIDGET_IS_ENABLE(widget) || RTGUI_WIDGET_IS_HIDE(widget)) return RT_FALSE; + +#ifndef RTGUI_USING_SMALL_SIZE + if (widget->on_key != RT_NULL) widget->on_key(widget, event); + else +#endif + { + return rtgui_slider_onkey(slider, (struct rtgui_event_kbd *)event); + } + break; + + case RTGUI_EVENT_MOUSE_BUTTON: + if (!RTGUI_WIDGET_IS_ENABLE(widget) || RTGUI_WIDGET_IS_HIDE(widget)) return RT_FALSE; + +#ifndef RTGUI_USING_SMALL_SIZE + if (widget->on_mouseclick != RT_NULL) widget->on_mouseclick(widget, event); + else +#endif + { + rtgui_slider_onmouse(slider, (struct rtgui_event_mouse*)event); + } + break; + } + + return RT_FALSE; +} + +struct rtgui_slider* rtgui_slider_create(rt_size_t min, rt_size_t max, int orient) +{ + struct rtgui_slider* slider; + + slider = (struct rtgui_slider*) rtgui_widget_create (RTGUI_SLIDER_TYPE); + if (slider != RT_NULL) + { + /* set proper of control */ + slider->min = min; + slider->max = max; + slider->value = min; + + slider->ticks = 10; + slider->thumb_width = 8; + + rtgui_slider_set_orientation(slider, orient); + } + + return slider; +} + +void rtgui_slider_set_range(struct rtgui_slider* slider, rt_size_t min, rt_size_t max) +{ + RT_ASSERT(slider != RT_NULL); + + slider->max = max; + slider->min = min; +} + +void rtgui_slider_set_value(struct rtgui_slider* slider, rt_size_t value) +{ + RT_ASSERT(slider != RT_NULL); + + if (RTGUI_WIDGET_IS_ENABLE(RTGUI_WIDGET(slider))) + { + if (value < slider->min) value = slider->min; + if (value > slider->max) value = slider->max; + + if (slider->value != value) + { + slider->value = value; + rtgui_theme_draw_slider(slider); + } + } +} + +void rtgui_slider_set_orientation(struct rtgui_slider* slider, int orientation) +{ + RT_ASSERT(slider != RT_NULL); + + /* set orientation */ + slider->orient = orientation; +#ifndef RTGUI_USING_SMALL_SIZE + if (slider->orient == RTGUI_HORIZONTAL) + { + /* HORIZONTAL */ + rtgui_widget_set_miniheight(RTGUI_WIDGET(slider), RTGUI_SLIDER_DEFAULT_HEIGHT); + rtgui_widget_set_miniwidth(RTGUI_WIDGET(slider), RTGUI_SLIDER_DEFAULT_WIDTH); + } + else + { + /* VERTICAL */ + rtgui_widget_set_miniwidth(RTGUI_WIDGET(slider), RTGUI_SLIDER_DEFAULT_HEIGHT); + rtgui_widget_set_miniheight(RTGUI_WIDGET(slider), RTGUI_SLIDER_DEFAULT_WIDTH); + } +#endif +} + +rt_size_t rtgui_slider_get_value(struct rtgui_slider* slider) +{ + RT_ASSERT(slider != RT_NULL); + + return slider->value; +} diff --git a/components/rtgui/widgets/staticline.c b/components/rtgui/widgets/staticline.c index a1c38bbd20..19a1caed49 100644 --- a/components/rtgui/widgets/staticline.c +++ b/components/rtgui/widgets/staticline.c @@ -1,80 +1,80 @@ -#include <rtgui/dc.h>
-#include <rtgui/rtgui_theme.h>
-#include <rtgui/widgets/staticline.h>
-
-static void _rtgui_staticline_constructor(rtgui_staticline_t *staticline)
-{
- /* init widget and set event handler */
- rtgui_rect_t rect = {0, 0, 100, 2};
-
- rtgui_widget_set_rect(RTGUI_WIDGET(staticline), &rect);
- staticline->orient= RTGUI_HORIZONTAL;
-
- rtgui_widget_set_event_handler(RTGUI_WIDGET(staticline), rtgui_staticline_event_handler);
-}
-
-
-DEFINE_CLASS_TYPE(staticline, "staticline",
- RTGUI_WIDGET_TYPE,
- _rtgui_staticline_constructor,
- RT_NULL,
- sizeof(struct rtgui_staticline));
-
-rt_bool_t rtgui_staticline_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
-{
- struct rtgui_staticline* staticline;
- RT_ASSERT(widget != RT_NULL);
-
- staticline = (struct rtgui_staticline*) widget;
- switch (event->type)
- {
- case RTGUI_EVENT_PAINT:
-#ifndef RTGUI_USING_SMALL_SIZE
- if (widget->on_draw != RT_NULL) widget->on_draw(widget, event);
- else
-#endif
- rtgui_theme_draw_staticline(staticline);
- break;
- }
-
- return RT_FALSE;
-}
-
-rtgui_staticline_t * rtgui_staticline_create(int orientation)
-{
- rtgui_staticline_t* staticline;
-
- staticline = (struct rtgui_staticline*) rtgui_widget_create(RTGUI_STATICLINE_TYPE);
- if (staticline!= RT_NULL)
- {
- rtgui_staticline_set_orientation(staticline, orientation);
- }
-
- return staticline;
-}
-
-void rtgui_staticline_destroy(rtgui_staticline_t* staticline)
-{
- rtgui_widget_destroy(RTGUI_WIDGET(staticline));
-}
-
-void rtgui_staticline_set_orientation(rtgui_staticline_t* staticline, int orientation)
-{
- RT_ASSERT(staticline != RT_NULL);
-
- staticline->orient = orientation;
-#ifndef RTGUI_USING_SMALL_SIZE
- if (orientation == RTGUI_HORIZONTAL)
- {
- /* HORIZONTAL */
- rtgui_widget_set_miniheight(RTGUI_WIDGET(staticline), 2);
- rtgui_widget_set_miniwidth(RTGUI_WIDGET(staticline), 100);
- }
- else
- {
- /* VERTICAL */
- rtgui_widget_set_miniwidth(RTGUI_WIDGET(staticline), 2);
- rtgui_widget_set_miniheight(RTGUI_WIDGET(staticline), 100);
- }
-#endif
-}
+#include <rtgui/dc.h> +#include <rtgui/rtgui_theme.h> +#include <rtgui/widgets/staticline.h> + +static void _rtgui_staticline_constructor(rtgui_staticline_t *staticline) +{ + /* init widget and set event handler */ + rtgui_rect_t rect = {0, 0, 100, 2}; + + rtgui_widget_set_rect(RTGUI_WIDGET(staticline), &rect); + staticline->orient= RTGUI_HORIZONTAL; + + rtgui_object_set_event_handler(RTGUI_OBJECT(staticline), rtgui_staticline_event_handler); +} + + +DEFINE_CLASS_TYPE(staticline, "staticline", + RTGUI_WIDGET_TYPE, + _rtgui_staticline_constructor, + RT_NULL, + sizeof(struct rtgui_staticline)); + +rt_bool_t rtgui_staticline_event_handler(struct rtgui_object* object, struct rtgui_event* event) +{ + struct rtgui_staticline* staticline; + RTGUI_WIDGET_EVENT_HANDLER_PREPARE + + staticline = RTGUI_STATICLINE(object); + switch (event->type) + { + case RTGUI_EVENT_PAINT: +#ifndef RTGUI_USING_SMALL_SIZE + if (widget->on_draw != RT_NULL) widget->on_draw(widget, event); + else +#endif + rtgui_theme_draw_staticline(staticline); + break; + } + + return RT_FALSE; +} + +rtgui_staticline_t * rtgui_staticline_create(int orientation) +{ + rtgui_staticline_t* staticline; + + staticline = (struct rtgui_staticline*) rtgui_widget_create(RTGUI_STATICLINE_TYPE); + if (staticline!= RT_NULL) + { + rtgui_staticline_set_orientation(staticline, orientation); + } + + return staticline; +} + +void rtgui_staticline_destroy(rtgui_staticline_t* staticline) +{ + rtgui_widget_destroy(RTGUI_WIDGET(staticline)); +} + +void rtgui_staticline_set_orientation(rtgui_staticline_t* staticline, int orientation) +{ + RT_ASSERT(staticline != RT_NULL); + + staticline->orient = orientation; +#ifndef RTGUI_USING_SMALL_SIZE + if (orientation == RTGUI_HORIZONTAL) + { + /* HORIZONTAL */ + rtgui_widget_set_miniheight(RTGUI_WIDGET(staticline), 2); + rtgui_widget_set_miniwidth(RTGUI_WIDGET(staticline), 100); + } + else + { + /* VERTICAL */ + rtgui_widget_set_miniwidth(RTGUI_WIDGET(staticline), 2); + rtgui_widget_set_miniheight(RTGUI_WIDGET(staticline), 100); + } +#endif +} diff --git a/components/rtgui/widgets/textbox.c b/components/rtgui/widgets/textbox.c index 4bbaaed615..15f2bd44ef 100644 --- a/components/rtgui/widgets/textbox.c +++ b/components/rtgui/widgets/textbox.c @@ -25,13 +25,13 @@ #define RTGUI_TEXTBOX_MARGIN 3 static void rtgui_textbox_onkey(struct rtgui_textbox* box, struct rtgui_event_kbd* event); -static rt_bool_t rtgui_textbox_onfocus(struct rtgui_widget* widget, struct rtgui_event* event); -static rt_bool_t rtgui_textbox_onunfocus(struct rtgui_widget* widget, struct rtgui_event* event); +static rt_bool_t rtgui_textbox_onfocus(struct rtgui_object* object, struct rtgui_event* event); +static rt_bool_t rtgui_textbox_onunfocus(struct rtgui_object* object, struct rtgui_event* event); static void _rtgui_textbox_caret_timeout(struct rtgui_timer* timer, void* parameter) { rtgui_textbox_t* box; - + box = (rtgui_textbox_t*)parameter; /* set caret flag */ if (box->flag & RTGUI_TEXTBOX_CARET_SHOW) @@ -51,7 +51,7 @@ static void _rtgui_textbox_constructor(rtgui_textbox_t *box) rtgui_widget_set_rect(RTGUI_WIDGET(box), &rect); RTGUI_WIDGET(box)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE; - rtgui_widget_set_event_handler(RTGUI_WIDGET(box), rtgui_textbox_event_handler); + rtgui_object_set_event_handler(RTGUI_OBJECT(box), rtgui_textbox_event_handler); rtgui_widget_set_onfocus(RTGUI_WIDGET(box), rtgui_textbox_onfocus); rtgui_widget_set_onunfocus(RTGUI_WIDGET(box), rtgui_textbox_onunfocus); @@ -226,10 +226,12 @@ static void rtgui_textbox_onkey(struct rtgui_textbox* box, struct rtgui_event_kb rtgui_theme_draw_textbox(box); } -static rt_bool_t rtgui_textbox_onfocus(struct rtgui_widget* widget, struct rtgui_event* event) +static rt_bool_t rtgui_textbox_onfocus(struct rtgui_object* object, struct rtgui_event* event) { - struct rtgui_textbox* box = (struct rtgui_textbox*)widget; + struct rtgui_textbox* box; + RTGUI_WIDGET_EVENT_HANDLER_PREPARE + box = RTGUI_TEXTBOX(object); /* set caret to show */ box->flag |= RTGUI_TEXTBOX_CARET_SHOW; /* start caret timer */ @@ -238,10 +240,12 @@ static rt_bool_t rtgui_textbox_onfocus(struct rtgui_widget* widget, struct rtgui return RT_TRUE; } -static rt_bool_t rtgui_textbox_onunfocus(struct rtgui_widget* widget, struct rtgui_event* event) +static rt_bool_t rtgui_textbox_onunfocus(struct rtgui_object* object, struct rtgui_event* event) { - struct rtgui_textbox* box = (struct rtgui_textbox*)widget; + struct rtgui_textbox* box; + RTGUI_WIDGET_EVENT_HANDLER_PREPARE + box = RTGUI_TEXTBOX(object); /* stop caret timer */ rtgui_timer_stop(box->caret_timer); /* set caret to hide */ @@ -250,10 +254,12 @@ static rt_bool_t rtgui_textbox_onunfocus(struct rtgui_widget* widget, struct rtg return RT_TRUE; } -rt_bool_t rtgui_textbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event) +rt_bool_t rtgui_textbox_event_handler(struct rtgui_object* object, struct rtgui_event* event) { - struct rtgui_textbox* box = (struct rtgui_textbox*)widget; + struct rtgui_textbox* box; + RTGUI_WIDGET_EVENT_HANDLER_PREPARE + box = RTGUI_TEXTBOX(object); switch (event->type) { case RTGUI_EVENT_PAINT: diff --git a/components/rtgui/widgets/textview.c b/components/rtgui/widgets/textview.c index 2bb7a41e1d..fe57b82ab2 100644 --- a/components/rtgui/widgets/textview.c +++ b/components/rtgui/widgets/textview.c @@ -1,352 +1,351 @@ -/*
- * File : textview.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2006 - 2011, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date Author Notes
- * 2011-03-05 Bernard first version
- */
-#include <rtgui/dc.h>
-#include <rtgui/rtgui_system.h>
-#include <rtgui/widgets/textview.h>
-
-rt_inline char* _get_line_text(rtgui_textview_t *textview, rt_uint16_t index)
-{
- char* line;
- if (index < textview->line_count)
- {
- line = textview->lines + (index * textview->line_width);
- return line;
- }
-
- return RT_NULL;
-}
-
-static void _calc_line(rtgui_textview_t *textview, const char* text)
-{
- char* line;
- const unsigned char* ptr;
- rt_ubase_t line_index, line_position;
-
- if (textview->lines != RT_NULL)
- {
- rt_free(textview->lines);
- textview->lines = RT_NULL;
- textview->line_count = 0;
- }
-
- /* get line count */
- line_index = 0; line_position = 0;
- ptr = (const unsigned char*)text;
- if (*ptr == 0) return;
-
- while (*ptr != '\0')
- {
- if (*ptr == '\n')
- {
- line_index ++;
- line_position = 0;
- }
- else if (*ptr == '\r')
- {
- ptr ++;
- continue;
- }
- else if (*ptr == '\t')
- {
- line_position += 4;
- if (line_position >= textview->line_width - 1)
- {
- line_index ++;
- line_position = 0;
- }
- }
- else
- {
- if ((*ptr) >= 0x80)
- {
- /* fill cjk character */
- if (line_position + 1 >= (textview->line_width - 1))
- {
- /* split to next line */
- line_index ++;
- line_position = 0;
- }
-
- line_position ++;
- line_position ++;
- }
- else
- {
- line_position ++;
- }
-
- if (line_position >= textview->line_width - 1)
- {
- line_index ++;
- line_position = 0;
- }
- }
-
- ptr ++;
- }
-
- /* set line count */
- textview->line_count = line_index + 1;
-
- /* allocate lines */
- textview->lines = rt_malloc(textview->line_count * textview->line_width);
- rt_memset(textview->lines, 0, (textview->line_count * textview->line_width));
-
- /* fill lines */
- line_index = 0; line_position = 0;
- ptr = (const unsigned char*)text;
- line = _get_line_text(textview, line_index);
- while (*ptr)
- {
- if (*ptr == '\n')
- {
- line_index ++;
- line_position = 0;
- line = _get_line_text(textview, line_index);
- }
- else if (*ptr == '\r')
- {
- /* ignore '\r' */
- ptr ++;
- continue;
- }
- else if (*ptr == '\t')
- {
- line[line_position++] = ' ';
- line[line_position++] = ' ';
- line[line_position++] = ' ';
- line[line_position++] = ' ';
- if (line_position >= textview->line_width - 1)
- {
- line_index ++;
- line_position = 0;
- line = _get_line_text(textview, line_index);
- }
- }
- else
- {
- if ((*ptr) >= 0x80)
- {
- /* fill cjk character */
- if (line_position + 1 >= (textview->line_width - 1))
- {
- /* split to next line */
- line_index ++;
- line_position = 0;
- line = _get_line_text(textview, line_index);
- }
-
- line[line_position ++] = *ptr ++;
- line[line_position ++] = *ptr;
- }
- else
- {
- line[line_position ++] = *ptr;
- }
-
- if (line_position >= textview->line_width - 1)
- {
- line_index ++;
- line_position = 0;
- line = _get_line_text(textview, line_index);
- }
- }
-
- ptr ++;
- }
-
- textview->line_current = 0;
-}
-
-static void _calc_width(rtgui_textview_t *textview)
-{
- rtgui_rect_t rect;
- rt_uint16_t width, height;
-
- width = rtgui_rect_width(RTGUI_WIDGET(textview)->extent) - 6;
- height = rtgui_rect_height(RTGUI_WIDGET(textview)->extent);
-
- rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(textview)), "W", &rect);
- textview->line_width = width / rtgui_rect_width(rect) + 1;
- textview->line_page_count = height / (rtgui_rect_height(rect) + 3);
-
- /* set minimal value */
- if (textview->line_page_count == 0) textview->line_page_count = 1;
-}
-
-static void _draw_textview(rtgui_textview_t *textview)
-{
- struct rtgui_dc* dc;
- struct rtgui_rect rect, font_rect;
- char* line;
- rt_ubase_t line_index, item_height;
-
- rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(textview)), "W", &font_rect);
- item_height = rtgui_rect_height(font_rect) + 3;
-
- dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(textview));
- if (dc == RT_NULL) return ;
-
- /* fill rect */
- rtgui_widget_get_rect(RTGUI_WIDGET(textview), &rect);
- rtgui_dc_fill_rect(dc, &rect);
-
- rect.x1 += 3;
- rect.x2 -= 3;
-
- for (line_index = textview->line_current;
- (line_index < textview->line_current + textview->line_page_count) &&
- (line_index < textview->line_count);
- line_index ++)
- {
- line = (char* )_get_line_text(textview, line_index);
- rtgui_dc_draw_text(dc, line, &rect);
-
- rect.y1 += item_height;
- }
-
- rtgui_dc_end_drawing(dc);
-}
-
-static void _rtgui_textview_constructor(rtgui_textview_t *textview)
-{
- /* init widget and set event handler */
- rtgui_widget_set_event_handler(RTGUI_WIDGET(textview), rtgui_textview_event_handler);
- RTGUI_WIDGET(textview)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
-
- /* set field */
- textview->line_count = 0;
- textview->lines = RT_NULL;
-
- textview->line_current = -1;
- textview->line_page_count = 1;
-}
-
-static void _rtgui_textview_destructor(rtgui_textview_t *textview)
-{
- /* release line memory */
- rt_free(textview->lines);
- textview->lines = RT_NULL;
-}
-
-DEFINE_CLASS_TYPE(textview, "textview",
- RTGUI_WIDGET_TYPE,
- _rtgui_textview_constructor,
- _rtgui_textview_destructor,
- sizeof(struct rtgui_textview));
-
-rt_bool_t rtgui_textview_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
-{
- struct rtgui_textview* textview;
-
- RT_ASSERT(widget != RT_NULL);
-
- textview = (struct rtgui_textview*) widget;
- switch (event->type)
- {
- case RTGUI_EVENT_PAINT:
- _draw_textview(textview);
- break;
-
- case RTGUI_EVENT_KBD:
- {
- struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
- if (ekbd->type == RTGUI_KEYDOWN)
- {
- rt_int16_t line_current_update;
- line_current_update = textview->line_current;
- if (ekbd->key == RTGUIK_LEFT)
- {
- if (textview->line_current > textview->line_page_count)
- {
- line_current_update -= textview->line_page_count;
- }
- else if (textview->line_current > 0)
- {
- line_current_update = 0;
- }
- }
- else if (ekbd->key == RTGUIK_RIGHT)
- {
- if (textview->line_current + textview->line_page_count < textview->line_count - 1)
- {
- line_current_update += textview->line_page_count;
- }
- }
- else if (ekbd->key == RTGUIK_UP)
- {
- if (textview->line_current > 0)
- {
- line_current_update --;
- }
- }
- else if (ekbd->key == RTGUIK_DOWN)
- {
- if (textview->line_current + textview->line_page_count < textview->line_count - 1)
- {
- line_current_update ++;
- }
- }
-
- if (textview->line_current != line_current_update)
- {
- textview->line_current = line_current_update;
- rtgui_widget_update(widget);
- return RT_TRUE;
- }
- }
- break;
- }
- }
-
- return RT_FALSE;
-}
-
-rtgui_textview_t* rtgui_textview_create(const char* text, const rtgui_rect_t *rect)
-{
- struct rtgui_textview* textview;
-
- textview = (struct rtgui_textview*) rtgui_widget_create(RTGUI_TEXTVIEW_TYPE);
- if (textview != RT_NULL)
- {
- rtgui_widget_set_rect(RTGUI_WIDGET(textview), rect);
-
- /* calculate line width and line page count */
- _calc_width(textview);
-
- /* set text */
- _calc_line(textview, text);
- }
-
- return textview;
-}
-
-void rtgui_textview_destroy(rtgui_textview_t* textview)
-{
- rtgui_widget_destroy(RTGUI_WIDGET(textview));
-}
-
-void rtgui_textview_set_text(rtgui_textview_t* textview, const char* text)
-{
- RT_ASSERT(textview != RT_NULL);
-
- /* calculate line width and line page count */
- _calc_width(textview);
-
- /* set text */
- _calc_line(textview, text);
-
- /* update widget */
- rtgui_widget_update(RTGUI_WIDGET(textview));
-}
+/* + * File : textview.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2011, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2011-03-05 Bernard first version + */ +#include <rtgui/dc.h> +#include <rtgui/rtgui_system.h> +#include <rtgui/widgets/textview.h> + +rt_inline char* _get_line_text(rtgui_textview_t *textview, rt_uint16_t index) +{ + char* line; + if (index < textview->line_count) + { + line = textview->lines + (index * textview->line_width); + return line; + } + + return RT_NULL; +} + +static void _calc_line(rtgui_textview_t *textview, const char* text) +{ + char* line; + const unsigned char* ptr; + rt_ubase_t line_index, line_position; + + if (textview->lines != RT_NULL) + { + rt_free(textview->lines); + textview->lines = RT_NULL; + textview->line_count = 0; + } + + /* get line count */ + line_index = 0; line_position = 0; + ptr = (const unsigned char*)text; + if (*ptr == 0) return; + + while (*ptr != '\0') + { + if (*ptr == '\n') + { + line_index ++; + line_position = 0; + } + else if (*ptr == '\r') + { + ptr ++; + continue; + } + else if (*ptr == '\t') + { + line_position += 4; + if (line_position >= textview->line_width - 1) + { + line_index ++; + line_position = 0; + } + } + else + { + if ((*ptr) >= 0x80) + { + /* fill cjk character */ + if (line_position + 1 >= (textview->line_width - 1)) + { + /* split to next line */ + line_index ++; + line_position = 0; + } + + line_position ++; + line_position ++; + } + else + { + line_position ++; + } + + if (line_position >= textview->line_width - 1) + { + line_index ++; + line_position = 0; + } + } + + ptr ++; + } + + /* set line count */ + textview->line_count = line_index + 1; + + /* allocate lines */ + textview->lines = rt_malloc(textview->line_count * textview->line_width); + rt_memset(textview->lines, 0, (textview->line_count * textview->line_width)); + + /* fill lines */ + line_index = 0; line_position = 0; + ptr = (const unsigned char*)text; + line = _get_line_text(textview, line_index); + while (*ptr) + { + if (*ptr == '\n') + { + line_index ++; + line_position = 0; + line = _get_line_text(textview, line_index); + } + else if (*ptr == '\r') + { + /* ignore '\r' */ + ptr ++; + continue; + } + else if (*ptr == '\t') + { + line[line_position++] = ' '; + line[line_position++] = ' '; + line[line_position++] = ' '; + line[line_position++] = ' '; + if (line_position >= textview->line_width - 1) + { + line_index ++; + line_position = 0; + line = _get_line_text(textview, line_index); + } + } + else + { + if ((*ptr) >= 0x80) + { + /* fill cjk character */ + if (line_position + 1 >= (textview->line_width - 1)) + { + /* split to next line */ + line_index ++; + line_position = 0; + line = _get_line_text(textview, line_index); + } + + line[line_position ++] = *ptr ++; + line[line_position ++] = *ptr; + } + else + { + line[line_position ++] = *ptr; + } + + if (line_position >= textview->line_width - 1) + { + line_index ++; + line_position = 0; + line = _get_line_text(textview, line_index); + } + } + + ptr ++; + } + + textview->line_current = 0; +} + +static void _calc_width(rtgui_textview_t *textview) +{ + rtgui_rect_t rect; + rt_uint16_t width, height; + + width = rtgui_rect_width(RTGUI_WIDGET(textview)->extent) - 6; + height = rtgui_rect_height(RTGUI_WIDGET(textview)->extent); + + rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(textview)), "W", &rect); + textview->line_width = width / rtgui_rect_width(rect) + 1; + textview->line_page_count = height / (rtgui_rect_height(rect) + 3); + + /* set minimal value */ + if (textview->line_page_count == 0) textview->line_page_count = 1; +} + +static void _draw_textview(rtgui_textview_t *textview) +{ + struct rtgui_dc* dc; + struct rtgui_rect rect, font_rect; + char* line; + rt_ubase_t line_index, item_height; + + rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(textview)), "W", &font_rect); + item_height = rtgui_rect_height(font_rect) + 3; + + dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(textview)); + if (dc == RT_NULL) return ; + + /* fill rect */ + rtgui_widget_get_rect(RTGUI_WIDGET(textview), &rect); + rtgui_dc_fill_rect(dc, &rect); + + rect.x1 += 3; + rect.x2 -= 3; + + for (line_index = textview->line_current; + (line_index < textview->line_current + textview->line_page_count) && + (line_index < textview->line_count); + line_index ++) + { + line = (char* )_get_line_text(textview, line_index); + rtgui_dc_draw_text(dc, line, &rect); + + rect.y1 += item_height; + } + + rtgui_dc_end_drawing(dc); +} + +static void _rtgui_textview_constructor(rtgui_textview_t *textview) +{ + /* init widget and set event handler */ + rtgui_object_set_event_handler(RTGUI_OBJECT(textview), rtgui_textview_event_handler); + RTGUI_WIDGET(textview)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE; + + /* set field */ + textview->line_count = 0; + textview->lines = RT_NULL; + + textview->line_current = -1; + textview->line_page_count = 1; +} + +static void _rtgui_textview_destructor(rtgui_textview_t *textview) +{ + /* release line memory */ + rt_free(textview->lines); + textview->lines = RT_NULL; +} + +DEFINE_CLASS_TYPE(textview, "textview", + RTGUI_WIDGET_TYPE, + _rtgui_textview_constructor, + _rtgui_textview_destructor, + sizeof(struct rtgui_textview)); + +rt_bool_t rtgui_textview_event_handler(struct rtgui_object* object, struct rtgui_event* event) +{ + struct rtgui_textview* textview; + RTGUI_WIDGET_EVENT_HANDLER_PREPARE + + textview = RTGUI_TEXTVIEW(object); + switch (event->type) + { + case RTGUI_EVENT_PAINT: + _draw_textview(textview); + break; + + case RTGUI_EVENT_KBD: + { + struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event; + if (ekbd->type == RTGUI_KEYDOWN) + { + rt_int16_t line_current_update; + line_current_update = textview->line_current; + if (ekbd->key == RTGUIK_LEFT) + { + if (textview->line_current > textview->line_page_count) + { + line_current_update -= textview->line_page_count; + } + else if (textview->line_current > 0) + { + line_current_update = 0; + } + } + else if (ekbd->key == RTGUIK_RIGHT) + { + if (textview->line_current + textview->line_page_count < textview->line_count - 1) + { + line_current_update += textview->line_page_count; + } + } + else if (ekbd->key == RTGUIK_UP) + { + if (textview->line_current > 0) + { + line_current_update --; + } + } + else if (ekbd->key == RTGUIK_DOWN) + { + if (textview->line_current + textview->line_page_count < textview->line_count - 1) + { + line_current_update ++; + } + } + + if (textview->line_current != line_current_update) + { + textview->line_current = line_current_update; + rtgui_widget_update(widget); + return RT_TRUE; + } + } + break; + } + } + + return RT_FALSE; +} + +rtgui_textview_t* rtgui_textview_create(const char* text, const rtgui_rect_t *rect) +{ + struct rtgui_textview* textview; + + textview = (struct rtgui_textview*) rtgui_widget_create(RTGUI_TEXTVIEW_TYPE); + if (textview != RT_NULL) + { + rtgui_widget_set_rect(RTGUI_WIDGET(textview), rect); + + /* calculate line width and line page count */ + _calc_width(textview); + + /* set text */ + _calc_line(textview, text); + } + + return textview; +} + +void rtgui_textview_destroy(rtgui_textview_t* textview) +{ + rtgui_widget_destroy(RTGUI_WIDGET(textview)); +} + +void rtgui_textview_set_text(rtgui_textview_t* textview, const char* text) +{ + RT_ASSERT(textview != RT_NULL); + + /* calculate line width and line page count */ + _calc_width(textview); + + /* set text */ + _calc_line(textview, text); + + /* update widget */ + rtgui_widget_update(RTGUI_WIDGET(textview)); +} diff --git a/components/rtgui/widgets/toplevel.c b/components/rtgui/widgets/toplevel.c index eeabcf09a8..b6882e7c3b 100644 --- a/components/rtgui/widgets/toplevel.c +++ b/components/rtgui/widgets/toplevel.c @@ -13,26 +13,25 @@ */ #include <rtgui/rtgui_system.h> #include <rtgui/widgets/toplevel.h> -extern void rtgui_topwin_do_clip(rtgui_widget_t* widget); +#include <rtgui/widgets/window.h> +#include <rtgui/widgets/title.h> static void _rtgui_toplevel_constructor(rtgui_toplevel_t *toplevel) { /* set event handler */ - rtgui_widget_set_event_handler(RTGUI_WIDGET(toplevel), rtgui_toplevel_event_handler); + rtgui_object_set_event_handler(RTGUI_OBJECT(toplevel), rtgui_toplevel_event_handler); /* set toplevel to self */ - RTGUI_WIDGET(toplevel)->toplevel = RTGUI_WIDGET(toplevel); + if (RTGUI_IS_WINTITLE(toplevel)) + RTGUI_WIDGET(toplevel)->toplevel = (struct rtgui_win*)toplevel; + else + RTGUI_WIDGET(toplevel)->toplevel = RTGUI_WIN(toplevel); /* init toplevel property */ toplevel->drawing = 0; /* hide toplevel default */ RTGUI_WIDGET_HIDE(RTGUI_WIDGET(toplevel)); - - /* set server as RT_NULL (no connected) */ - toplevel->server = RT_NULL; - /* initialize last mouse event handled widget */ - toplevel->last_mevent_widget = RT_NULL; } static void _rtgui_toplevel_destructor(rtgui_toplevel_t* toplevel) @@ -41,51 +40,35 @@ static void _rtgui_toplevel_destructor(rtgui_toplevel_t* toplevel) toplevel->drawing = 0; } -DEFINE_CLASS_TYPE(toplevel, "toplevel", +DEFINE_CLASS_TYPE(toplevel, "toplevel", RTGUI_CONTAINER_TYPE, _rtgui_toplevel_constructor, _rtgui_toplevel_destructor, sizeof(struct rtgui_toplevel)); -rt_bool_t rtgui_toplevel_event_handler(rtgui_widget_t* widget, rtgui_event_t* event) +rt_bool_t rtgui_toplevel_event_handler(struct rtgui_object* object, rtgui_event_t* event) { - rtgui_toplevel_t* toplevel = (rtgui_toplevel_t*)widget; + struct rtgui_toplevel* toplevel; + + RT_ASSERT(object != RT_NULL); + RT_ASSERT(event != RT_NULL); + + toplevel = RTGUI_TOPLEVEL(object); switch (event->type) { - case RTGUI_EVENT_KBD: - if (RTGUI_CONTAINER(toplevel)->focused != RT_NULL) - { - RTGUI_CONTAINER(toplevel)->focused->event_handler(RTGUI_CONTAINER(toplevel)->focused, event); - } - break; - case RTGUI_EVENT_CLIP_INFO: /* update toplevel clip */ rtgui_toplevel_update_clip(toplevel); break; - case RTGUI_EVENT_TIMER: - { - struct rtgui_timer* timer; - struct rtgui_event_timer* etimer = (struct rtgui_event_timer*) event; - - timer = etimer->timer; - if (timer->timeout != RT_NULL) - { - /* call timeout function */ - timer->timeout(timer, timer->user_data); - } - } - break; - case RTGUI_EVENT_COMMAND: - if (rtgui_container_dispatch_event(RTGUI_CONTAINER(widget), event) != RT_TRUE) + if (rtgui_container_dispatch_event(RTGUI_CONTAINER(object), event) != RT_TRUE) { #ifndef RTGUI_USING_SMALL_SIZE - if (widget->on_command != RT_NULL) + if (RTGUI_WIDGET(object)->on_command != RT_NULL) { - widget->on_command(widget, event); + RTGUI_WIDGET(object)->on_command(object, event); } #endif } @@ -93,38 +76,23 @@ rt_bool_t rtgui_toplevel_event_handler(rtgui_widget_t* widget, rtgui_event_t* ev break; default : - return rtgui_container_event_handler(widget, event); + return rtgui_container_event_handler(object, event); } return RT_FALSE; } -#include <rtgui/driver.h> /* to get screen rect */ - void rtgui_toplevel_update_clip(rtgui_toplevel_t* top) { - rtgui_container_t* container; + rtgui_container_t* view; struct rtgui_list_node* node; - rtgui_rect_t screen_rect; - - if (top == RT_NULL) return; - - /* reset toplevel widget clip to extent */ - rtgui_region_reset(&(RTGUI_WIDGET(top)->clip), &(RTGUI_WIDGET(top)->extent)); - - /* subtract the screen rect */ - screen_rect.x1 = screen_rect.y1 = 0; - screen_rect.x2 = rtgui_graphic_driver_get_default()->width; - screen_rect.y2 = rtgui_graphic_driver_get_default()->height; - rtgui_region_intersect_rect(&(RTGUI_WIDGET(top)->clip), &(RTGUI_WIDGET(top)->clip), - &screen_rect); - /* subtract the external rect */ - rtgui_topwin_do_clip(RTGUI_WIDGET(top)); + if (top == RT_NULL) + return; /* update the clip info of each child */ - container = RTGUI_CONTAINER(top); - rtgui_list_foreach(node, &(container->children)) + view = RTGUI_CONTAINER(top); + rtgui_list_foreach(node, &(view->children)) { rtgui_widget_t* child = rtgui_list_entry(node, rtgui_widget_t, sibling); diff --git a/components/rtgui/widgets/view.c b/components/rtgui/widgets/view.c deleted file mode 100644 index 0f35f42eb4..0000000000 --- a/components/rtgui/widgets/view.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * File : view.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2009-10-16 Bernard first version - * 2010-09-24 Bernard fix view destroy issue - */ -#include <rtgui/dc.h> -#include <rtgui/rtgui_system.h> -#include <rtgui/widgets/view.h> -#include <rtgui/widgets/workbench.h> - -static void _rtgui_view_constructor(rtgui_view_t *view) -{ - /* init view */ - rtgui_widget_set_event_handler(RTGUI_WIDGET(view), - rtgui_view_event_handler); - - view->modal_show = RT_FALSE; - view->title = RT_NULL; -} - -static void _rtgui_view_destructor(rtgui_view_t *view) -{ - /* remove view from workbench */ - if (RTGUI_WIDGET(view)->parent != RT_NULL) - { - rtgui_workbench_t *workbench; - - if (view->modal_show == RT_TRUE) - rtgui_view_end_modal(view, RTGUI_MODAL_CANCEL); - - workbench = RTGUI_WORKBENCH(RTGUI_WIDGET(view)->parent); - rtgui_workbench_remove_view(workbench, view); - } - - if (view->title != RT_NULL) - { - rt_free(view->title); - view->title = RT_NULL; - } -} - -DEFINE_CLASS_TYPE(view, "view", - RTGUI_CONTAINER_TYPE, - _rtgui_view_constructor, - _rtgui_view_destructor, - sizeof(struct rtgui_view)); - -rt_bool_t rtgui_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event) -{ - struct rtgui_view* view = (struct rtgui_view*) widget; - RT_ASSERT(widget != RT_NULL); - - switch (event->type) - { - case RTGUI_EVENT_PAINT: - { - struct rtgui_dc* dc; - struct rtgui_rect rect; - - dc = rtgui_dc_begin_drawing(widget); - if (dc == RT_NULL) return RT_FALSE; - rtgui_widget_get_rect(widget, &rect); - - /* fill view with background */ - rtgui_dc_fill_rect(dc, &rect); - - /* paint on each child */ - rtgui_container_dispatch_event(RTGUI_CONTAINER(view), event); - - rtgui_dc_end_drawing(dc); - } - break; - - default: - return rtgui_container_event_handler(widget, event); - } - - return RT_FALSE; -} - -rtgui_view_t* rtgui_view_create(const char* title) -{ - struct rtgui_view* view; - - /* allocate view */ - view = (struct rtgui_view*) rtgui_widget_create (RTGUI_VIEW_TYPE); - if (view != RT_NULL) - { - if (title != RT_NULL) - view->title = rt_strdup(title); - } - - return view; -} - -void rtgui_view_destroy(rtgui_view_t* view) -{ - if (view->modal_show == RT_TRUE) - rtgui_view_end_modal(view, RTGUI_MODAL_CANCEL); - else - { - rtgui_view_hide(view); - rtgui_widget_destroy(RTGUI_WIDGET(view)); - } -} - -#ifndef RTGUI_USING_SMALL_SIZE -void rtgui_view_set_box(rtgui_view_t* view, rtgui_box_t* box) -{ - if (view == RT_NULL || - box == RT_NULL) return; - - rtgui_container_add_child(RTGUI_CONTAINER(view), RTGUI_WIDGET(box)); - rtgui_widget_set_rect(RTGUI_WIDGET(box), &(RTGUI_WIDGET(view)->extent)); -} -#endif - -rtgui_modal_code_t rtgui_view_show(rtgui_view_t* view, rt_bool_t is_modal) -{ - rtgui_workbench_t* workbench; - - /* parameter check */ - if (view == RT_NULL) return RTGUI_MODAL_CANCEL; - - if (RTGUI_WIDGET(view)->parent == RT_NULL) - { - RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(view)); - return RTGUI_MODAL_CANCEL; - } - - workbench = RTGUI_WORKBENCH(RTGUI_WIDGET(view)->parent); - rtgui_workbench_show_view(workbench, view); - if (RTGUI_CONTAINER(view)->focused != RT_NULL) - rtgui_widget_focus(RTGUI_CONTAINER(view)->focused); - else - { - if (RTGUI_WIDGET_IS_FOCUSABLE(RTGUI_WIDGET(view))) - rtgui_widget_focus(RTGUI_WIDGET(view)); - } - - view->modal_show = is_modal; - if (is_modal == RT_TRUE) - { - /* set modal mode */ - workbench->flag |= RTGUI_WORKBENCH_FLAG_MODAL_MODE; - workbench->modal_widget = RTGUI_WIDGET(view); - - /* perform workbench event loop */ - rtgui_workbench_event_loop(workbench); - - workbench->modal_widget = RT_NULL; - return workbench->modal_code; - } - - /* no modal mode, always return modal_ok */ - return RTGUI_MODAL_OK; -} - -void rtgui_view_end_modal(rtgui_view_t* view, rtgui_modal_code_t modal_code) -{ - rtgui_workbench_t* workbench; - - /* parameter check */ - if ((view == RT_NULL) || (RTGUI_WIDGET(view)->parent == RT_NULL))return ; - - workbench = RTGUI_WORKBENCH(RTGUI_WIDGET(view)->parent); - workbench->modal_code = modal_code; - workbench->flag &= ~RTGUI_WORKBENCH_FLAG_MODAL_MODE; - - /* remove modal mode */ - view->modal_show = RT_FALSE; -} - -void rtgui_view_hide(rtgui_view_t* view) -{ - if (view == RT_NULL) return; - - if (RTGUI_WIDGET(view)->parent == RT_NULL) - { - RTGUI_WIDGET_HIDE(RTGUI_WIDGET(view)); - return; - } - - rtgui_workbench_hide_view((rtgui_workbench_t*)(RTGUI_WIDGET(view)->parent), view); -} - -char* rtgui_view_get_title(rtgui_view_t* view) -{ - RT_ASSERT(view != RT_NULL); - - return view->title; -} - -void rtgui_view_set_title(rtgui_view_t* view, const char *title) -{ - RT_ASSERT(view != RT_NULL); - - if (view->title != RT_NULL) - { - rtgui_free(view->title); - - if (title != RT_NULL) view->title = rt_strdup(title); - else view->title = RT_NULL; - } -} diff --git a/components/rtgui/widgets/widget.c b/components/rtgui/widgets/widget.c index 91a14ac27e..e639eb8bed 100644 --- a/components/rtgui/widgets/widget.c +++ b/components/rtgui/widgets/widget.c @@ -14,10 +14,11 @@ */ #include <rtgui/dc_client.h> +#include <rtgui/rtgui_application.h> #include <rtgui/widgets/widget.h> #include <rtgui/widgets/window.h> -#include <rtgui/widgets/view.h> -extern void rtgui_topwin_do_clip(rtgui_widget_t* widget);
+#include <rtgui/widgets/container.h> +#include <rtgui/widgets/notebook.h> static void _rtgui_widget_constructor(rtgui_widget_t *widget) { @@ -40,23 +41,25 @@ static void _rtgui_widget_constructor(rtgui_widget_t *widget) #endif /* set parent and toplevel root */ - widget->parent = RT_NULL; - widget->toplevel = RT_NULL; + widget->parent = RT_NULL; + widget->toplevel = RT_NULL; /* some common event handler */ - widget->on_focus_in = RT_NULL; - widget->on_focus_out = RT_NULL; + widget->on_focus_in = RT_NULL; + widget->on_focus_out = RT_NULL; + widget->on_show = RT_NULL; + widget->on_hide = RT_NULL; #ifndef RTGUI_USING_SMALL_SIZE - widget->on_draw = RT_NULL; - widget->on_mouseclick = RT_NULL; - widget->on_key = RT_NULL; - widget->on_size = RT_NULL; - widget->on_command = RT_NULL; + widget->on_draw = RT_NULL; + widget->on_mouseclick = RT_NULL; + widget->on_key = RT_NULL; + widget->on_size = RT_NULL; + widget->on_command = RT_NULL; #endif /* set default event handler */ - rtgui_widget_set_event_handler(widget,rtgui_widget_event_handler); + rtgui_object_set_event_handler(RTGUI_OBJECT(widget), rtgui_widget_event_handler); /* init user data private to 0 */ widget->user_data = 0; @@ -203,13 +206,6 @@ void rtgui_widget_move_to_logic(rtgui_widget_t* widget, int dx, int dy) } } -void rtgui_widget_set_event_handler(rtgui_widget_t* widget, rtgui_event_handler_ptr handler) -{ - RT_ASSERT(widget != RT_NULL); - - widget->event_handler = handler; -} - void rtgui_widget_get_rect(rtgui_widget_t* widget, rtgui_rect_t *rect) { RT_ASSERT(widget != RT_NULL); @@ -236,6 +232,20 @@ void rtgui_widget_set_onunfocus(rtgui_widget_t* widget, rtgui_event_handler_ptr widget->on_focus_out = handler; } +void rtgui_widget_set_onshow(rtgui_widget_t* widget, rtgui_event_handler_ptr handler) +{ + RT_ASSERT(widget != RT_NULL); + + widget->on_show = handler; +} + +void rtgui_widget_set_onhide(rtgui_widget_t* widget, rtgui_event_handler_ptr handler) +{ + RT_ASSERT(widget != RT_NULL); + + widget->on_hide = handler; +} + #ifndef RTGUI_USING_SMALL_SIZE void rtgui_widget_set_ondraw(rtgui_widget_t* widget, rtgui_event_handler_ptr handler) { @@ -280,35 +290,28 @@ void rtgui_widget_set_oncommand(rtgui_widget_t* widget, rtgui_event_handler_ptr */ void rtgui_widget_focus(rtgui_widget_t *widget) { - rtgui_container_t *parent; + struct rtgui_widget *old_focus; RT_ASSERT(widget != RT_NULL); - if (!widget->parent || !widget->toplevel) return; if (!RTGUI_WIDGET_IS_FOCUSABLE(widget) || !RTGUI_WIDGET_IS_ENABLE(widget)) return; - /* set widget as focused */ - widget->flag |= RTGUI_WIDGET_FLAG_FOCUS; - - /* get root parent container and old focused widget */ - parent = RTGUI_CONTAINER(widget->toplevel); - if (parent->focused == widget) return ; /* it's the same focused widget */ + old_focus = RTGUI_WIN(widget->toplevel)->focused_widget; + if (old_focus == widget) + return; /* it's the same focused widget */ /* unfocused the old widget */ - if (parent->focused != RT_NULL) rtgui_widget_unfocus(parent->focused); + if (old_focus != RT_NULL) + rtgui_widget_unfocus(old_focus); - /* set widget as focused widget in parent link */ - parent = RTGUI_CONTAINER(widget->parent); - do - { - parent->focused = widget; - parent = RTGUI_CONTAINER(RTGUI_WIDGET(parent)->parent); - } while ((parent != RT_NULL) && !RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(parent))); + /* set widget as focused */ + widget->flag |= RTGUI_WIDGET_FLAG_FOCUS; + RTGUI_WIN(widget->toplevel)->focused_widget = widget; /* invoke on focus in call back */ if (widget->on_focus_in != RT_NULL) - widget->on_focus_in(widget, RT_NULL); + widget->on_focus_in(RTGUI_OBJECT(widget), RT_NULL); } /** @@ -317,6 +320,7 @@ void rtgui_widget_focus(rtgui_widget_t *widget) */ void rtgui_widget_unfocus(rtgui_widget_t *widget) { + RT_ASSERT(widget != RT_NULL); if (!widget->toplevel || !RTGUI_WIDGET_IS_FOCUSED(widget)) @@ -325,7 +329,9 @@ void rtgui_widget_unfocus(rtgui_widget_t *widget) widget->flag &= ~RTGUI_WIDGET_FLAG_FOCUS; if (widget->on_focus_out != RT_NULL) - widget->on_focus_out(widget, RT_NULL); + widget->on_focus_out(RTGUI_OBJECT(widget), RT_NULL); + + RTGUI_WIN(widget->toplevel)->focused_widget = RT_NULL; /* refresh widget */ rtgui_widget_update(widget); @@ -381,47 +387,62 @@ void rtgui_widget_rect_to_logic(rtgui_widget_t* widget, rtgui_rect_t* rect) } } -rtgui_widget_t* rtgui_widget_get_toplevel(rtgui_widget_t* widget) +struct rtgui_win* rtgui_widget_get_toplevel(rtgui_widget_t* widget) { rtgui_widget_t* r; RT_ASSERT(widget != RT_NULL); - if (widget->toplevel) return widget->toplevel; + if (widget->toplevel) + return widget->toplevel; + rt_kprintf("widget->toplevel not properly set\n"); r = widget; /* get the toplevel widget */ - while (r->parent != RT_NULL) r = r->parent; + while (r->parent != RT_NULL) + r = r->parent; /* set toplevel */ - widget->toplevel = r; + widget->toplevel = RTGUI_WIN(r); - return r; + return RTGUI_WIN(r); } -rt_bool_t rtgui_widget_event_handler(rtgui_widget_t* widget, rtgui_event_t* event) +rt_bool_t rtgui_widget_event_handler(struct rtgui_object* object, rtgui_event_t* event) { #ifndef RTGUI_USING_SMALL_SIZE + struct rtgui_widget *widget; + + RT_ASSERT(object != RT_NULL); + RT_ASSERT(event != RT_NULL); + + widget = RTGUI_WIDGET(object); + switch (event->type) { case RTGUI_EVENT_PAINT: - if (widget->on_draw != RT_NULL) return widget->on_draw(widget, event); + if (widget->on_draw != RT_NULL) + return widget->on_draw(RTGUI_OBJECT(widget), event); break; case RTGUI_EVENT_KBD: - if (widget->on_key != RT_NULL) return widget->on_key(widget, event); + if (widget->on_key != RT_NULL) + return widget->on_key(RTGUI_OBJECT(widget), event); break; case RTGUI_EVENT_MOUSE_BUTTON: - if (widget->on_mouseclick != RT_NULL) return widget->on_mouseclick(widget, event); + if (widget->on_mouseclick != RT_NULL) + return widget->on_mouseclick(RTGUI_OBJECT(widget), event); break; case RTGUI_EVENT_COMMAND: - if (widget->on_command != RT_NULL) return widget->on_command(widget, event); + if (widget->on_command != RT_NULL) + return widget->on_command(RTGUI_OBJECT(widget), event); break; case RTGUI_EVENT_RESIZE: - if (widget->on_size != RT_NULL) return widget->on_size(widget, event); + if (widget->on_size != RT_NULL) + return widget->on_size(RTGUI_OBJECT(widget), event); break; } #endif @@ -441,14 +462,9 @@ void rtgui_widget_update_clip(rtgui_widget_t* widget) if (widget == RT_NULL || RTGUI_WIDGET_IS_HIDE(widget)) return; parent = widget->parent; - /* if there is no parent, do not update clip (please use toplevel widget API) */ + /* if there is no parent, there is no clip to update. */ if (parent == RT_NULL) { - if (RTGUI_IS_TOPLEVEL(widget)) - { - /* if it's toplevel widget, update it by toplevel function */ - rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(widget)); - } return; } @@ -479,7 +495,7 @@ void rtgui_widget_update_clip(rtgui_widget_t* widget) * intersect. */ - /* if it's a container object, update the clip info of children */ + /* if it's a view object, update the clip info of children */ if (RTGUI_IS_CONTAINER(widget)) { rtgui_widget_t* child; @@ -490,17 +506,25 @@ void rtgui_widget_update_clip(rtgui_widget_t* widget) rtgui_widget_update_clip(child); } } + else if (RTGUI_IS_NOTEBOOK(widget)) + { + rtgui_widget_update_clip(rtgui_notebook_get_current(RTGUI_NOTEBOOK(widget))); + } } void rtgui_widget_show(rtgui_widget_t* widget) { /* there is no parent or the parent is hide, no show at all */ if (widget->parent == RT_NULL || - RTGUI_WIDGET_IS_HIDE(widget->parent)) return; + RTGUI_WIDGET_IS_HIDE(widget->parent)) + return; /* update the clip info of widget */ RTGUI_WIDGET_UNHIDE(widget); rtgui_widget_update_clip(widget); + + if (widget->on_show != RT_NULL) + widget->on_show(RTGUI_OBJECT(widget), RT_NULL); } void rtgui_widget_hide(rtgui_widget_t* widget) @@ -521,10 +545,10 @@ void rtgui_widget_hide(rtgui_widget_t* widget) /* union widget rect */ rtgui_region_union_rect(&(parent->clip), &(parent->clip), &(widget->extent)); - - /* subtract the external rect */ - rtgui_topwin_do_clip(RTGUI_WIDGET(parent)); } + + if (widget->on_hide != RT_NULL) + widget->on_hide(RTGUI_OBJECT(widget), RT_NULL); } rtgui_color_t rtgui_widget_get_parent_foreground(rtgui_widget_t* widget) @@ -567,9 +591,11 @@ void rtgui_widget_update(rtgui_widget_t* widget) RT_ASSERT(widget != RT_NULL); - if (widget->event_handler != RT_NULL) + if (RTGUI_OBJECT(widget)->event_handler != RT_NULL) { - widget->event_handler(widget, &paint.parent); + RTGUI_OBJECT(widget)->event_handler( + RTGUI_OBJECT(widget), + &paint.parent); } } @@ -617,11 +643,9 @@ void rtgui_widget_dump(rtgui_widget_t* widget) obj = RTGUI_OBJECT(widget); rt_kprintf("widget type: %s ", obj->type->name); - if (RTGUI_IS_VIEW(widget) == RT_TRUE) - rt_kprintf(":%s ", RTGUI_VIEW(widget)->title); if (RTGUI_IS_WIN(widget) == RT_TRUE) rt_kprintf(":%s ", RTGUI_WIN(widget)->title); - if ((RTGUI_IS_LABEL(widget) == RT_TRUE) || (RTGUI_IS_BUTTON(widget) == RT_TRUE)) + else if ((RTGUI_IS_LABEL(widget) == RT_TRUE) || (RTGUI_IS_BUTTON(widget) == RT_TRUE)) rt_kprintf(":%s ", RTGUI_LABEL(widget)->text); rt_kprintf("extent(%d, %d) - (%d, %d)\n", widget->extent.x1, diff --git a/components/rtgui/widgets/window.c b/components/rtgui/widgets/window.c index c1df9379ff..f8d5db3d24 100644 --- a/components/rtgui/widgets/window.c +++ b/components/rtgui/widgets/window.c @@ -15,27 +15,37 @@ #include <rtgui/color.h> #include <rtgui/image.h> #include <rtgui/rtgui_system.h> +#include <rtgui/rtgui_server.h> +#include <rtgui/rtgui_application.h> #include <rtgui/widgets/window.h> #include <rtgui/widgets/button.h> -#include <rtgui/widgets/workbench.h> static void _rtgui_win_constructor(rtgui_win_t *win) { + RTGUI_WIDGET(win)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE; + win->parent_window = RT_NULL; /* init window attribute */ - win->on_activate = RT_NULL; - win->on_deactivate = RT_NULL; - win->on_close = RT_NULL; - win->title = RT_NULL; - win->modal_code = RTGUI_MODAL_OK; - win->modal_widget = RT_NULL; + win->on_activate = RT_NULL; + win->on_deactivate = RT_NULL; + win->on_close = RT_NULL; + win->on_key = RT_NULL; + win->title = RT_NULL; + win->modal_code = RTGUI_MODAL_OK; + + /* initialize last mouse event handled widget */ + win->last_mevent_widget = RT_NULL; + win->focused_widget = RT_NULL; /* set window hide */ RTGUI_WIDGET_HIDE(RTGUI_WIDGET(win)); /* set window style */ win->style = RTGUI_WIN_STYLE_DEFAULT; - rtgui_widget_set_event_handler(RTGUI_WIDGET(win), rtgui_win_event_handler); + + win->flag = RTGUI_WIN_FLAG_INIT; + + rtgui_object_set_event_handler(RTGUI_OBJECT(win), rtgui_win_event_handler); /* init user data */ win->user_data = 0; @@ -45,12 +55,12 @@ static void _rtgui_win_destructor(rtgui_win_t* win) { struct rtgui_event_win_destroy edestroy; - if (RTGUI_TOPLEVEL(win)->server != RT_NULL) + if (win->flag & RTGUI_WIN_FLAG_CONNECTED) { /* destroy in server */ RTGUI_EVENT_WIN_DESTROY_INIT(&edestroy); edestroy.wid = win; - if (rtgui_thread_send_sync(RTGUI_TOPLEVEL(win)->server, RTGUI_EVENT(&edestroy), + if (rtgui_server_post_event_sync(RTGUI_EVENT(&edestroy), sizeof(struct rtgui_event_win_destroy)) != RT_EOK) { /* destroy in server failed */ @@ -62,225 +72,238 @@ static void _rtgui_win_destructor(rtgui_win_t* win) rt_free(win->title); } -static rt_bool_t _rtgui_win_create_in_server(rtgui_win_t* win) +static rt_bool_t _rtgui_win_create_in_server(struct rtgui_win *win) { - if (RTGUI_TOPLEVEL(win)->server == RT_NULL) + if (!(win->flag & RTGUI_WIN_FLAG_CONNECTED)) { - rt_thread_t server; struct rtgui_event_win_create ecreate; RTGUI_EVENT_WIN_CREATE_INIT(&ecreate); - /* get server thread id */ - server = rtgui_thread_get_server(); - if (server == RT_NULL) - { - rt_kprintf("RTGUI server is not running...\n"); - return RT_FALSE; - } - /* send win create event to server */ - ecreate.wid = win; - ecreate.parent.user = win->style; + ecreate.parent_window = win->parent_window; + ecreate.wid = win; + ecreate.parent.user = win->style; #ifndef RTGUI_USING_SMALL_SIZE - ecreate.extent = RTGUI_WIDGET(win)->extent; + ecreate.extent = RTGUI_WIDGET(win)->extent; rt_strncpy((char*)ecreate.title, (char*)win->title, RTGUI_NAME_MAX); #endif - if (rtgui_thread_send_sync(server, RTGUI_EVENT(&ecreate), - sizeof(struct rtgui_event_win_create)) != RT_EOK) + if (rtgui_server_post_event_sync(RTGUI_EVENT(&ecreate), + sizeof(struct rtgui_event_win_create) + ) != RT_EOK) { rt_kprintf("create win: %s failed\n", win->title); return RT_FALSE; } - /* set server */ - RTGUI_TOPLEVEL(win)->server = server; + win->flag |= RTGUI_WIN_FLAG_CONNECTED; } return RT_TRUE; } -DEFINE_CLASS_TYPE(win, "win", +DEFINE_CLASS_TYPE(win, "win", RTGUI_TOPLEVEL_TYPE, _rtgui_win_constructor, _rtgui_win_destructor, sizeof(struct rtgui_win)); -rtgui_win_t* rtgui_win_create(rtgui_toplevel_t* parent_toplevel, const char* title, rtgui_rect_t *rect, rt_uint8_t style) +#ifdef RTGUI_USING_DESKTOP_WINDOW +static struct rtgui_win *the_desktop_window; +#endif + +rtgui_win_t* rtgui_win_create(struct rtgui_win* parent_window, + const char* title, + rtgui_rect_t *rect, + rt_uint16_t style) { struct rtgui_win* win; /* allocate win memory */ - win = (struct rtgui_win*) rtgui_widget_create (RTGUI_WIN_TYPE); - if (win != RT_NULL) + win = RTGUI_WIN(rtgui_widget_create(RTGUI_WIN_TYPE)); + if (win == RT_NULL) + return RT_NULL; + + /* set parent toplevel */ +#ifdef RTGUI_USING_DESKTOP_WINDOW + if (style & RTGUI_WIN_STYLE_DESKTOP) { - /* set parent toplevel */ - win->parent_toplevel = parent_toplevel; + RT_ASSERT(the_desktop_window == RT_NULL); + win->parent_window = RT_NULL; + the_desktop_window = win; + } + else if (parent_window == RT_NULL) + { + RT_ASSERT(the_desktop_window != RT_NULL); + win->parent_window = the_desktop_window; + } + else + win->parent_window = parent_window; +#else + win->parent_window = parent_window; +#endif - /* set title, rect and style */ - if (title != RT_NULL) win->title = rt_strdup(title); - else win->title = RT_NULL; + /* set title, rect and style */ + if (title != RT_NULL) + win->title = rt_strdup(title); + else + win->title = RT_NULL; - rtgui_widget_set_rect(RTGUI_WIDGET(win), rect); - win->style = style; + rtgui_widget_set_rect(RTGUI_WIDGET(win), rect); + win->style = style; - if (_rtgui_win_create_in_server(win) == RT_FALSE) - { - rtgui_widget_destroy(RTGUI_WIDGET(win)); - return RT_NULL; - } + if (_rtgui_win_create_in_server(win) == RT_FALSE) + { + goto __on_err; } - return win; + +__on_err: + rtgui_widget_destroy(RTGUI_WIDGET(win)); + return RT_NULL; } void rtgui_win_destroy(struct rtgui_win* win) { - if (win->style & RTGUI_WIN_STYLE_MODAL) + if (win->flag & RTGUI_WIN_FLAG_MODAL) { - /* end modal */ + /* set the RTGUI_WIN_STYLE_DESTROY_ON_CLOSE flag so the window will be + * destroyed after the event_loop */ + win->style |= RTGUI_WIN_STYLE_DESTROY_ON_CLOSE; rtgui_win_end_modal(win, RTGUI_MODAL_CANCEL); } else - { rtgui_widget_destroy(RTGUI_WIDGET(win)); +} + +static rt_bool_t _rtgui_win_deal_close(struct rtgui_win *win, + struct rtgui_event *event) +{ + if (win->on_close != RT_NULL) + { + if (win->on_close(RTGUI_OBJECT(win), event) == RT_FALSE) + return RT_FALSE; + } + + rtgui_win_hiden(win); + + win->flag |= RTGUI_WIN_FLAG_CLOSED; + + if (win->flag & RTGUI_WIN_FLAG_MODAL) + { + rtgui_win_end_modal(win, RTGUI_MODAL_CANCEL); } + else if (win->style & RTGUI_WIN_STYLE_DESTROY_ON_CLOSE) + { + rtgui_win_destroy(win); + } + + return RT_TRUE; } -void rtgui_win_close(struct rtgui_win* win) +/* send a close event to myself to get a consistent behavior */ +rt_bool_t rtgui_win_close(struct rtgui_win* win) { - win->style |= RTGUI_WIN_STYLE_CLOSED; + struct rtgui_event_win_close eclose; + + RTGUI_EVENT_WIN_CLOSE_INIT(&eclose); + eclose.wid = win; + return _rtgui_win_deal_close(win, + (struct rtgui_event*)&eclose); } -rtgui_modal_code_t rtgui_win_show(struct rtgui_win* win, rt_bool_t is_modal) +rt_base_t rtgui_win_show(struct rtgui_win* win, rt_bool_t is_modal) { - rtgui_modal_code_t result; + struct rtgui_event_win_show eshow; + rt_base_t exit_code = -1; - RT_ASSERT(win != RT_NULL); - result = RTGUI_MODAL_CANCEL; + RTGUI_EVENT_WIN_SHOW_INIT(&eshow); + eshow.wid = win; + + if (win == RT_NULL) + return exit_code; /* if it does not register into server, create it in server */ - if (RTGUI_TOPLEVEL(win)->server == RT_NULL) + if (!(win->flag & RTGUI_WIN_FLAG_CONNECTED)) { if (_rtgui_win_create_in_server(win) == RT_FALSE) - return result; + return exit_code; } - if (RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(win))) + if (rtgui_server_post_event_sync(RTGUI_EVENT(&eshow), + sizeof(struct rtgui_event_win_show) + ) != RT_EOK) { - /* send show message to server */ - struct rtgui_event_win_show eshow; - RTGUI_EVENT_WIN_SHOW_INIT(&eshow); - eshow.wid = win; + rt_kprintf("show win failed\n"); + return exit_code; + } - if (rtgui_thread_send_sync(RTGUI_TOPLEVEL(win)->server, RTGUI_EVENT(&eshow), - sizeof(struct rtgui_event_win_show)) != RT_EOK) - { - /* hide window failed */ - return result; - } + /* set window unhidden */ + RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(win)); - /* set window unhidden */ - RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(win)); - } - else rtgui_widget_update(RTGUI_WIDGET(win)); + if (win->focused_widget == RT_NULL) + rtgui_widget_focus(RTGUI_WIDGET(win)); - if (is_modal == RT_TRUE) - { - if (win->parent_toplevel != RT_NULL) - { - rtgui_widget_t *parent_widget; + if (is_modal == RT_TRUE) + { + struct rtgui_application *app; + struct rtgui_event_win_modal_enter emodal; - /* set style */ - win->style |= RTGUI_WIN_STYLE_MODAL; + RTGUI_EVENT_WIN_MODAL_ENTER_INIT(&emodal); + emodal.wid = win; - /* get root toplevel */ - parent_widget = RTGUI_WIDGET(win->parent_toplevel); - if (RTGUI_IS_WORKBENCH(parent_widget)) - { - rtgui_workbench_t* workbench; - workbench = RTGUI_WORKBENCH(win->parent_toplevel); - workbench->flag |= RTGUI_WORKBENCH_FLAG_MODAL_MODE; - workbench->modal_widget = RTGUI_WIDGET(win); + app = rtgui_application_self(); + RT_ASSERT(app != RT_NULL); - rtgui_workbench_event_loop(workbench); - result = workbench->modal_code; - workbench->flag &= ~RTGUI_WORKBENCH_FLAG_MODAL_MODE; - workbench->modal_widget = RT_NULL; - } - else if (RTGUI_IS_WIN(parent_widget)) - { - rtgui_win_t* parent_win; - parent_win = RTGUI_WIN(win->parent_toplevel); - parent_win->style |= RTGUI_WIN_STYLE_UNDER_MODAL; - parent_win->modal_widget = RTGUI_WIDGET(win); + win->flag |= RTGUI_WIN_FLAG_MODAL; - rtgui_win_event_loop(parent_win); - result = parent_win->modal_code; - parent_win->style &= ~RTGUI_WIN_STYLE_UNDER_MODAL; - parent_win->modal_widget = RT_NULL; - } - } - else - { - /* which is a root window */ - win->style |= RTGUI_WIN_STYLE_MODAL; - rtgui_win_event_loop(win); + if (rtgui_server_post_event_sync((struct rtgui_event*)&emodal, + sizeof(emodal)) != RT_EOK) + return exit_code; - result = win->modal_code; - win->style &= ~RTGUI_WIN_STYLE_MODAL; + app->modal_object = RTGUI_OBJECT(win); + + exit_code = rtgui_application_run(app); + + app->modal_object = RT_NULL; + win->flag &= ~RTGUI_WIN_FLAG_MODAL; + + if (win->style & RTGUI_WIN_STYLE_DESTROY_ON_CLOSE) + { + rtgui_win_destroy(win); } - } + } - return result; + return exit_code; } void rtgui_win_end_modal(struct rtgui_win* win, rtgui_modal_code_t modal_code) { - if (win->parent_toplevel != RT_NULL) - { - if (RTGUI_IS_WORKBENCH(win->parent_toplevel)) - { - rtgui_workbench_t* workbench; + if (win == RT_NULL || !(win->flag & RTGUI_WIN_FLAG_MODAL)) + return; - /* which is shown under workbench */ - workbench = RTGUI_WORKBENCH(win->parent_toplevel); - workbench->modal_code = modal_code; - workbench->flag &= ~RTGUI_WORKBENCH_FLAG_MODAL_MODE; - } - else if (RTGUI_IS_WIN(win->parent_toplevel)) - { - rtgui_win_t* parent_win; - - /* which is shown under win */ - parent_win = RTGUI_WIN(win->parent_toplevel); - parent_win->modal_code = modal_code; - parent_win->style &= ~RTGUI_WIN_STYLE_UNDER_MODAL; - } - } - else - { - /* which is a stand alone window */ - win->modal_code = modal_code; - } + rtgui_application_exit(rtgui_application_self(), modal_code); /* remove modal mode */ - win->style &= ~RTGUI_WIN_STYLE_MODAL; + win->flag &= ~RTGUI_WIN_FLAG_MODAL; } void rtgui_win_hiden(struct rtgui_win* win) { RT_ASSERT(win != RT_NULL); +#ifdef RTGUI_USING_DESKTOP_WINDOW + RT_ASSERT(win != the_desktop_window); +#endif if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(win)) && - RTGUI_TOPLEVEL(win)->server != RT_NULL) + win->flag & RTGUI_WIN_FLAG_CONNECTED) { /* send hidden message to server */ struct rtgui_event_win_hide ehide; RTGUI_EVENT_WIN_HIDE_INIT(&ehide); ehide.wid = win; - if (rtgui_thread_send_sync(RTGUI_TOPLEVEL(win)->server, RTGUI_EVENT(&ehide), + if (rtgui_server_post_event_sync(RTGUI_EVENT(&ehide), sizeof(struct rtgui_event_win_hide)) != RT_EOK) { rt_kprintf("hide win: %s failed\n", win->title); @@ -289,7 +312,7 @@ void rtgui_win_hiden(struct rtgui_win* win) /* set window hide and deactivated */ RTGUI_WIDGET_HIDE(RTGUI_WIDGET(win)); - win->style &= ~RTGUI_WIN_STYLE_ACTIVATE; + win->flag &= ~RTGUI_WIN_FLAG_ACTIVATE; } } @@ -297,7 +320,7 @@ rt_bool_t rtgui_win_is_activated(struct rtgui_win* win) { RT_ASSERT(win != RT_NULL); - if (win->style & RTGUI_WIN_STYLE_ACTIVATE) return RT_TRUE; + if (win->flag & RTGUI_WIN_FLAG_ACTIVATE) return RT_TRUE; return RT_FALSE; } @@ -307,28 +330,29 @@ void rtgui_win_move(struct rtgui_win* win, int x, int y) struct rtgui_event_win_move emove; RTGUI_EVENT_WIN_MOVE_INIT(&emove); - if (win == RT_NULL) return; + if (win == RT_NULL) + return; + + /* move window to logic position */ + rtgui_widget_move_to_logic(RTGUI_WIDGET(win), + x - RTGUI_WIDGET(win)->extent.x1, + y - RTGUI_WIDGET(win)->extent.y1); - if (RTGUI_TOPLEVEL(win)->server != RT_NULL) + if (win->flag & RTGUI_WIN_FLAG_CONNECTED) { /* set win hide firstly */ RTGUI_WIDGET_HIDE(RTGUI_WIDGET(win)); - emove.wid = win; + emove.wid = win; emove.x = x; emove.y = y; - if (rtgui_thread_send_sync(RTGUI_TOPLEVEL(win)->server, RTGUI_EVENT(&emove), + if (rtgui_server_post_event_sync(RTGUI_EVENT(&emove), sizeof(struct rtgui_event_win_move)) != RT_EOK) { return; } } - /* move window to logic position */ - rtgui_widget_move_to_logic(RTGUI_WIDGET(win), - x - RTGUI_WIDGET(win)->extent.x1, - y - RTGUI_WIDGET(win)->extent.y1); - /* set window visible */ RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(win)); return; @@ -342,7 +366,8 @@ static rt_bool_t rtgui_win_ondraw(struct rtgui_win* win) /* begin drawing */ dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(win)); - if (dc == RT_NULL) return RT_FALSE; + if (dc == RT_NULL) + return RT_FALSE; /* get window rect */ rtgui_widget_get_rect(RTGUI_WIDGET(win), &rect); @@ -352,18 +377,22 @@ static rt_bool_t rtgui_win_ondraw(struct rtgui_win* win) /* paint each widget */ RTGUI_EVENT_PAINT_INIT(&event); event.wid = RT_NULL; - rtgui_container_dispatch_event(RTGUI_CONTAINER(win), (rtgui_event_t*)&event); + rtgui_container_dispatch_event(RTGUI_CONTAINER(win), + (rtgui_event_t*)&event); rtgui_dc_end_drawing(dc); return RT_FALSE; } -rt_bool_t rtgui_win_event_handler(struct rtgui_widget* widget, struct rtgui_event* event) +rt_bool_t rtgui_win_event_handler(struct rtgui_object* object, struct rtgui_event* event) { - struct rtgui_win* win = (struct rtgui_win*)widget; + struct rtgui_win* win; + + RT_ASSERT(object != RT_NULL); + RT_ASSERT(event != RT_NULL); - RT_ASSERT((win != RT_NULL) && (event != RT_NULL)); + win = RTGUI_WIN(object); switch (event->type) { @@ -376,22 +405,8 @@ rt_bool_t rtgui_win_event_handler(struct rtgui_widget* widget, struct rtgui_even break; case RTGUI_EVENT_WIN_CLOSE: - if (win->on_close != RT_NULL) - { - if (win->on_close(widget, event) == RT_FALSE) return RT_TRUE; - } - - if (win->style & RTGUI_WIN_STYLE_MODAL) - { - rtgui_win_end_modal(win, RTGUI_MODAL_CANCEL); - } - else - { - /* destroy window */ - rtgui_win_destroy(win); - } - - /* exit event loop */ + _rtgui_win_deal_close(win, event); + /* don't broadcast WIN_CLOSE event to others */ return RT_TRUE; case RTGUI_EVENT_WIN_MOVE: @@ -410,49 +425,54 @@ rt_bool_t rtgui_win_event_handler(struct rtgui_widget* widget, struct rtgui_even return RT_TRUE; } - win->style |= RTGUI_WIN_STYLE_ACTIVATE; + win->flag |= RTGUI_WIN_FLAG_ACTIVATE; #ifndef RTGUI_USING_SMALL_SIZE - if (widget->on_draw != RT_NULL) widget->on_draw(widget, event); - else + if (RTGUI_WIDGET(object)->on_draw != RT_NULL) + RTGUI_WIDGET(object)->on_draw(object, event); + else #endif rtgui_widget_update(RTGUI_WIDGET(win)); if (win->on_activate != RT_NULL) { - win->on_activate(widget, event); + win->on_activate(RTGUI_OBJECT(object), event); } break; case RTGUI_EVENT_WIN_DEACTIVATE: - if (win->style & RTGUI_WIN_STYLE_MODAL) + if (win->flag & RTGUI_WIN_FLAG_MODAL) { - /* do not deactivate a modal win, re-send win-show event */ - struct rtgui_event_win_show eshow; - RTGUI_EVENT_WIN_SHOW_INIT(&eshow); - eshow.wid = win; - - rtgui_thread_send(RTGUI_TOPLEVEL(win)->server, RTGUI_EVENT(&eshow), - sizeof(struct rtgui_event_win_show)); + /* FIXME: make modal concept clear and easy. See the comment of + * rtgui_topwin_modal_enter. */ + /* There are various reason that a modal window got deactivated: + * 1, it has child windows and the user activate one of them. + * 2, the application has more than one root window and the + * user switched to one of the others. + * + * In any of the cases, we have nothing to do here. + */ } else { - win->style &= ~RTGUI_WIN_STYLE_ACTIVATE; + win->flag &= ~RTGUI_WIN_FLAG_ACTIVATE; #ifndef RTGUI_USING_SMALL_SIZE - if (widget->on_draw != RT_NULL) widget->on_draw(widget, event); - else + if (RTGUI_WIDGET(object)->on_draw != RT_NULL) + RTGUI_WIDGET(object)->on_draw(object, event); + else #endif - rtgui_win_ondraw(win); + rtgui_widget_update(RTGUI_WIDGET(win)); if (win->on_deactivate != RT_NULL) { - win->on_deactivate(widget, event); + win->on_deactivate(RTGUI_OBJECT(object), event); } } break; case RTGUI_EVENT_PAINT: #ifndef RTGUI_USING_SMALL_SIZE - if (widget->on_draw != RT_NULL) widget->on_draw(widget, event); + if (RTGUI_WIDGET(object)->on_draw != RT_NULL) + RTGUI_WIDGET(object)->on_draw(object, event); else #endif rtgui_win_ondraw(win); @@ -460,36 +480,22 @@ rt_bool_t rtgui_win_event_handler(struct rtgui_widget* widget, struct rtgui_even case RTGUI_EVENT_MOUSE_BUTTON: /* check whether has widget which handled mouse event before */ - if (RTGUI_TOPLEVEL_LAST_MEVENT_WIDGET(win) != RT_NULL) + if (win->last_mevent_widget != RT_NULL) { - struct rtgui_event_mouse* emouse; - - emouse = (struct rtgui_event_mouse*)event; - - RTGUI_TOPLEVEL_LAST_MEVENT_WIDGET(win)->event_handler(RTGUI_TOPLEVEL_LAST_MEVENT_WIDGET(win), event); - if (rtgui_rect_contains_point(&(RTGUI_TOPLEVEL_LAST_MEVENT_WIDGET(win)->extent), - emouse->x, emouse->y) == RT_EOK) - { - RTGUI_TOPLEVEL_LAST_MEVENT_WIDGET(win) = RT_NULL; - break; /* mouse event is inside of widget, do not handle it anymore */ - } + RTGUI_OBJECT(win->last_mevent_widget)->event_handler( + RTGUI_OBJECT(win->last_mevent_widget), + event); /* clean last mouse event handled widget */ - RTGUI_TOPLEVEL_LAST_MEVENT_WIDGET(win) = RT_NULL; + win->last_mevent_widget = RT_NULL; } - - if (win->style & RTGUI_WIN_STYLE_UNDER_MODAL) - { - if (win->modal_widget != RT_NULL) - return win->modal_widget->event_handler(win->modal_widget, event); - } - else if (rtgui_container_dispatch_mouse_event(RTGUI_CONTAINER(win), + else if (rtgui_container_dispatch_mouse_event(RTGUI_CONTAINER(win), (struct rtgui_event_mouse*)event) == RT_FALSE) { #ifndef RTGUI_USING_SMALL_SIZE - if (widget->on_mouseclick != RT_NULL) + if (RTGUI_WIDGET(object)->on_mouseclick != RT_NULL) { - return widget->on_mouseclick(widget, event); + return RTGUI_WIDGET(object)->on_mouseclick(object, event); } #endif } @@ -512,101 +518,45 @@ rt_bool_t rtgui_win_event_handler(struct rtgui_widget* widget, struct rtgui_even #endif break; - case RTGUI_EVENT_KBD: - if (win->style & RTGUI_WIN_STYLE_UNDER_MODAL) + case RTGUI_EVENT_KBD: + /* we should dispatch key event firstly */ + if (!(win->flag & RTGUI_WIN_FLAG_HANDLE_KEY)) { - if (win->modal_widget != RT_NULL) - return win->modal_widget->event_handler(win->modal_widget, event); + rt_bool_t res = RT_FALSE; + /* we should dispatch the key event just once. Once entered the + * dispatch mode, we should swtich to key handling mode. */ + win->flag |= RTGUI_WIN_FLAG_HANDLE_KEY; + + /* dispatch the key event */ + if (win->focused_widget != RT_NULL && + RTGUI_OBJECT(win->focused_widget)->event_handler != RT_NULL) + res = RTGUI_OBJECT(win->focused_widget)->event_handler( + RTGUI_OBJECT(win->focused_widget), event); + + /* if the focused widget doesn't handle it, I will handle it. */ + if (res != RT_TRUE && win->on_key != RT_NULL) + res = win->on_key(RTGUI_OBJECT(win), event); + + win->flag &= ~RTGUI_WIN_FLAG_HANDLE_KEY; + return res; } - else if (RTGUI_CONTAINER(win)->focused != widget && - RTGUI_CONTAINER(win)->focused != RT_NULL) + else { - RTGUI_CONTAINER(win)->focused->event_handler(RTGUI_CONTAINER(win)->focused, event); + /* in key handling mode(it may reach here in + * win->focused_widget->event_handler call) */ + if (win->on_key != RT_NULL) + return win->on_key(RTGUI_OBJECT(win), event); } - break; + break; default: /* call parent event handler */ - return rtgui_toplevel_event_handler(widget, event); + return rtgui_toplevel_event_handler(object, event); } return RT_FALSE; } -/* windows event loop */ -void rtgui_win_event_loop(rtgui_win_t* wnd) -{ - rt_err_t result; - rtgui_thread_t* tid; - struct rtgui_event* event; - - tid = rtgui_thread_self(); - RT_ASSERT(tid != RT_NULL); - - /* point to event buffer */ - event = (struct rtgui_event*)tid->event_buffer; - - if (wnd->style & RTGUI_WIN_STYLE_UNDER_MODAL) - { - while (wnd->style & RTGUI_WIN_STYLE_UNDER_MODAL) - { - if (tid->on_idle != RT_NULL) - { - result = rtgui_thread_recv_nosuspend(event, RTGUI_EVENT_BUFFER_SIZE); - if (result == RT_EOK) - { - /* perform event handler */ - RTGUI_WIDGET(wnd)->event_handler(RTGUI_WIDGET(wnd), event); - } - else if (result == -RT_ETIMEOUT) - { - tid->on_idle(RTGUI_WIDGET(wnd), RT_NULL); - } - } - else - { - result = rtgui_thread_recv(event, RTGUI_EVENT_BUFFER_SIZE); - if (result == RT_EOK) - { - /* perform event handler */ - RTGUI_WIDGET(wnd)->event_handler(RTGUI_WIDGET(wnd), event); - } - } - } - } - else - { - while (!(wnd->style & RTGUI_WIN_STYLE_CLOSED)) - { - if (tid->on_idle != RT_NULL) - { - result = rtgui_thread_recv_nosuspend(event, RTGUI_EVENT_BUFFER_SIZE); - if (result == RT_EOK) - { - /* perform event handler */ - RTGUI_WIDGET(wnd)->event_handler(RTGUI_WIDGET(wnd), event); - } - else if (result == -RT_ETIMEOUT) - { - tid->on_idle(RTGUI_WIDGET(wnd), RT_NULL); - } - } - else - { - result = rtgui_thread_recv(event, RTGUI_EVENT_BUFFER_SIZE); - if (result == RT_EOK) - { - /* perform event handler */ - RTGUI_WIDGET(wnd)->event_handler(RTGUI_WIDGET(wnd), event); - } - } - } - } - - /* destroy window */ - rtgui_widget_destroy(RTGUI_WIDGET(wnd)); -} - void rtgui_win_set_rect(rtgui_win_t* win, rtgui_rect_t* rect) { struct rtgui_event_win_resize event; @@ -615,14 +565,14 @@ void rtgui_win_set_rect(rtgui_win_t* win, rtgui_rect_t* rect) RTGUI_WIDGET(win)->extent = *rect; - if (RTGUI_TOPLEVEL(win)->server != RT_NULL) + if (win->flag & RTGUI_WIN_FLAG_CONNECTED) { /* set window resize event to server */ RTGUI_EVENT_WIN_RESIZE_INIT(&event); event.wid = win; event.rect = *rect; - rtgui_thread_send(RTGUI_TOPLEVEL(win)->server, &(event.parent), sizeof(struct rtgui_event_win_resize)); + rtgui_server_post_event(&(event.parent), sizeof(struct rtgui_event_win_resize)); } } @@ -660,10 +610,18 @@ void rtgui_win_set_onclose(rtgui_win_t* win, rtgui_event_handler_ptr handler) } } +void rtgui_win_set_onkey(rtgui_win_t* win, rtgui_event_handler_ptr handler) +{ + if (win != RT_NULL) + { + win->on_key = handler; + } +} + void rtgui_win_set_title(rtgui_win_t* win, const char *title) { /* send title to server */ - if (RTGUI_TOPLEVEL(win)->server != RT_NULL) + if (win->flag & RTGUI_WIN_FLAG_CONNECTED) { } diff --git a/components/rtgui/widgets/workbench.c b/components/rtgui/widgets/workbench.c deleted file mode 100644 index 4dd3f7e6e8..0000000000 --- a/components/rtgui/widgets/workbench.c +++ /dev/null @@ -1,581 +0,0 @@ -/* - * File : workbench.c - * This file is part of RTGUI in RT-Thread RTOS - * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2009-10-04 Bernard first version - * 2010-09-24 Bernard fix workbench destroy issue - */ -#include <rtgui/rtgui_system.h> -#include <rtgui/widgets/window.h> -#include <rtgui/widgets/workbench.h> - -static void _rtgui_workbench_constructor(rtgui_workbench_t *workbench) -{ - /* set event handler */ - rtgui_widget_set_event_handler(RTGUI_WIDGET(workbench), rtgui_workbench_event_handler); - - /* set attributes */ - workbench->flag = RTGUI_WORKBENCH_FLAG_DEFAULT; - workbench->panel = RT_NULL; - workbench->title = RT_NULL; - workbench->current_view = RT_NULL; - workbench->modal_code = RTGUI_MODAL_OK; - workbench->modal_widget = RT_NULL; -} - -static void _rtgui_workbench_destructor(rtgui_workbench_t *workbench) -{ - RT_ASSERT(workbench != RT_NULL); - - if (RTGUI_TOPLEVEL(workbench)->server != RT_NULL) - { - struct rtgui_event_panel_detach edetach; - RTGUI_EVENT_PANEL_DETACH_INIT(&edetach); - - /* detach from panel */ - edetach.panel = workbench->panel; - - /* send PANEL DETACH to server */ - if (rtgui_thread_send_sync(RTGUI_TOPLEVEL(workbench)->server, - RTGUI_EVENT(&edetach), sizeof(struct rtgui_event_panel_detach)) != RT_EOK) - return; - - RTGUI_TOPLEVEL(workbench)->server = RT_NULL; - } - - /* release title */ - rt_free(workbench->title); - workbench->title = RT_NULL; -} - -DEFINE_CLASS_TYPE(workbench, "workbench", - RTGUI_TOPLEVEL_TYPE, - _rtgui_workbench_constructor, - _rtgui_workbench_destructor, - sizeof(struct rtgui_workbench)); - -rtgui_workbench_t *rtgui_workbench_create(const char* panel_name, const unsigned char* title) -{ - struct rtgui_workbench* workbench; - - /* the server thread id */ - rt_thread_t server = rtgui_thread_get_server(); - if (server == RT_NULL) - { - rt_kprintf("can't find rtgui server\n"); - return RT_NULL; - } - - /* create workbench */ - workbench = (rtgui_workbench_t*) rtgui_widget_create (RTGUI_WORKBENCH_TYPE); - if (workbench != RT_NULL) - { - /* the buffer uses to receive event */ - union - { - struct rtgui_event_panel_attach ecreate; - struct rtgui_event_panel_info epanel; - - char buffer[256]; /* use to recv other information */ - } event; - - /* set workbench title */ - workbench->title = (unsigned char*)rt_strdup((char*)title); - - /* create application in server */ - RTGUI_EVENT_PANEL_ATTACH_INIT(&(event.ecreate)); - - /* set the panel name and workbench */ - rt_strncpy(event.ecreate.panel_name, panel_name, RTGUI_NAME_MAX); - event.ecreate.workbench = workbench; - - /* send PANEL ATTACH to server */ - if (rtgui_thread_send_sync(server, - &(event.ecreate.parent), sizeof(struct rtgui_event_panel_attach)) != RTGUI_STATUS_OK) - { - return RT_NULL; - } - - /* get PANEL INFO */ - rtgui_thread_recv_filter(RTGUI_EVENT_PANEL_INFO, &(event.epanel.parent), sizeof(event)); - - /* set panel */ - workbench->panel = (struct rtgui_panel*)event.epanel.panel; - - /* connected */ - RTGUI_TOPLEVEL(workbench)->server = server; - - /* set extent of workbench */ - rtgui_widget_set_rect(RTGUI_WIDGET(workbench), &(event.epanel.extent)); - - /* set workbench in thread */ - rtgui_thread_set_widget(RTGUI_WIDGET(workbench)); - } - - return workbench; -} - -void rtgui_workbench_destroy(rtgui_workbench_t* workbench) -{ - RT_ASSERT(workbench != RT_NULL); - - if (workbench->flag & RTGUI_WORKBENCH_FLAG_CLOSED) - { - rtgui_widget_destroy(RTGUI_WIDGET(workbench)); - } - else - { - /* just close workbench */ - rtgui_workbench_close(workbench); - } -} - -void rtgui_workbench_close(rtgui_workbench_t* workbench) -{ - /* detach workbench in server */ - if (RTGUI_TOPLEVEL(workbench)->server != RT_NULL) - { - struct rtgui_event_panel_detach edetach; - RTGUI_EVENT_PANEL_DETACH_INIT(&edetach); - - /* detach from panel */ - edetach.panel = workbench->panel; - edetach.workbench = workbench; - - /* send PANEL DETACH to server */ - if (rtgui_thread_send_sync(RTGUI_TOPLEVEL(workbench)->server, - RTGUI_EVENT(&edetach), sizeof(struct rtgui_event_panel_detach)) != RT_EOK) - return; - - RTGUI_TOPLEVEL(workbench)->server = RT_NULL; - } - - /* set status to close */ - workbench->flag |= RTGUI_WORKBENCH_FLAG_CLOSED; -} - -void rtgui_workbench_set_flag(rtgui_workbench_t* workbench, rt_uint8_t flag) -{ - RT_ASSERT(workbench != RT_NULL); - - workbench->flag = flag; -} - -rt_bool_t rtgui_workbench_event_loop(rtgui_workbench_t* workbench) -{ - rt_err_t result; - rtgui_thread_t* tid; - struct rtgui_event* event; - - tid = rtgui_thread_self(); - RT_ASSERT(tid != RT_NULL); - - /* point to event buffer */ - event = (struct rtgui_event*)tid->event_buffer; - - if (workbench->flag & RTGUI_WORKBENCH_FLAG_MODAL_MODE) - { - /* event loop for modal mode shown view */ - while (workbench->flag & RTGUI_WORKBENCH_FLAG_MODAL_MODE) - { - if (tid->on_idle != RT_NULL) - { - result = rtgui_thread_recv_nosuspend(event, RTGUI_EVENT_BUFFER_SIZE); - if (result == RT_EOK) - RTGUI_WIDGET(workbench)->event_handler(RTGUI_WIDGET(workbench), event); - else if (result == -RT_ETIMEOUT) - tid->on_idle(RTGUI_WIDGET(workbench), RT_NULL); - } - else - { - result = rtgui_thread_recv(event, RTGUI_EVENT_BUFFER_SIZE); - if (result == RT_EOK) - RTGUI_WIDGET(workbench)->event_handler(RTGUI_WIDGET(workbench), event); - } - } - } - else - { - /* show workbench firstly */ - rtgui_workbench_show(workbench); - - while (!(workbench->flag & RTGUI_WORKBENCH_FLAG_CLOSED)) - { - if (tid->on_idle != RT_NULL) - { - result = rtgui_thread_recv_nosuspend(event, RTGUI_EVENT_BUFFER_SIZE); - if (result == RT_EOK) - RTGUI_WIDGET(workbench)->event_handler(RTGUI_WIDGET(workbench), event); - else if (result == -RT_ETIMEOUT) - tid->on_idle(RTGUI_WIDGET(workbench), RT_NULL); - } - else - { - result = rtgui_thread_recv(event, RTGUI_EVENT_BUFFER_SIZE); - if (result == RT_EOK) - RTGUI_WIDGET(workbench)->event_handler(RTGUI_WIDGET(workbench), event); - } - } - } - - return RT_TRUE; -} - -rt_err_t rtgui_workbench_show(rtgui_workbench_t* workbench) -{ - RT_ASSERT(workbench != RT_NULL); - - if (RTGUI_TOPLEVEL(workbench)->server != RT_NULL) - { - struct rtgui_event_panel_show eraise; - RTGUI_EVENT_PANEL_SHOW_INIT(&eraise); - eraise.workbench = workbench; - - eraise.panel = workbench->panel; - if (rtgui_thread_send_sync(workbench->parent.server, RTGUI_EVENT(&eraise), - sizeof(struct rtgui_event_panel_show)) != RT_EOK) - return -RT_ERROR; - - RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(workbench)); - rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(workbench)); - } - else return -RT_ERROR; - - return RT_EOK; -} - -rt_err_t rtgui_workbench_hide(rtgui_workbench_t* workbench) -{ - if (RTGUI_TOPLEVEL(workbench)->server != RT_NULL) - { - struct rtgui_event_panel_hide ehide; - RTGUI_EVENT_PANEL_HIDE_INIT(&ehide); - - RT_ASSERT(workbench != RT_NULL); - if (workbench->parent.server == RT_NULL) return -RT_ERROR; - - ehide.panel = workbench->panel; - if (rtgui_thread_send_sync(RTGUI_TOPLEVEL(workbench)->server, RTGUI_EVENT(&ehide), - sizeof(struct rtgui_event_panel_hide)) != RT_EOK) - return -RT_ERROR; - - RTGUI_WIDGET_HIDE(RTGUI_WIDGET(workbench)); - rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(workbench)); - } - - return RT_EOK; -} - -rt_bool_t rtgui_workbench_event_handler(rtgui_widget_t* widget, rtgui_event_t* event) -{ - struct rtgui_workbench* workbench = (struct rtgui_workbench*)widget; - - switch (event->type) - { - case RTGUI_EVENT_PANEL_DETACH: - RTGUI_WIDGET_HIDE(RTGUI_WIDGET(workbench)); - RTGUI_TOPLEVEL(workbench)->server = RT_NULL; - return RT_TRUE; - - case RTGUI_EVENT_PANEL_SHOW: - /* show workbench in server */ - rtgui_workbench_show(workbench); - break; - - case RTGUI_EVENT_PANEL_HIDE: - /* hide widget */ - RTGUI_WIDGET_HIDE(widget); - break; - - case RTGUI_EVENT_MOUSE_MOTION: - { - struct rtgui_event_mouse* emouse = (struct rtgui_event_mouse*)event; - struct rtgui_toplevel* top = RTGUI_TOPLEVEL(emouse->wid); - - /* check the destination window */ - if (top != RT_NULL && RTGUI_WIDGET(top)->event_handler != RT_NULL) - { - RTGUI_WIDGET(top)->event_handler(RTGUI_WIDGET(top), event); - } - else - { - /* let viewer to handle it */ - rtgui_view_t* view = workbench->current_view; - if (view != RT_NULL && - RTGUI_WIDGET(view)->event_handler != RT_NULL) - { - RTGUI_WIDGET(view)->event_handler(RTGUI_WIDGET(view), event); - } - } - } - break; - - case RTGUI_EVENT_MOUSE_BUTTON: - { - struct rtgui_event_mouse* emouse = (struct rtgui_event_mouse*)event; - struct rtgui_toplevel* top = RTGUI_TOPLEVEL(emouse->wid); - - /* check whether has widget which handled mouse event before */ - if (RTGUI_TOPLEVEL_LAST_MEVENT_WIDGET(workbench) != RT_NULL) - { - struct rtgui_event_mouse* emouse; - - emouse = (struct rtgui_event_mouse*)event; - - RTGUI_TOPLEVEL_LAST_MEVENT_WIDGET(workbench)->event_handler(RTGUI_TOPLEVEL_LAST_MEVENT_WIDGET(workbench), event); - if (rtgui_rect_contains_point(&(RTGUI_TOPLEVEL_LAST_MEVENT_WIDGET(workbench)->extent), - emouse->x, emouse->y) == RT_EOK) - { - RTGUI_TOPLEVEL_LAST_MEVENT_WIDGET(workbench) = RT_NULL; - break; /* mouse event is inside of widget, do not handle it anymore */ - } - - /* clean last mouse event handled widget */ - RTGUI_TOPLEVEL_LAST_MEVENT_WIDGET(workbench) = RT_NULL; - } - - /* check the destination window */ - if (top != RT_NULL && RTGUI_WIDGET(top)->event_handler != RT_NULL) - { - RTGUI_WIDGET(top)->event_handler(RTGUI_WIDGET(top), event); - } - else - { - if (RTGUI_WORKBENCH_IS_MODAL_MODE(workbench)) - { - /* let modal widget to handle it */ - if (workbench->modal_widget != RT_NULL && - workbench->modal_widget->event_handler != RT_NULL) - { - workbench->modal_widget->event_handler(workbench->modal_widget, event); - } - } - else - { - /* let viewer to handle it */ - rtgui_view_t* view = workbench->current_view; - if (view != RT_NULL && - RTGUI_WIDGET(view)->event_handler != RT_NULL) - { - RTGUI_WIDGET(view)->event_handler(RTGUI_WIDGET(view), event); - } - } - } - } - break; - - case RTGUI_EVENT_KBD: - { - struct rtgui_event_kbd* kbd = (struct rtgui_event_kbd*)event; - struct rtgui_toplevel* top = RTGUI_TOPLEVEL(kbd->wid); - - /* check the destination window */ - if (top != RT_NULL && RTGUI_WIDGET(top)->event_handler != RT_NULL) - { - RTGUI_WIDGET(top)->event_handler(RTGUI_WIDGET(top), event); - } - else - { - if (RTGUI_WORKBENCH_IS_MODAL_MODE(workbench)) - { - /* let modal widget to handle it */ - if (workbench->modal_widget != RT_NULL && - workbench->modal_widget->event_handler != RT_NULL) - { - workbench->modal_widget->event_handler(workbench->modal_widget, event); - } - } - else - { - if (RTGUI_CONTAINER(widget)->focused == widget) - { - /* set focused widget to the current view */ - if (workbench->current_view != RT_NULL) - rtgui_widget_focus(RTGUI_WIDGET(RTGUI_CONTAINER(workbench->current_view)->focused)); - } - - return rtgui_toplevel_event_handler(widget, event); - } - } - } - break; - - case RTGUI_EVENT_PAINT: - { - struct rtgui_event_paint* epaint = (struct rtgui_event_paint*)event; - struct rtgui_toplevel* top = RTGUI_TOPLEVEL(epaint->wid); - - /* check the destination window */ - if (top != RT_NULL && RTGUI_WIDGET(top)->event_handler != RT_NULL) - { - RTGUI_WIDGET(top)->event_handler(RTGUI_WIDGET(top), event); - } - else - { - rtgui_view_t* view; - - /* un-hide workbench */ - RTGUI_WIDGET_UNHIDE(widget); - - /* paint a view */ - view = workbench->current_view; - if (view != RT_NULL) - { - /* remake a paint event */ - RTGUI_EVENT_PAINT_INIT(epaint); - epaint->wid = RT_NULL; - - /* send this event to the view */ - if (RTGUI_WIDGET(view)->event_handler != RT_NULL) - { - RTGUI_WIDGET(view)->event_handler(RTGUI_WIDGET(view), event); - } - } - else - { - struct rtgui_dc* dc; - struct rtgui_rect rect; - - dc = rtgui_dc_begin_drawing(widget); - rtgui_widget_get_rect(widget, &rect); - rtgui_dc_fill_rect(dc, &rect); - rtgui_dc_end_drawing(dc); - } - } - } - break; - - case RTGUI_EVENT_CLIP_INFO: - { - struct rtgui_event_clip_info* eclip = (struct rtgui_event_clip_info*)event; - struct rtgui_widget* dest_widget = RTGUI_WIDGET(eclip->wid); - - if (dest_widget != RT_NULL && dest_widget->event_handler != RT_NULL) - { - dest_widget->event_handler(dest_widget, event); - } - else - { - return rtgui_toplevel_event_handler(widget, event); - } - } - break; - - case RTGUI_EVENT_WIN_CLOSE: - case RTGUI_EVENT_WIN_ACTIVATE: - case RTGUI_EVENT_WIN_DEACTIVATE: - { - struct rtgui_event_win* wevent = (struct rtgui_event_win*)event; - struct rtgui_widget* dest_widget = RTGUI_WIDGET(wevent->wid); - if (dest_widget != RT_NULL && dest_widget->event_handler != RT_NULL) - { - dest_widget->event_handler(dest_widget, event); - } - } - break; - - case RTGUI_EVENT_WIN_MOVE: - { - struct rtgui_event_win_move* wevent = (struct rtgui_event_win_move*)event; - struct rtgui_toplevel* top = RTGUI_TOPLEVEL(wevent->wid); - if (top != RT_NULL && RTGUI_WIDGET(top)->event_handler != RT_NULL) - { - RTGUI_WIDGET(top)->event_handler(RTGUI_WIDGET(top), event); - } - } - break; - - default: - return rtgui_toplevel_event_handler(widget, event); - } - - return RT_TRUE; -} - -/* - * - * view on workbench - * - */ - -void rtgui_workbench_add_view(rtgui_workbench_t* workbench, rtgui_view_t* view) -{ - rtgui_container_add_child(RTGUI_CONTAINER(workbench), RTGUI_WIDGET(view)); - /* hide view in default */ - RTGUI_WIDGET_HIDE(RTGUI_WIDGET(view)); - - /* reset view extent */ - rtgui_widget_set_rect(RTGUI_WIDGET(view), &(RTGUI_WIDGET(workbench)->extent)); -} - -void rtgui_workbench_remove_view(rtgui_workbench_t* workbench, rtgui_view_t* view) -{ - if (view == workbench->current_view) - rtgui_workbench_hide_view(workbench, view); - - rtgui_container_remove_child(RTGUI_CONTAINER(workbench), RTGUI_WIDGET(view)); -} - -void rtgui_workbench_show_view(rtgui_workbench_t* workbench, rtgui_view_t* view) -{ - RT_ASSERT(workbench != RT_NULL); - RT_ASSERT(view != RT_NULL); - - /* already shown */ - if (workbench->current_view == view) return; - - if (workbench->current_view != RT_NULL) - { - /* hide old view */ - RTGUI_WIDGET_HIDE(RTGUI_WIDGET(workbench->current_view)); - } - - /* show view */ - RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(view)); - workbench->current_view = view; - - /* update workbench clip */ - rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(workbench)); - - if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(workbench))) - { - rtgui_widget_update(RTGUI_WIDGET(view)); - } -} - -void rtgui_workbench_hide_view(rtgui_workbench_t* workbench, rtgui_view_t* view) -{ - RT_ASSERT(workbench != RT_NULL); - RT_ASSERT(view != RT_NULL); - - /* hide view */ - RTGUI_WIDGET_HIDE(RTGUI_WIDGET(view)); - - if (view == workbench->current_view) - { - rtgui_view_t *next_view; - - workbench->current_view = RT_NULL; - - next_view = RTGUI_VIEW(rtgui_widget_get_next_sibling(RTGUI_WIDGET(view))); - if (next_view == RT_NULL) - next_view = RTGUI_VIEW(rtgui_widget_get_prev_sibling(RTGUI_WIDGET(view))); - - if (next_view != RT_NULL) - { - rtgui_view_show(next_view, RT_FALSE); - } - else - { - /* update workbench clip */ - rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(workbench)); - } - } -} |
