From 601eb6fe70aa10e4bf62f7a68915dc1ad7b37553 Mon Sep 17 00:00:00 2001
From: "dzzxzz@gmail.com" <dzzxzz@gmail.com>
Date: Fri, 14 Dec 2012 03:34:24 +0000
Subject: [PATCH] sync RTGUI with github(https://github.com/RT-Thread/RTGUI)
 c4b8c0ac2a3de482357b88d584931831aed7c8ae As always, full log is in GitHub.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2481 bbd45198-f89e-11dd-88c7-29a3b14d5316
---
 components/rtgui/common/font.c                |  3 +
 .../rtgui/include/rtgui/widgets/button.h      | 11 ++++
 .../rtgui/include/rtgui/widgets/textbox.h     |  2 +-
 components/rtgui/widgets/button.c             | 32 ++++++----
 components/rtgui/widgets/listctrl.c           | 61 +++++++------------
 components/rtgui/widgets/textbox.c            |  2 +-
 6 files changed, 60 insertions(+), 51 deletions(-)

diff --git a/components/rtgui/common/font.c b/components/rtgui/common/font.c
index 8739b0b4b..f2518f8cf 100644
--- a/components/rtgui/common/font.c
+++ b/components/rtgui/common/font.c
@@ -70,11 +70,13 @@ void rtgui_font_system_add_font(struct rtgui_font *font)
     if (font->engine->font_load != RT_NULL)
         font->engine->font_load(font);
 }
+RTM_EXPORT(rtgui_font_system_add_font);
 
 void rtgui_font_system_remove_font(struct rtgui_font *font)
 {
     rtgui_list_remove(&_rtgui_font_list, &(font->list));
 }
+RTM_EXPORT(rtgui_font_system_remove_font);
 
 struct rtgui_font *rtgui_font_default()
 {
@@ -105,6 +107,7 @@ struct rtgui_font *rtgui_font_refer(const char *family, rt_uint16_t height)
 
     return RT_NULL;
 }
+RTM_EXPORT(rtgui_font_refer);
 
 void rtgui_font_derefer(struct rtgui_font *font)
 {
diff --git a/components/rtgui/include/rtgui/widgets/button.h b/components/rtgui/include/rtgui/widgets/button.h
index c414b1796..b81c88281 100644
--- a/components/rtgui/include/rtgui/widgets/button.h
+++ b/components/rtgui/include/rtgui/widgets/button.h
@@ -68,6 +68,17 @@ extern "C" {
     void rtgui_button_set_pressed_image(rtgui_button_t *btn, rtgui_image_t *image);
     void rtgui_button_set_unpressed_image(rtgui_button_t *btn, rtgui_image_t *image);
 
+    /** Set the callback function on button btn
+     *
+     * If the btn is a push button, the callback will be invoked every
+     * time the btn got "pushed", i.e., both pressed down @em and pressed
+     * up.  If the button is a normal button, the callback will be invoked when
+     * the btn got "clicked", i.e., when pressed up @em after pressed
+     * down.
+     *
+     * @param btn the btn that the callback will be setted on.
+     * @param func the callback function.
+     */
     void rtgui_button_set_onbutton(rtgui_button_t *btn, rtgui_onbutton_func_t func);
 
     rt_bool_t rtgui_button_event_handler(struct rtgui_object *object, struct rtgui_event *event);
diff --git a/components/rtgui/include/rtgui/widgets/textbox.h b/components/rtgui/include/rtgui/widgets/textbox.h
index 918e98d16..e6c1d008a 100644
--- a/components/rtgui/include/rtgui/widgets/textbox.h
+++ b/components/rtgui/include/rtgui/widgets/textbox.h
@@ -76,7 +76,7 @@ rt_bool_t rtgui_textbox_event_handler(struct rtgui_object *object, struct rtgui_
 void rtgui_textbox_set_value(struct rtgui_textbox *box, const char *text);
 const char *rtgui_textbox_get_value(struct rtgui_textbox *box);
 void rtgui_textbox_set_mask_char(rtgui_textbox_t *box, const char ch);
-const char rtgui_textbox_get_mask_char(rtgui_textbox_t *box);
+char rtgui_textbox_get_mask_char(rtgui_textbox_t *box);
 void rtgui_textbox_set_line_length(struct rtgui_textbox *box, rt_size_t length);
 
 void rtgui_textbox_get_edit_rect(struct rtgui_textbox *box, rtgui_rect_t *rect);
diff --git a/components/rtgui/widgets/button.c b/components/rtgui/widgets/button.c
index 6f1f7984f..ca15acb89 100644
--- a/components/rtgui/widgets/button.c
+++ b/components/rtgui/widgets/button.c
@@ -156,10 +156,24 @@ rt_bool_t rtgui_button_event_handler(struct rtgui_object *object, struct rtgui_e
                 {
                     /* set the last mouse event handled widget */
                     struct rtgui_win *win;
+                    /* need callback */
+                    rt_bool_t need_cb = RT_FALSE;
 
                     win = RTGUI_WIN(RTGUI_WIDGET(btn)->toplevel);
                     win->last_mevent_widget = RTGUI_WIDGET(btn);
 
+                    /* we need to decide whether the callback will be invoked
+                     * before the flag has changed. Moreover, we cannot invoke
+                     * it directly here, because the button might be destroyed
+                     * in the callback. If that happens, program will crash on
+                     * the following code. We need to make sure that the
+                     * callbacks are invoke at the very last step. */
+                    if ((btn->flag & RTGUI_BUTTON_FLAG_PRESS)
+                        && (emouse->button & RTGUI_MOUSE_BUTTON_UP))
+                    {
+                        need_cb = RT_TRUE;
+                    }
+
                     /* it's a normal button */
                     if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN)
                     {
@@ -173,20 +187,16 @@ rt_bool_t rtgui_button_event_handler(struct rtgui_object *object, struct rtgui_e
                     /* draw button */
                     rtgui_theme_draw_button(btn);
 
-#ifndef RTGUI_USING_SMALL_SIZE
-                    /* invokes call back */
-                    if (widget->on_mouseclick != RT_NULL &&
-                            emouse->button & RTGUI_MOUSE_BUTTON_UP)
-                        return widget->on_mouseclick(RTGUI_OBJECT(widget), event);
-#endif
-
-                    if (!(btn->flag & RTGUI_BUTTON_FLAG_PRESS) && (btn->on_button != RT_NULL))
+                    if (need_cb)
                     {
-                        /* call on button handler */
-                        btn->on_button(RTGUI_OBJECT(widget), event);
+                        if (btn->on_button)
+                            btn->on_button(RTGUI_OBJECT(widget), event);
+#ifndef RTGUI_USING_SMALL_SIZE
+                        if (widget->on_mouseclick)
+                            return widget->on_mouseclick(RTGUI_OBJECT(widget), event);
+#endif
                     }
                 }
-
             }
 
             return RT_TRUE;
diff --git a/components/rtgui/widgets/listctrl.c b/components/rtgui/widgets/listctrl.c
index 8c6409c08..ee74bb261 100644
--- a/components/rtgui/widgets/listctrl.c
+++ b/components/rtgui/widgets/listctrl.c
@@ -105,16 +105,18 @@ static void _rtgui_listctrl_scrollbar_onmouse(struct rtgui_listctrl *ctrl, struc
     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);
+            rtgui_listctrl_set_current_item(ctrl, ctrl->current_item - ctrl->page_items);
+        else
+            rtgui_listctrl_update_current(ctrl, old_item);
     }
     else if (mouse->y > rect.y2)
     {
+        rt_uint16_t new_item;
         if (ctrl->current_item + ctrl->page_items < ctrl->items_count - 1)
-            ctrl->current_item += ctrl->page_items;
+            new_item = 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);
+            new_item = ((ctrl->current_item / ctrl->page_items) + 1) * ctrl->page_items;
+        rtgui_listctrl_set_current_item(ctrl, new_item);
     }
 }
 
@@ -166,7 +168,7 @@ static void _rtgui_listctrl_ondraw(struct rtgui_listctrl *ctrl)
     rtgui_dc_end_drawing(dc);
 }
 
-void rtgui_listctrl_update_current(struct rtgui_listctrl *ctrl, rt_uint16_t old_item)
+static void rtgui_listctrl_update_current(struct rtgui_listctrl *ctrl, rt_uint16_t old_item)
 {
     struct rtgui_dc *dc;
     rtgui_rect_t rect, item_rect;
@@ -214,7 +216,6 @@ void rtgui_listctrl_update_current(struct rtgui_listctrl *ctrl, rt_uint16_t old_
 
     rtgui_dc_end_drawing(dc);
 }
-RTM_EXPORT(rtgui_listctrl_update_current);
 
 rt_bool_t rtgui_listctrl_event_handler(struct rtgui_object *object, struct rtgui_event *event)
 {
@@ -288,24 +289,10 @@ rt_bool_t rtgui_listctrl_event_handler(struct rtgui_object *object, struct rtgui
             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);
-                    }
+                    rtgui_listctrl_set_current_item(ctrl,
+                            (ctrl->current_item / ctrl->page_items) * ctrl->page_items + index);
                 }
             }
         }
@@ -318,38 +305,36 @@ rt_bool_t rtgui_listctrl_event_handler(struct rtgui_object *object, struct rtgui
         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);
+                    rtgui_listctrl_set_current_item(ctrl, ctrl->current_item - ctrl->page_items);
                 return RT_TRUE;
 
             case RTGUIK_UP:
                 if (ctrl->current_item > 0)
-                    ctrl->current_item --;
-                rtgui_listctrl_update_current(ctrl, old_item);
+                    rtgui_listctrl_set_current_item(ctrl, ctrl->current_item-1);
                 return RT_TRUE;
 
             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;
+                    rt_uint16_t new_item = ctrl->items_count;
+                    if (ctrl->current_item + ctrl->page_items < ctrl->items_count - 1)
+                        new_item = ctrl->current_item + ctrl->page_items;
+                    else
+                    {
+                        if ((((ctrl->current_item / ctrl->page_items) + 1) * ctrl->page_items)
+                                < ctrl->items_count - 1)
+                            new_item = ((ctrl->current_item / ctrl->page_items) + 1) * ctrl->page_items;
+                    }
+                    rtgui_listctrl_set_current_item(ctrl, new_item);
                 }
-                rtgui_listctrl_update_current(ctrl, old_item);
                 return RT_TRUE;
 
             case RTGUIK_DOWN:
                 if (ctrl->current_item < ctrl->items_count - 1)
-                    ctrl->current_item ++;
-                rtgui_listctrl_update_current(ctrl, old_item);
+                    rtgui_listctrl_set_current_item(ctrl, ctrl->current_item+1);
                 return RT_TRUE;
 
             case RTGUIK_RETURN:
diff --git a/components/rtgui/widgets/textbox.c b/components/rtgui/widgets/textbox.c
index 9dd2cafca..53642aeed 100644
--- a/components/rtgui/widgets/textbox.c
+++ b/components/rtgui/widgets/textbox.c
@@ -605,7 +605,7 @@ void rtgui_textbox_set_mask_char(rtgui_textbox_t *box, const char ch)
 	box->mask_char = ch;
 }
 
-const char rtgui_textbox_get_mask_char(rtgui_textbox_t *box)
+char rtgui_textbox_get_mask_char(rtgui_textbox_t *box)
 {
 	return box->mask_char;
 }