Browse Source

sync with github f5619cb8ad5e4f581e3b2f6a44be4ddd5b432e59
As always, full log is in GitHub.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2253 bbd45198-f89e-11dd-88c7-29a3b14d5316

dzzxzz@gmail.com 12 years ago
parent
commit
e6a9dd1922
59 changed files with 3008 additions and 441 deletions
  1. 2 0
      components/rtgui/SConscript
  2. 29 4
      components/rtgui/common/dc.c
  3. 10 2
      components/rtgui/common/dc_client.c
  4. 5 0
      components/rtgui/common/dc_hw.c
  5. 17 17
      components/rtgui/common/font_bmp.c
  6. 2 2
      components/rtgui/common/font_freetype.c
  7. 108 108
      components/rtgui/common/font_hz_file.c
  8. 5 5
      components/rtgui/common/image_bmp.c
  9. 27 27
      components/rtgui/common/image_container.c
  10. 7 0
      components/rtgui/common/region.c
  11. 27 5
      components/rtgui/common/rtgui_app.c
  12. 37 2
      components/rtgui/common/rtgui_system.c
  13. 64 57
      components/rtgui/common/rtgui_theme.c
  14. 2 2
      components/rtgui/include/rtgui/color.h
  15. 2 0
      components/rtgui/include/rtgui/dc.h
  16. 3 1
      components/rtgui/include/rtgui/event.h
  17. 1 0
      components/rtgui/include/rtgui/region.h
  18. 16 1
      components/rtgui/include/rtgui/rtgui.h
  19. 14 11
      components/rtgui/include/rtgui/rtgui_app.h
  20. 6 4
      components/rtgui/include/rtgui/rtgui_config.h
  21. 13 0
      components/rtgui/include/rtgui/rtgui_object.h
  22. 6 1
      components/rtgui/include/rtgui/rtgui_system.h
  23. 1 1
      components/rtgui/include/rtgui/widgets/box.h
  24. 129 0
      components/rtgui/include/rtgui/widgets/edit.h
  25. 73 0
      components/rtgui/include/rtgui/widgets/groupbox.h
  26. 1 0
      components/rtgui/include/rtgui/widgets/iconbox.h
  27. 2 0
      components/rtgui/include/rtgui/widgets/listctrl.h
  28. 22 0
      components/rtgui/include/rtgui/widgets/notebook.h
  29. 7 1
      components/rtgui/include/rtgui/widgets/panel.h
  30. 24 20
      components/rtgui/include/rtgui/widgets/widget.h
  31. 11 9
      components/rtgui/include/rtgui/widgets/window.h
  32. 24 1
      components/rtgui/server/mouse.c
  33. 1 0
      components/rtgui/server/mouse.h
  34. 5 5
      components/rtgui/server/topwin.c
  35. 41 17
      components/rtgui/widgets/box.c
  36. 3 3
      components/rtgui/widgets/button.c
  37. 1 1
      components/rtgui/widgets/checkbox.c
  38. 4 4
      components/rtgui/widgets/combobox.c
  39. 1 1
      components/rtgui/widgets/container.c
  40. 1666 0
      components/rtgui/widgets/edit.c
  41. 13 5
      components/rtgui/widgets/filelist_view.c
  42. 155 0
      components/rtgui/widgets/groupbox.c
  43. 33 16
      components/rtgui/widgets/iconbox.c
  44. 3 2
      components/rtgui/widgets/label.c
  45. 6 6
      components/rtgui/widgets/list_view.c
  46. 4 4
      components/rtgui/widgets/listbox.c
  47. 30 18
      components/rtgui/widgets/listctrl.c
  48. 6 6
      components/rtgui/widgets/menu.c
  49. 239 27
      components/rtgui/widgets/notebook.c
  50. 2 2
      components/rtgui/widgets/progressbar.c
  51. 7 7
      components/rtgui/widgets/radiobox.c
  52. 4 4
      components/rtgui/widgets/scrollbar.c
  53. 1 1
      components/rtgui/widgets/slider.c
  54. 15 15
      components/rtgui/widgets/textbox.c
  55. 5 5
      components/rtgui/widgets/textview.c
  56. 4 3
      components/rtgui/widgets/title.c
  57. 1 1
      components/rtgui/widgets/toplevel.c
  58. 46 3
      components/rtgui/widgets/widget.c
  59. 15 4
      components/rtgui/widgets/window.c

+ 2 - 0
components/rtgui/SConscript

@@ -67,6 +67,8 @@ widgets/filelist_view.c
 widgets/widget.c
 widgets/window.c
 widgets/panel.c
+widgets/groupbox.c
+widgets/edit.c
 """)
 
 # The set of source files associated with this SConscript file.

+ 29 - 4
components/rtgui/common/dc.c

@@ -290,6 +290,31 @@ void rtgui_dc_draw_text (struct rtgui_dc* dc, const char* text, struct rtgui_rec
 	rtgui_font_draw(font, dc, text, len, &text_rect);
 }
 
+void rtgui_dc_draw_text_stroke (struct rtgui_dc* dc, const char* text, struct rtgui_rect* rect,
+	rtgui_color_t color_stroke, rtgui_color_t color_core)
+{
+	int x, y;
+	rtgui_rect_t r;
+	rtgui_color_t fc;
+	
+	RT_ASSERT(dc != RT_NULL);
+	
+	fc = RTGUI_DC_FC(dc);
+	RTGUI_DC_FC(dc) = color_stroke;
+	for(x=-1; x<2; x++)
+	{
+		for(y=-1; y<2; y++)
+		{
+			r = *rect;
+			rtgui_rect_moveto(&r, x, y);
+			rtgui_dc_draw_text(dc, text, &r);
+		}
+	}
+	RTGUI_DC_FC(dc) = color_core;
+	rtgui_dc_draw_text(dc, text, rect);
+	RTGUI_DC_FC(dc) = fc;
+}
+
 /*
  * draw a monochrome color bitmap data
  */
@@ -424,8 +449,8 @@ void rtgui_dc_draw_regular_polygon(struct rtgui_dc* dc, int x, int y, int r, int
 	* Pointer setup
 	*/
 
-	x_head = xx = (int *)rt_malloc(sizeof(int) * count);
-	y_head = yy = (int *)rt_malloc(sizeof(int) * count);
+	x_head = xx = (int *)rtgui_malloc(sizeof(int) * count);
+	y_head = yy = (int *)rtgui_malloc(sizeof(int) * count);
 
     for(i = 0; i < count; i++)
     {
@@ -445,8 +470,8 @@ void rtgui_dc_draw_regular_polygon(struct rtgui_dc* dc, int x, int y, int r, int
     
     rtgui_dc_draw_polygon(dc, (const int *)x_head, (const int *)y_head, count);  
 
-	rt_free(x_head);
-	rt_free(y_head);
+	rtgui_free(x_head);
+	rtgui_free(y_head);
 
 }
 

+ 10 - 2
components/rtgui/common/dc_client.c

@@ -47,18 +47,26 @@ static void rtgui_dc_client_get_rect(struct rtgui_dc* dc, rtgui_rect_t* rect);
 
 struct rtgui_dc* rtgui_dc_begin_drawing(rtgui_widget_t* owner)
 {
+	struct rtgui_dc* dc;
 	RT_ASSERT(owner != RT_NULL);
 
+	rtgui_screen_lock(RT_WAITING_FOREVER);
+
 	if ((rtgui_region_is_flat(&owner->clip) == RT_EOK) &&
 		rtgui_rect_is_equal(&(owner->extent), &(owner->clip.extents)) == RT_EOK)
-		return rtgui_dc_hw_create(owner);
+		dc = rtgui_dc_hw_create(owner);
 	else
-		return rtgui_dc_client_create(owner);
+		dc = rtgui_dc_client_create(owner);
+
+	if (dc == RT_NULL) rtgui_screen_unlock();
+
+	return dc;
 }
 
 void rtgui_dc_end_drawing(struct rtgui_dc* dc)
 {
 	dc->engine->fini(dc);
+	rtgui_screen_unlock();
 }
 
 const struct rtgui_dc_engine dc_client_engine =

+ 5 - 0
components/rtgui/common/dc_hw.c

@@ -22,6 +22,8 @@
 #include <rtgui/widgets/window.h>
 #include <rtgui/widgets/title.h>
 
+#define _int_swap(x, y)			do {x ^= y; y ^= x; x ^= y;} while (0)
+
 static void rtgui_dc_hw_draw_point(struct rtgui_dc* dc, int x, int y);
 static void rtgui_dc_hw_draw_color_point(struct rtgui_dc* dc, int x, int y, rtgui_color_t color);
 static void rtgui_dc_hw_draw_hline(struct rtgui_dc* dc, int x1, int x2, int y);
@@ -267,6 +269,7 @@ static void rtgui_dc_hw_draw_vline(struct rtgui_dc* self, int x, int y1, int y2)
 	x = x + dc->owner->extent.x1;
 	y1 = y1 + dc->owner->extent.y1;
 	y2 = y2 + dc->owner->extent.y1;
+	if (y1 > y2) _int_swap(y1, y2);
 
 	/* draw vline */
 	dc->hw_driver->ops->draw_vline(&(dc->owner->gc.foreground), x, y1, y2);
@@ -285,6 +288,7 @@ static void rtgui_dc_hw_draw_hline(struct rtgui_dc* self, int x1, int x2, int y)
 	/* convert logic to device */
 	x1 = x1 + dc->owner->extent.x1;
 	x2 = x2 + dc->owner->extent.x1;
+	if (x1 > x2) _int_swap(x1, x2);	
 	y  = y + dc->owner->extent.y1;
 
 	/* draw hline */
@@ -323,6 +327,7 @@ static void rtgui_dc_hw_blit_line (struct rtgui_dc* self, int x1, int x2, int y,
 	/* convert logic to device */
 	x1 = x1 + dc->owner->extent.x1;
 	x2 = x2 + dc->owner->extent.x1;
+	if (x1 > x2) _int_swap(x1, x2);	
 	y  = y + dc->owner->extent.y1;
 
 	dc->hw_driver->ops->draw_raw_hline(line_data, x1, x2, y);

+ 17 - 17
components/rtgui/common/font_bmp.c

@@ -31,8 +31,8 @@ void rtgui_bitmap_font_draw_char(struct rtgui_font_bitmap* font, struct rtgui_dc
 {
 	rtgui_color_t bc;
 	const rt_uint8_t* font_ptr;
-	rt_uint16_t x, y, h, style;
-	register rt_base_t i, j, k, word_bytes;
+	rt_uint16_t x, y, w, h, style;
+	register rt_base_t i, j, /*k,*/ word_bytes;
 
 	/* check first and last char */
 	if (ch < font->first_char || ch > font->last_char) return;
@@ -54,25 +54,21 @@ void rtgui_bitmap_font_draw_char(struct rtgui_font_bitmap* font, struct rtgui_dc
 		word_bytes = ((font->char_width[ch - font->first_char] - 1)/8) + 1;
 		font_ptr = font->bmp + font->offset[ch - font->first_char];
 	}
-
+	w = (font->width  + x > rect->x2) ? rect->x2 - rect->x1 : font->width;
 	h = (font->height + y > rect->y2) ? rect->y2 - rect->y1 : font->height;
 
-	for (i = 0; i < h; i++)
+	for(i = 0; i < h; i++)
 	{
-		for (j = 0; j < word_bytes; j++)
+		rt_uint8_t chr;
+		const rt_uint8_t *ptr = font_ptr + i * word_bytes;
+		for(j = 0; j < w; j++)
 		{
-			for (k = 0; k < 8; k++)
-			{
-				if (((font_ptr[i * word_bytes + j] >> (7 - k)) & 0x01) != 0)
-				{
-					/* draw a pixel */
-					rtgui_dc_draw_point(dc, k + 8 * j + x, i + y);
-				}
-				else if (style & RTGUI_TEXTSTYLE_DRAW_BACKGROUND)
-				{
-					rtgui_dc_draw_color_point(dc, k + 8 * j + x, i + y, bc);
-				}
-			}
+			if(j % 8 == 0)chr = *ptr++;
+			if(chr & 0x80)
+				rtgui_dc_draw_point(dc, j + x, i + y);
+			else if (style & RTGUI_TEXTSTYLE_DRAW_BACKGROUND)
+				rtgui_dc_draw_color_point(dc, j + x, i + y, bc);
+			chr <<= 1;
 		}
 	}
 }
@@ -87,6 +83,8 @@ static void rtgui_bitmap_font_draw_text(struct rtgui_font* font, struct rtgui_dc
 
 	RT_ASSERT(bmp_font != RT_NULL);
 
+	if (rect->y1 > rect->y2) return;
+
 	hz_font = rtgui_font_refer("hz", font->height);
 	while ((rect->x1 < rect->x2) && len)
 	{
@@ -121,6 +119,8 @@ static void rtgui_bitmap_font_draw_text(struct rtgui_font* font, struct rtgui_dc
 	if (hz_font != RT_NULL) rtgui_font_derefer(hz_font);
 
 #else
+	if (rect->y1 > rect->y2) return;
+
 	while ((rect->x1 < rect->x2) && len)
 	{
 		length = 0;

+ 2 - 2
components/rtgui/common/font_freetype.c

@@ -163,7 +163,7 @@ rtgui_font_t* rtgui_freetype_font_create(const char* filename, int bold, int ita
 		freetype = (struct rtgui_freetype_font*) rtgui_malloc (sizeof(struct rtgui_freetype_font));
 		if (freetype == RT_NULL)
 		{
-			rt_free(font);
+			rtgui_free(font);
 			font = RT_NULL;
 		}
 		else
@@ -173,7 +173,7 @@ rtgui_font_t* rtgui_freetype_font_create(const char* filename, int bold, int ita
 			{
 				FT_Done_FreeType(freetype->library);
 
-				rt_free(font);
+				rtgui_free(font);
 				font = RT_NULL;
 			}
 			else

+ 108 - 108
components/rtgui/common/font_hz_file.c

@@ -18,10 +18,10 @@ static void rtgui_hz_file_font_draw_text(struct rtgui_font* font, struct rtgui_d
 static void rtgui_hz_file_font_get_metrics(struct rtgui_font* font, const char* text, rtgui_rect_t* rect);
 const struct rtgui_font_engine rtgui_hz_file_font_engine =
 {
-	RT_NULL,
-	rtgui_hz_file_font_load,
-	rtgui_hz_file_font_draw_text,
-	rtgui_hz_file_font_get_metrics
+    RT_NULL,
+    rtgui_hz_file_font_load,
+    rtgui_hz_file_font_draw_text,
+    rtgui_hz_file_font_get_metrics
 };
 
 SPLAY_PROTOTYPE(cache_tree, hz_cache, hz_node, _font_cache_compare);
@@ -42,26 +42,26 @@ static rt_uint8_t* _font_cache_get(struct rtgui_hz_file_font* font, rt_uint16_t
 
     search.hz_id = hz_id;
 
-	/* enter critical */
-	rtgui_enter_critical();
+    /* enter critical */
+    rtgui_enter_critical();
 
-	cache = SPLAY_FIND(cache_tree, &(font->cache_root), &search);
+    cache = SPLAY_FIND(cache_tree, &(font->cache_root), &search);
     if (cache != RT_NULL)
     {
-		/* exit critical */
-		rtgui_exit_critical();
+        /* exit critical */
+        rtgui_exit_critical();
 
         /* found it */
         return (rt_uint8_t*)(cache + 1);
     }
 
-	/* exit critical */
-	rtgui_exit_critical();
+    /* exit critical */
+    rtgui_exit_critical();
 
-	/* can not find it, load to cache */
+    /* can not find it, load to cache */
     cache = (struct hz_cache*) rtgui_malloc(sizeof(struct hz_cache) + font->font_data_size);
     if (cache == RT_NULL)
-		return RT_NULL; /* no memory yet */
+        return RT_NULL; /* no memory yet */
 
     cache->hz_id = hz_id;
     seek = 94 * (((hz_id & 0xff) - 0xA0) - 1) + ((hz_id >> 8) - 0xA0) - 1;
@@ -76,14 +76,10 @@ static rt_uint8_t* _font_cache_get(struct rtgui_hz_file_font* font, rt_uint16_t
         return RT_NULL;
     }
 
-	/* enter critical */
-	rtgui_enter_critical();
+    /* enter critical */
+    rtgui_enter_critical();
 
-	/* insert to cache */
-    SPLAY_INSERT(cache_tree, &(font->cache_root), cache);
-	font->cache_size ++;
-
-    if (font->cache_size > HZ_CACHE_MAX)
+    if (font->cache_size >= HZ_CACHE_MAX)
     {
         /* remove a cache */
         struct hz_cache* left;
@@ -92,12 +88,16 @@ static rt_uint8_t* _font_cache_get(struct rtgui_hz_file_font* font, rt_uint16_t
 
         /* remove the left node */
         SPLAY_REMOVE(cache_tree, &(font->cache_root), left);
-		rtgui_free(left);
-		font->cache_size --;
+        rtgui_free(left);
+        font->cache_size --;
     }
 
-	/* exit critical */
-	rtgui_exit_critical();
+    /* insert to cache */
+    SPLAY_INSERT(cache_tree, &(font->cache_root), cache);
+    font->cache_size ++;
+
+    /* exit critical */
+    rtgui_exit_critical();
 
     return (rt_uint8_t*)(cache + 1);
 }
@@ -112,93 +112,93 @@ static void rtgui_hz_file_font_load(struct rtgui_font* font)
 
 static void _rtgui_hz_file_font_draw_text(struct rtgui_hz_file_font* hz_file_font, struct rtgui_dc* dc, const char* text, rt_ubase_t len, struct rtgui_rect* rect)
 {
-	rt_uint8_t* str;
-	rtgui_color_t bc;
-	rt_uint16_t style;
-	register rt_base_t h, word_bytes;
+    rt_uint8_t* str;
+    rtgui_color_t bc;
+    rt_uint16_t style;
+    register rt_base_t h, word_bytes;
 
-	/* get text style */
-	style = rtgui_dc_get_gc(dc)->textstyle;
-	bc = rtgui_dc_get_gc(dc)->background;
+    /* get text style */
+    style = rtgui_dc_get_gc(dc)->textstyle;
+    bc = rtgui_dc_get_gc(dc)->background;
 
-	/* drawing height */
-	h = (hz_file_font->font_size + rect->y1 > rect->y2)?
+    /* drawing height */
+    h = (hz_file_font->font_size + rect->y1 > rect->y2)?
         rect->y2 - rect->y1 : hz_file_font->font_size;
-	word_bytes = (hz_file_font->font_size + 7) / 8;
-
-	str = (rt_uint8_t*)text;
-
-	while (len > 0 && rect->x1 < rect->x2)
-	{
-		const rt_uint8_t* font_ptr;
-		register rt_base_t i, j, k;
-
-		/* get font pixel data */
-		font_ptr = _font_cache_get(hz_file_font, *str | (*(str+1) << 8));
-
-		/* draw word */
-		for (i=0; i < h; i ++)
-		{
-			for (j=0; j < word_bytes; j++)
-				for (k=0; k < 8; k++)
-				{
-					if ( ((font_ptr[i*word_bytes + j] >> (7-k)) & 0x01) != 0 &&
-						(rect->x1 + 8 * j + k < rect->x2))
-					{
-						rtgui_dc_draw_point(dc, rect->x1 + 8*j + k, rect->y1 + i);
-					}
-					else if (style & RTGUI_TEXTSTYLE_DRAW_BACKGROUND)
-					{
-						rtgui_dc_draw_color_point(dc, rect->x1 + 8*j + k, rect->y1 + i, bc);
-					}
-				}
-		}
-
-		/* move x to next character */
-		rect->x1 += hz_file_font->font_size;
-		str += 2;
-		len -= 2;
-	}
+    word_bytes = (hz_file_font->font_size + 7) / 8;
+
+    str = (rt_uint8_t*)text;
+
+    while (len > 0 && rect->x1 < rect->x2)
+    {
+        const rt_uint8_t* font_ptr;
+        register rt_base_t i, j, k;
+
+        /* get font pixel data */
+        font_ptr = _font_cache_get(hz_file_font, *str | (*(str+1) << 8));
+
+        /* draw word */
+        for (i=0; i < h; i ++)
+        {
+            for (j=0; j < word_bytes; j++)
+                for (k=0; k < 8; k++)
+                {
+                    if ( ((font_ptr[i*word_bytes + j] >> (7-k)) & 0x01) != 0 &&
+                        (rect->x1 + 8 * j + k < rect->x2))
+                    {
+                        rtgui_dc_draw_point(dc, rect->x1 + 8*j + k, rect->y1 + i);
+                    }
+                    else if (style & RTGUI_TEXTSTYLE_DRAW_BACKGROUND)
+                    {
+                        rtgui_dc_draw_color_point(dc, rect->x1 + 8*j + k, rect->y1 + i, bc);
+                    }
+                }
+        }
+
+        /* move x to next character */
+        rect->x1 += hz_file_font->font_size;
+        str += 2;
+        len -= 2;
+    }
 }
 
 static void rtgui_hz_file_font_draw_text(struct rtgui_font* font, struct rtgui_dc* dc, const char* text, rt_ubase_t length, struct rtgui_rect* rect)
 {
-	rt_uint32_t len;
-	struct rtgui_font *efont;
-	struct rtgui_hz_file_font* hz_file_font = (struct rtgui_hz_file_font*)font->data;
-
-	RT_ASSERT(dc != RT_NULL);
-	RT_ASSERT(hz_file_font != RT_NULL);
-
-	/* get English font */
-	efont = rtgui_font_refer("asc", hz_file_font->font_size);
-	if (efont == RT_NULL) efont = rtgui_font_default(); /* use system default font */
-
-	while (length > 0)
-	{
-		len = 0;
-		while (((rt_uint8_t)*(text + len)) < 0x80 && *(text + len) && len < length) len ++;
-		/* draw text with English font */
-		if (len > 0)
-		{
-			rtgui_font_draw(efont, dc, text, len, rect);
-
-			text += len;
-			length -= len;
-		}
-
-		len = 0;
-		while (((rt_uint8_t)*(text + len)) >= 0x80 && len < length) len ++;
-		if (len > 0)
-		{
-			_rtgui_hz_file_font_draw_text(hz_file_font, dc, text, len, rect);
-
-			text += len;
-			length -= len;
-		}
-	}
-
-	rtgui_font_derefer(efont);
+    rt_uint32_t len;
+    struct rtgui_font *efont;
+    struct rtgui_hz_file_font* hz_file_font = (struct rtgui_hz_file_font*)font->data;
+
+    RT_ASSERT(dc != RT_NULL);
+    RT_ASSERT(hz_file_font != RT_NULL);
+
+    /* get English font */
+    efont = rtgui_font_refer("asc", hz_file_font->font_size);
+    if (efont == RT_NULL) efont = rtgui_font_default(); /* use system default font */
+
+    while (length > 0)
+    {
+        len = 0;
+        while (((rt_uint8_t)*(text + len)) < 0x80 && *(text + len) && len < length) len ++;
+        /* draw text with English font */
+        if (len > 0)
+        {
+            rtgui_font_draw(efont, dc, text, len, rect);
+
+            text += len;
+            length -= len;
+        }
+
+        len = 0;
+        while (((rt_uint8_t)*(text + len)) >= 0x80 && len < length) len ++;
+        if (len > 0)
+        {
+            _rtgui_hz_file_font_draw_text(hz_file_font, dc, text, len, rect);
+
+            text += len;
+            length -= len;
+        }
+    }
+
+    rtgui_font_derefer(efont);
 }
 
 static void rtgui_hz_file_font_get_metrics(struct rtgui_font* font, const char* text, rtgui_rect_t* rect)
@@ -206,9 +206,9 @@ static void rtgui_hz_file_font_get_metrics(struct rtgui_font* font, const char*
     struct rtgui_hz_file_font* hz_file_font = (struct rtgui_hz_file_font*)font->data;
     RT_ASSERT(hz_file_font != RT_NULL);
 
-	/* set metrics rect */
-	rect->x1 = rect->y1 = 0;
-	rect->x2 = (rt_int16_t)(hz_file_font->font_size/2 * rt_strlen((const char*)text));
-	rect->y2 = hz_file_font->font_size;
+    /* set metrics rect */
+    rect->x1 = rect->y1 = 0;
+    rect->x2 = (rt_int16_t)(hz_file_font->font_size/2 * rt_strlen((const char*)text));
+    rect->y2 = hz_file_font->font_size;
 }
 #endif

+ 5 - 5
components/rtgui/common/image_bmp.c

@@ -172,7 +172,7 @@ static rt_bool_t rtgui_image_bmp_load(struct rtgui_image *image, struct rtgui_fi
 
     do
     {
-        wrkBuffer = (rt_uint8_t *)rt_malloc(BMP_WORKING_BUFFER_SIZE);
+        wrkBuffer = (rt_uint8_t *)rtgui_malloc(BMP_WORKING_BUFFER_SIZE);
         if (wrkBuffer == RT_NULL)
         {
             rt_kprintf("BMP err: no mem\n");
@@ -470,13 +470,13 @@ static rt_bool_t rtgui_image_bmp_load(struct rtgui_image *image, struct rtgui_fi
         }
 
         /* Release memory */
-        rt_free(wrkBuffer);
+        rtgui_free(wrkBuffer);
         return RT_TRUE;
     }
     while (0);
 
     /* Release memory */
-    rt_free(wrkBuffer);
+    rtgui_free(wrkBuffer);
     rtgui_free(image->palette);
     rtgui_free(bmp->pixels);
     rtgui_free(bmp);
@@ -602,7 +602,7 @@ static void rtgui_image_bmp_blit(struct rtgui_image *image, struct rtgui_dc *dc,
                 }
             }
 
-            wrkBuffer = (rt_uint8_t *)rt_malloc(
+            wrkBuffer = (rt_uint8_t *)rtgui_malloc(
 					(BMP_WORKING_BUFFER_SIZE > bmp->pitch) ? \
 					bmp->pitch : BMP_WORKING_BUFFER_SIZE);
             if (wrkBuffer == RT_NULL)
@@ -770,7 +770,7 @@ static void rtgui_image_bmp_blit(struct rtgui_image *image, struct rtgui_dc *dc,
                 break;
             }
             /* Release memory */
-            rt_free(wrkBuffer);
+            rtgui_free(wrkBuffer);
 //            rt_kprintf("BMP: load to display\n");
         }
         else

+ 27 - 27
components/rtgui/common/image_container.c

@@ -12,16 +12,16 @@ typedef void (*rtgui_user_func_t) (const void* value, const void* data);
 rtgui_hash_table_t* hash_table_create(rtgui_hash_func_t hash_func, rtgui_equal_func_t key_equal_func);
 void hash_table_destroy (rtgui_hash_table_t* hash_table);
 
-void* hash_table_find (rtgui_hash_table_t* hash_table, void* key);
-void hash_table_insert (rtgui_hash_table_t* hash_table, void* key, void* value);
-rt_bool_t hash_table_remove (rtgui_hash_table_t* hash_table, void* key);
+void* hash_table_find (rtgui_hash_table_t* hash_table, const void* key);
+void hash_table_insert (rtgui_hash_table_t* hash_table, const void* key, void* value);
+rt_bool_t hash_table_remove (rtgui_hash_table_t* hash_table, const void* key);
 
 void hash_table_foreach(rtgui_hash_table_t* hash_table, rtgui_user_func_t user_func, void* data);
 unsigned int hash_table_get_size (rtgui_hash_table_t* hash_table);
 
 /* Hash Functions
  */
-unsigned int direct_hash (void* v);
+unsigned int direct_hash (const void* v);
 
 #define HASH_TABLE_MIN_SIZE 11
 #define HASH_TABLE_MAX_SIZE 6247
@@ -87,8 +87,8 @@ static const unsigned int primes[] =
 static const unsigned int nprimes = sizeof (primes) / sizeof (primes[0]);
 
 static void hash_table_resize (rtgui_hash_table_t *hash_table);
-static rtgui_hash_node_t** hash_table_find_node (rtgui_hash_table_t *hash_table, void* key);
-static rtgui_hash_node_t* hash_node_create (void* key, void* value);
+static rtgui_hash_node_t** hash_table_find_node (rtgui_hash_table_t *hash_table, const void* key);
+static rtgui_hash_node_t* hash_node_create (const void* key, void* value);
 static void hash_node_destroy (rtgui_hash_node_t *hash_node);
 static void hash_nodes_destroy (rtgui_hash_node_t *hash_node);
 static unsigned int primes_closest (unsigned int num);
@@ -106,7 +106,7 @@ rt_inline unsigned int primes_closest (unsigned int num)
 }
 
 /* directly hash */
-unsigned int direct_hash (void* v)
+unsigned int direct_hash (const void* v)
 {
 	return (unsigned int)v;
 }
@@ -115,18 +115,18 @@ rtgui_hash_table_t* hash_table_create(rtgui_hash_func_t hash_func, rtgui_equal_f
 {
 	rtgui_hash_table_t *hash_table;
 
-	hash_table = (rtgui_hash_table_t*) rt_malloc (sizeof(rtgui_hash_table_t));
+	hash_table = (rtgui_hash_table_t*) rtgui_malloc (sizeof(rtgui_hash_table_t));
 	if (hash_table != RT_NULL)
 	{
 		hash_table->size               = HASH_TABLE_MIN_SIZE;
 		hash_table->nnodes             = 0;
 		hash_table->hash_func          = hash_func ? hash_func : direct_hash;
 		hash_table->key_equal_func     = key_equal_func;
-		hash_table->nodes              = (rtgui_hash_node_t **)rt_malloc ( sizeof(rtgui_hash_node_t*) * hash_table->size);
+		hash_table->nodes              = (rtgui_hash_node_t **)rtgui_malloc ( sizeof(rtgui_hash_node_t*) * hash_table->size);
 		if (hash_table->nodes == RT_NULL)
 		{
 			/* no memory yet */
-			rt_free(hash_table);
+			rtgui_free(hash_table);
 			return RT_NULL;
 		}
 
@@ -145,11 +145,11 @@ void hash_table_destroy (rtgui_hash_table_t *hash_table)
 	for (i = 0; i < hash_table->size; i++)
 		hash_nodes_destroy (hash_table->nodes[i]);
 
-	rt_free (hash_table->nodes);
-	rt_free (hash_table);
+	rtgui_free (hash_table->nodes);
+	rtgui_free (hash_table);
 }
 
-static rtgui_hash_node_t** hash_table_find_node (rtgui_hash_table_t *hash_table, void* key)
+static rtgui_hash_node_t** hash_table_find_node (rtgui_hash_table_t *hash_table, const void* key)
 {
 	rtgui_hash_node_t **node;
 
@@ -165,7 +165,7 @@ static rtgui_hash_node_t** hash_table_find_node (rtgui_hash_table_t *hash_table,
 	return node;
 }
 
-void* hash_table_find (rtgui_hash_table_t* hash_table, void* key)
+void* hash_table_find (rtgui_hash_table_t* hash_table, const void* key)
 {
 	rtgui_hash_node_t *node;
 
@@ -178,7 +178,7 @@ void* hash_table_find (rtgui_hash_table_t* hash_table, void* key)
 	else return RT_NULL;
 }
 
-void hash_table_insert (rtgui_hash_table_t *hash_table, void* key, void* value)
+void hash_table_insert (rtgui_hash_table_t *hash_table, const void* key, void* value)
 {
 	rtgui_hash_node_t **node;
 
@@ -197,7 +197,7 @@ void hash_table_insert (rtgui_hash_table_t *hash_table, void* key, void* value)
 	}
 }
 
-rt_bool_t hash_table_remove (rtgui_hash_table_t *hash_table, void*  key)
+rt_bool_t hash_table_remove (rtgui_hash_table_t *hash_table, const void*  key)
 {
 	rtgui_hash_node_t **node, *dest;
 
@@ -258,7 +258,7 @@ static void hash_table_resize (rtgui_hash_table_t *hash_table)
 	i = primes_closest(hash_table->nnodes);
 	new_size = i > HASH_TABLE_MAX_SIZE ? HASH_TABLE_MAX_SIZE : i < HASH_TABLE_MIN_SIZE ? HASH_TABLE_MIN_SIZE : i ;
 
-	new_nodes = (rtgui_hash_node_t **)rt_malloc ( sizeof(rtgui_hash_node_t*) * new_size);
+	new_nodes = (rtgui_hash_node_t **)rtgui_malloc ( sizeof(rtgui_hash_node_t*) * new_size);
 	if (new_nodes == RT_NULL) return; /* no memory yet */
 	rt_memset(new_nodes, 0, sizeof(rtgui_hash_node_t*) * new_size);
 
@@ -275,7 +275,7 @@ static void hash_table_resize (rtgui_hash_table_t *hash_table)
 		}
 	}
 
-	rt_free (hash_table->nodes);
+	rtgui_free (hash_table->nodes);
 	hash_table->nodes = new_nodes;
 	hash_table->size = new_size;
 }
@@ -284,7 +284,7 @@ static rtgui_hash_node_t* hash_node_create (void* key, void* value)
 {
 	rtgui_hash_node_t *hash_node;
 
-	hash_node = (rtgui_hash_node_t*) rt_malloc ( sizeof(rtgui_hash_node_t) );
+	hash_node = (rtgui_hash_node_t*) rtgui_malloc ( sizeof(rtgui_hash_node_t) );
 	if (hash_node != RT_NULL)
 	{
 		/* set value and key */
@@ -299,7 +299,7 @@ static rtgui_hash_node_t* hash_node_create (void* key, void* value)
 
 static void hash_node_destroy (rtgui_hash_node_t *hash_node)
 {
-	rt_free(hash_node);
+	rtgui_free(hash_node);
 }
 
 static void hash_nodes_destroy (rtgui_hash_node_t *hash_node)
@@ -316,12 +316,12 @@ static void hash_nodes_destroy (rtgui_hash_node_t *hash_node)
 
 			temp = node;
 			node = node->next;
-			rt_free(temp);
+			rtgui_free(temp);
 		}
 
 		node->key = NULL;
 		node->value = NULL;
-		rt_free(node);
+		rtgui_free(node);
 	}
 }
 
@@ -372,14 +372,14 @@ rtgui_image_item_t* rtgui_image_container_get(const char* filename)
 	item = hash_table_find(image_hash_table, filename);
 	if (item == RT_NULL)
 	{
-		item = (struct rtgui_image_item*) rt_malloc (sizeof(struct rtgui_image_item));
+		item = (struct rtgui_image_item*) rtgui_malloc (sizeof(struct rtgui_image_item));
 		if (item == RT_NULL) return RT_NULL;
 
 		/* create a image object */
 		item->image = rtgui_image_create(filename, load_image);
 		if (item->image == RT_NULL)
 		{
-			rt_free(item);
+			rtgui_free(item);
 			return RT_NULL; /* create image failed */
 		}
 
@@ -407,14 +407,14 @@ rtgui_image_item_t* rtgui_image_container_get_memref(const char* type, const rt_
 	item = hash_table_find(image_hash_table, filename);
 	if (item == RT_NULL)
 	{
-		item = (struct rtgui_image_item*) rt_malloc (sizeof(struct rtgui_image_item));
+		item = (struct rtgui_image_item*) rtgui_malloc (sizeof(struct rtgui_image_item));
 		if (item == RT_NULL) return RT_NULL;
 
 		/* create image object */
 		item->image = rtgui_image_create_from_mem(type, memory, length, load_image);
 		if (item->image == RT_NULL)
 		{
-			rt_free(item);
+			rtgui_free(item);
 			return RT_NULL; /* create image failed */
 		}
 
@@ -438,7 +438,7 @@ void rtgui_image_container_put(rtgui_image_item_t* item)
 		/* destroy image and image item */
 		rt_free(item->filename);
 		rtgui_image_destroy(item->image);
-		rt_free(item);
+		rtgui_free(item);
 	}
 }
 

+ 7 - 0
components/rtgui/common/region.c

@@ -2266,3 +2266,10 @@ int rtgui_rect_is_equal(const rtgui_rect_t *rect1, const rtgui_rect_t *rect2)
 
 	return -RT_ERROR;
 }
+
+rt_bool_t rtgui_rect_is_empty(const rtgui_rect_t *rect)
+{
+	if (rtgui_rect_is_equal(rect, &rtgui_empty_rect) == RT_EOK) return RT_TRUE;
+	return RT_FALSE;
+}
+

+ 27 - 5
components/rtgui/common/rtgui_app.c

@@ -1,5 +1,5 @@
 /*
- * File      : rtgui_application.c
+ * File      : rtgui_app.c
  * This file is part of RTGUI in RT-Thread RTOS
  * COPYRIGHT (C) 2012, RT-Thread Development Team
  *
@@ -24,6 +24,7 @@ static void _rtgui_app_constructor(struct rtgui_app *app)
 			                       rtgui_app_event_handler);
 
 	app->name           = RT_NULL;
+	app->icon 			= RT_NULL;
 	/* set EXITED so we can destroy an application that just created */
 	app->state_flag     = RTGUI_APP_FLAG_EXITED;
 	app->ref_count      = 0;
@@ -240,6 +241,10 @@ rt_bool_t rtgui_app_event_handler(struct rtgui_object* object, rtgui_event_t* ev
 		}
 		break;
 
+	case RTGUI_EVENT_APP_DESTROY:
+		rtgui_app_exit(app, 0);
+		break;
+
 	case RTGUI_EVENT_MOUSE_BUTTON:
 	case RTGUI_EVENT_MOUSE_MOTION:
 		{
@@ -282,12 +287,9 @@ rt_bool_t rtgui_app_event_handler(struct rtgui_object* object, rtgui_event_t* ev
             if (ecmd->wid != RT_NULL)
                     return _rtgui_application_dest_handle(app, event);
         }
-
-	default:
-		return rtgui_object_event_handler(object, event);
 	}
 
-	return RT_TRUE;
+	return rtgui_object_event_handler(object, event);
 }
 
 rt_inline void _rtgui_application_event_loop(struct rtgui_app *app)
@@ -344,6 +346,26 @@ void rtgui_app_exit(struct rtgui_app* app, rt_uint16_t code)
 	app->exit_code = code;
 }
 
+void rtgui_app_activate(struct rtgui_app *app)
+{
+	struct rtgui_event_application event;
+
+	RTGUI_EVENT_APP_ACTIVATE_INIT(&event);
+	event.app = app;
+
+	rtgui_send(app->tid, RTGUI_EVENT(&event), sizeof(struct rtgui_event_application));
+}
+
+void rtgui_app_close(struct rtgui_app *app)
+{
+	struct rtgui_event_application event;
+
+	RTGUI_EVENT_APP_DESTROY_INIT(&event);
+	event.app = app;
+
+	rtgui_send(app->tid, RTGUI_EVENT(&event), sizeof(struct rtgui_event_application));
+}
+
 /**
  * set this application as window manager
  */

+ 37 - 2
components/rtgui/common/rtgui_system.c

@@ -26,13 +26,24 @@
 #define RTGUI_MEM_TRACE
 #endif
 
+static rtgui_rect_t _mainwin_rect;
+static struct rt_mutex _screen_lock;
+
 void rtgui_system_server_init()
 {
+	rt_mutex_init(&_screen_lock, "screen", RT_IPC_FLAG_FIFO);
+
+	/* the graphic device driver must be set before initialization */
+	RT_ASSERT(rtgui_graphic_driver_get_default() != RT_NULL);
+
 	/* init image */
 	rtgui_system_image_init();
 	/* init font */
 	rtgui_font_system_init();
 
+	/* set the rect of main window to full screen */
+	rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), &_mainwin_rect);
+
 	/* init rtgui server */
 	rtgui_topwin_init();
 	rtgui_server_init();
@@ -287,11 +298,11 @@ void rtgui_free(void* ptr)
 
 #if defined(RTGUI_MEM_TRACE) && defined(RT_USING_FINSH)
 #include <finsh.h>
-void list_mem(void)
+void list_guimem(void)
 {
 	rt_kprintf("Current Used: %d, Maximal Used: %d\n", mem_info.allocated_size, mem_info.max_allocated);
 }
-FINSH_FUNCTION_EXPORT(list_mem, display memory information);
+FINSH_FUNCTION_EXPORT(list_guimem, display memory information);
 #endif
 
 /************************************************************************/
@@ -699,3 +710,27 @@ rt_thread_t rtgui_get_server(void)
 	return rt_thread_find("rtgui");
 }
 
+void rtgui_set_mainwin_rect(struct rtgui_rect *rect)
+{
+	_mainwin_rect = *rect;
+}
+
+void rtgui_get_mainwin_rect(struct rtgui_rect *rect)
+{
+	*rect = _mainwin_rect;
+}
+
+void rtgui_get_screen_rect(struct rtgui_rect *rect)
+{
+	rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), rect);
+}
+
+void rtgui_screen_lock(rt_int32_t timeout)
+{
+	rt_mutex_take(&_screen_lock, timeout);
+}
+
+void rtgui_screen_unlock(void)
+{
+	rt_mutex_release(&_screen_lock);
+}

+ 64 - 57
components/rtgui/common/rtgui_theme.c

@@ -71,19 +71,19 @@ void rtgui_theme_draw_win(struct rtgui_topwin* win)
 	if (win->flag & WINTITLE_BORDER)
 	{
 		rect.x2 -= 1; rect.y2 -= 1;
-		RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(win->title)) = RTGUI_RGB(212, 208, 200);
+		RTGUI_WIDGET_FOREGROUND(win->title) = RTGUI_RGB(212, 208, 200);
 		rtgui_dc_draw_hline(dc, rect.x1, rect.x2, rect.y1);
 		rtgui_dc_draw_vline(dc, rect.x1, rect.y1, rect.y2);
 
-		RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(win->title)) = white;
+		RTGUI_WIDGET_FOREGROUND(win->title) = white;
 		rtgui_dc_draw_hline(dc, rect.x1 + 1, rect.x2 - 1, rect.y1 + 1);
 		rtgui_dc_draw_vline(dc, rect.x1 + 1, rect.y1 + 1, rect.y2 - 1);
 
-		RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(win->title)) = RTGUI_RGB(128, 128, 128);
+		RTGUI_WIDGET_FOREGROUND(win->title) = RTGUI_RGB(128, 128, 128);
 		rtgui_dc_draw_hline(dc, rect.x1 + 1, rect.x2 - 1, rect.y2 - 1);
 		rtgui_dc_draw_vline(dc, rect.x2 - 1, rect.y1 + 1, rect.y2);
 
-		RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(win->title)) = RTGUI_RGB(64, 64, 64);
+		RTGUI_WIDGET_FOREGROUND(win->title) = RTGUI_RGB(64, 64, 64);
 		rtgui_dc_draw_hline(dc, rect.x1, rect.x2, rect.y2);
 		rtgui_dc_draw_vline(dc, rect.x2, rect.y1, rect.y2 + 1);
 
@@ -108,7 +108,7 @@ void rtgui_theme_draw_win(struct rtgui_topwin* win)
 			delta = 64 / (float)(rect.x2 - rect.x1);
 		}
 
-		RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(win->title)) = RTGUI_RGB(r, g, b);
+		RTGUI_WIDGET_FOREGROUND(win->title) = RTGUI_RGB(r, g, b);
 		for (index = rect.x1; index < rect.x2 + 1; index ++)
 		{
 			rtgui_dc_draw_vline(dc, index, rect.y1, rect.y2);
@@ -117,11 +117,11 @@ void rtgui_theme_draw_win(struct rtgui_topwin* win)
 
 		if (win->flag & WINTITLE_ACTIVATE)
 		{
-			RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(win->title)) = white;
+			RTGUI_WIDGET_FOREGROUND(win->title) = white;
 		}
 		else
 		{
-			RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(win->title)) = RTGUI_RGB(212, 208, 200);
+			RTGUI_WIDGET_FOREGROUND(win->title) = RTGUI_RGB(212, 208, 200);
 		}
 
 		rect.x1 += 4;
@@ -140,13 +140,13 @@ void rtgui_theme_draw_win(struct rtgui_topwin* win)
 			if (win->flag & WINTITLE_CB_PRESSED)
 			{
 				rtgui_dc_draw_border(dc, &box_rect, RTGUI_BORDER_SUNKEN);
-				RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(win->title)) = red;
+				RTGUI_WIDGET_FOREGROUND(win->title) = red;
 				rtgui_dc_draw_word(dc, box_rect.x1, box_rect.y1 + 6, 7, close_byte);
 			}
 			else
 			{
 				rtgui_dc_draw_border(dc, &box_rect, RTGUI_BORDER_RAISE);
-				RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(win->title)) = black;
+				RTGUI_WIDGET_FOREGROUND(win->title) = black;
 				rtgui_dc_draw_word(dc, box_rect.x1 - 1, box_rect.y1 + 5, 7, close_byte);
 			}
 		}
@@ -171,61 +171,63 @@ void rtgui_theme_draw_button(rtgui_button_t* btn)
 	rtgui_widget_get_rect(RTGUI_WIDGET(btn), &rect);
 
 	/* get foreground color */
-	bc = RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(btn));
-	fc = RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(btn));
+	bc = RTGUI_WIDGET_BACKGROUND(btn);
+	fc = RTGUI_WIDGET_FOREGROUND(btn);
 
 	if (btn->flag & RTGUI_BUTTON_FLAG_PRESS)
 	{
+		/* fill button rect with background color */
+		rtgui_dc_fill_rect(dc, &rect);
+
 		if (btn->pressed_image != RT_NULL)
 		{
 			rtgui_rect_t image_rect;
 			image_rect.x1 = 0; image_rect.y1 = 0;
 			image_rect.x2 = btn->unpressed_image->w;
 			image_rect.y2 = btn->unpressed_image->h;
-			rtgui_rect_moveto_align(&rect, &image_rect, RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL);
+			rtgui_rect_moveto_align(&rect, &image_rect, RTGUI_ALIGN_CENTER);
 
 			rtgui_image_blit(btn->pressed_image, dc, &image_rect);
 		}
 		else
 		{
-			/* fill button rect with background color */
-			rtgui_dc_fill_rect(dc, &rect);
 			rtgui_dc_draw_border(dc, &rect, RTGUI_BORDER_SUNKEN);
 		}
 	}
 	else
 	{
+		/* fill button rect with background color */
+		rtgui_dc_fill_rect(dc, &rect);
+
 		if (btn->unpressed_image != RT_NULL)
 		{
 			rtgui_rect_t image_rect;
 			image_rect.x1 = 0; image_rect.y1 = 0;
 			image_rect.x2 = btn->unpressed_image->w;
 			image_rect.y2 = btn->unpressed_image->h;
-			rtgui_rect_moveto_align(&rect, &image_rect, RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL);
+			rtgui_rect_moveto_align(&rect, &image_rect, RTGUI_ALIGN_CENTER);
 
 			rtgui_image_blit(btn->unpressed_image, dc, &image_rect);
 		}
 		else
 		{
-			/* fill button rect with background color */
-			rtgui_dc_fill_rect(dc, &rect);
 			rtgui_dc_draw_border(dc, &rect, RTGUI_BORDER_RAISE);
 		}
 	}
 
-	if (RTGUI_WIDGET_IS_FOCUSED(RTGUI_WIDGET(btn)))
+	if (RTGUI_WIDGET_IS_FOCUSED(btn))
 	{
 		/* re-set foreground and get default rect */
 		rtgui_widget_get_rect(RTGUI_WIDGET(btn), &rect);
 		rtgui_rect_inflate(&rect, -2);
 
-		RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(btn)) = black;
+		RTGUI_WIDGET_FOREGROUND(btn) = black;
 		rtgui_dc_draw_focus_rect(dc, &rect);
 	}
 
 	/* set forecolor */
-	RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(btn)) = bc;
-	RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(btn)) = fc;
+	RTGUI_WIDGET_BACKGROUND(btn) = bc;
+	RTGUI_WIDGET_FOREGROUND(btn) = fc;
 
 	if (btn->pressed_image == RT_NULL)
 	{
@@ -277,18 +279,18 @@ void rtgui_theme_draw_textbox(rtgui_textbox_t* box)
 
 	/* get widget rect */
 	rtgui_widget_get_rect(RTGUI_WIDGET(box), &rect);
-	fc = RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(box));
+	fc = RTGUI_WIDGET_FOREGROUND(box);
 
 	/* fill widget rect with white color */
-	RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(box)) = white;
+	RTGUI_WIDGET_BACKGROUND(box) = white;
 	rtgui_dc_fill_rect(dc, &rect);
 
 	/* draw border */
-	RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(box)) = RTGUI_RGB(123, 158, 189);
+	RTGUI_WIDGET_FOREGROUND(box) = RTGUI_RGB(123, 158, 189);
 	rtgui_dc_draw_rect(dc, &rect);
 
 	/* draw text */
-	RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(box)) = fc;
+	RTGUI_WIDGET_FOREGROUND(box) = fc;
 	if (box->text != RT_NULL)
 	{
 		rect.x1 += RTGUI_TEXTBOX_MARGIN;
@@ -303,7 +305,7 @@ void rtgui_theme_draw_textbox(rtgui_textbox_t* box)
 				rt_memset(text_mask, '*', len + 1);
 				text_mask[len] = 0;
 				rtgui_dc_draw_text(dc, text_mask, &rect);
-				rt_free(text_mask);
+				rtgui_free(text_mask);
 			}
 		}
 		else
@@ -320,7 +322,7 @@ void rtgui_theme_draw_textbox(rtgui_textbox_t* box)
 			rect.y2 -= 2;
 			rect.y1 = rect.y2 - 3;
 
-			RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(box)) = black;
+			RTGUI_WIDGET_BACKGROUND(box) = black;
 			rtgui_dc_fill_rect(dc, &rect);
 		}
 	}
@@ -333,6 +335,7 @@ void rtgui_theme_draw_iconbox(rtgui_iconbox_t* iconbox)
 {
 	struct rtgui_dc* dc;
 	struct rtgui_rect rect;
+	struct rtgui_rect text_rect;
 
 	/* begin drawing */
 	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(iconbox));
@@ -348,12 +351,16 @@ void rtgui_theme_draw_iconbox(rtgui_iconbox_t* iconbox)
 	if (iconbox->text_position == RTGUI_ICONBOX_TEXT_BELOW && iconbox->text != RT_NULL)
 	{
 		rect.y1 = iconbox->image->h + RTGUI_WIDGET_DEFAULT_MARGIN;
-		rtgui_dc_draw_text(dc, iconbox->text, &rect);
+		rtgui_font_get_metrics(rtgui_dc_get_gc(dc)->font, iconbox->text, &text_rect);
+		rtgui_rect_moveto_align(&rect, &text_rect, RTGUI_ALIGN_CENTER);
+		rtgui_dc_draw_text(dc, iconbox->text, &text_rect);
 	}
 	else if (iconbox->text_position == RTGUI_ICONBOX_TEXT_RIGHT && iconbox->text != RT_NULL)
 	{
 		rect.x1 = iconbox->image->w + RTGUI_WIDGET_DEFAULT_MARGIN;
-		rtgui_dc_draw_text(dc, iconbox->text, &rect);
+		rtgui_font_get_metrics(rtgui_dc_get_gc(dc)->font, iconbox->text, &text_rect);
+		rtgui_rect_moveto_align(&rect, &text_rect, RTGUI_ALIGN_CENTER);
+		rtgui_dc_draw_text(dc, iconbox->text, &text_rect);
 	}
 
 	/* end drawing */
@@ -367,8 +374,8 @@ void rtgui_theme_draw_checkbox(struct rtgui_checkbox* checkbox)
 	struct rtgui_rect rect, box_rect;
 	rtgui_color_t bc, fc;
 
-	fc = RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(checkbox));
-	bc = RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(checkbox));
+	fc = RTGUI_WIDGET_FOREGROUND(checkbox);
+	bc = RTGUI_WIDGET_BACKGROUND(checkbox);
 
 	/* begin drawing */
 	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(checkbox));
@@ -380,9 +387,9 @@ void rtgui_theme_draw_checkbox(struct rtgui_checkbox* checkbox)
     /* fill rect */
 	rtgui_dc_fill_rect(dc, &rect);
 
-	if (RTGUI_WIDGET_IS_FOCUSED(RTGUI_WIDGET(checkbox)))
+	if (RTGUI_WIDGET_IS_FOCUSED(checkbox))
 	{
-		RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(checkbox)) = black;
+		RTGUI_WIDGET_FOREGROUND(checkbox) = black;
 
 		/* draw focused border */
 		rtgui_rect_inflate(&rect, -1);
@@ -401,17 +408,17 @@ void rtgui_theme_draw_checkbox(struct rtgui_checkbox* checkbox)
 
 	rtgui_dc_draw_border(dc, &box_rect, RTGUI_BORDER_BOX);
 	rtgui_rect_inflate(&box_rect, -1);
-	RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(checkbox)) = RTGUI_RGB(247, 247, 246);
+	RTGUI_WIDGET_BACKGROUND(checkbox) = RTGUI_RGB(247, 247, 246);
 	rtgui_dc_fill_rect(dc, &box_rect);
 	if (checkbox->status_down == RTGUI_CHECKBOX_STATUS_CHECKED)
 	{
-		RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(checkbox)) = RTGUI_RGB(33, 161, 33);
+		RTGUI_WIDGET_FOREGROUND(checkbox) = RTGUI_RGB(33, 161, 33);
 		rtgui_dc_draw_byte(dc, box_rect.x1 + 2, box_rect.y1 + 2, 7, checked_byte);
 	}
 
 	/* restore saved color */
-	RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(checkbox)) = bc;
-	RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(checkbox)) = fc;
+	RTGUI_WIDGET_BACKGROUND(checkbox) = bc;
+	RTGUI_WIDGET_FOREGROUND(checkbox) = fc;
 
 	/* draw text */
 	rect.x1 += rtgui_rect_height(rect) - 4 + 5;
@@ -471,7 +478,7 @@ void rtgui_theme_draw_radiobutton(struct rtgui_radiobox* radiobox, rt_uint16_t i
 		/* draw radio */
 		if (radiobox->item_selection == item)
 		{
-			if (RTGUI_WIDGET_IS_FOCUSED(RTGUI_WIDGET(radiobox)))
+			if (RTGUI_WIDGET_IS_FOCUSED(radiobox))
 				rtgui_dc_draw_focus_rect(dc, &item_rect);
 
 			rtgui_dc_draw_word(dc, item_rect.x1, item_rect.y1 + (item_size - RADIO_BOX_H) / 2, 
@@ -501,7 +508,7 @@ void rtgui_theme_draw_radiobutton(struct rtgui_radiobox* radiobox, rt_uint16_t i
 		/* draw radio */
 		if (radiobox->item_selection == item)
 		{
-			if (RTGUI_WIDGET_IS_FOCUSED(RTGUI_WIDGET(radiobox)))
+			if (RTGUI_WIDGET_IS_FOCUSED(radiobox))
 				rtgui_dc_draw_focus_rect(dc, &item_rect);
 			rtgui_dc_draw_word(dc, item_rect.x1, item_rect.y1, RADIO_BOX_H, radio_checked_byte);
 		}
@@ -549,17 +556,17 @@ void rtgui_theme_draw_radiobox(struct rtgui_radiobox* radiobox)
 
 	/* draw box */
 	rtgui_rect_inflate(&rect, -bord_size/2);
-	fc = RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(radiobox));
+	fc = RTGUI_WIDGET_FOREGROUND(radiobox);
 
-	RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(radiobox)) = white;
+	RTGUI_WIDGET_FOREGROUND(radiobox) = white;
 	rect.x1 ++; rect.y1 ++; rect.x2 ++; rect.y2 ++;
 	rtgui_dc_draw_rect(dc, &rect);
 
-	RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(radiobox)) = RTGUI_RGB(128, 128, 128);
+	RTGUI_WIDGET_FOREGROUND(radiobox) = RTGUI_RGB(128, 128, 128);
 	rect.x1 --; rect.y1 --; rect.x2 --; rect.y2 --;
 	rtgui_dc_draw_rect(dc, &rect);
 
-	RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(radiobox)) = fc;
+	RTGUI_WIDGET_FOREGROUND(radiobox) = fc;
 
 	rtgui_rect_inflate(&rect, bord_size/2);
 	if (radiobox->text != RT_NULL)
@@ -595,7 +602,7 @@ void rtgui_theme_draw_radiobox(struct rtgui_radiobox* radiobox)
 			/* draw radio */
 			if (radiobox->item_selection == index)
 			{
-				if (RTGUI_WIDGET_IS_FOCUSED(RTGUI_WIDGET(radiobox)))
+				if (RTGUI_WIDGET_IS_FOCUSED(radiobox))
 					rtgui_dc_draw_focus_rect(dc, &item_rect);
 
 				rtgui_dc_draw_word(dc, item_rect.x1, item_rect.y1 + offset, RADIO_BOX_H, radio_checked_byte);
@@ -628,7 +635,7 @@ void rtgui_theme_draw_radiobox(struct rtgui_radiobox* radiobox)
 			/* draw radio */
 			if (radiobox->item_selection == index)
 			{
-				if (RTGUI_WIDGET_IS_FOCUSED(RTGUI_WIDGET(radiobox)))
+				if (RTGUI_WIDGET_IS_FOCUSED(radiobox))
 					rtgui_dc_draw_focus_rect(dc, &item_rect);
 				rtgui_dc_draw_word(dc, item_rect.x1, item_rect.y1, RADIO_BOX_H, radio_checked_byte);
 			}
@@ -732,7 +739,7 @@ void rtgui_theme_draw_slider(struct rtgui_slider* slider)
 	}
 
 	/* draw focus */
-	if (RTGUI_WIDGET_IS_FOCUSED(RTGUI_WIDGET(slider)))
+	if (RTGUI_WIDGET_IS_FOCUSED(slider))
 	{
 		rtgui_dc_draw_focus_rect(dc, &focus_rect);
 	}
@@ -762,15 +769,15 @@ void rtgui_theme_draw_scrollbar(struct rtgui_scrollbar* bar)
 	rtgui_widget_get_rect(RTGUI_WIDGET(bar), &rect);
 
 	/* draw background */
-	fc = RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(bar));
-	if (!RTGUI_WIDGET_IS_ENABLE(RTGUI_WIDGET(bar)))
-		RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(bar)) = RTGUI_RGB(128, 128, 128);
+	fc = RTGUI_WIDGET_FOREGROUND(bar);
+	if (!RTGUI_WIDGET_IS_ENABLE(bar))
+		RTGUI_WIDGET_FOREGROUND(bar) = RTGUI_RGB(128, 128, 128);
 
-	bc = RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(bar));
-	RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(bar)) = white;
+	bc = RTGUI_WIDGET_BACKGROUND(bar);
+	RTGUI_WIDGET_BACKGROUND(bar) = white;
 	rtgui_dc_fill_rect(dc, &rect);
 
-	RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(bar)) = bc;
+	RTGUI_WIDGET_BACKGROUND(bar) = bc;
 
 	if (bar->orient == RTGUI_VERTICAL)
 	{
@@ -791,7 +798,7 @@ void rtgui_theme_draw_scrollbar(struct rtgui_scrollbar* bar)
 			rtgui_rect_height(arrow_rect), _up_arrow);
 
 		/* draw thumb */
-		if (RTGUI_WIDGET_IS_ENABLE(RTGUI_WIDGET(bar)))
+		if (RTGUI_WIDGET_IS_ENABLE(bar))
 		{
 			rtgui_scrollbar_get_thumb_rect(bar, &thum_rect);
 			rtgui_dc_fill_rect(dc, &thum_rect);
@@ -833,7 +840,7 @@ void rtgui_theme_draw_scrollbar(struct rtgui_scrollbar* bar)
 			rtgui_rect_height(arrow_rect), _left_arrow);
 
 		/* draw thumb */
-		if (RTGUI_WIDGET_IS_ENABLE(RTGUI_WIDGET(bar)))
+		if (RTGUI_WIDGET_IS_ENABLE(bar))
 		{
 			rtgui_scrollbar_get_thumb_rect(bar, &thum_rect);
 			rtgui_dc_fill_rect(dc, &thum_rect);
@@ -858,7 +865,7 @@ void rtgui_theme_draw_scrollbar(struct rtgui_scrollbar* bar)
 
 	/* end drawing */
 	rtgui_dc_end_drawing(dc);
-	RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(bar)) = fc;
+	RTGUI_WIDGET_FOREGROUND(bar) = fc;
 
 	return;
 }
@@ -881,7 +888,7 @@ void rtgui_theme_draw_progressbar(struct rtgui_progressbar* bar)
 	rtgui_widget_get_rect(&(bar->parent), &rect);
 
 	/* fill button rect with background color */
-	RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(bar)) = RTGUI_RGB(212, 208, 200);
+	RTGUI_WIDGET_BACKGROUND(bar) = RTGUI_RGB(212, 208, 200);
 
     /* draw border */
 	rtgui_dc_draw_border(dc, &rect, RTGUI_BORDER_SUNKEN);
@@ -896,7 +903,7 @@ void rtgui_theme_draw_progressbar(struct rtgui_progressbar* bar)
 	rect.x2 ++; rect.y2 ++;
     left = max - pos;
 	rtgui_rect_inflate(&rect, -2);
-    RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(bar)) = RTGUI_RGB(0, 0, 255);
+    RTGUI_WIDGET_BACKGROUND(bar) = RTGUI_RGB(0, 0, 255);
 	rect.y2 --; rect.x2 --;
 
     if (bar->orient == RTGUI_VERTICAL)

+ 2 - 2
components/rtgui/include/rtgui/color.h

@@ -89,7 +89,7 @@ rt_inline rtgui_color_t rtgui_color_from_565(rt_uint16_t pixel)
 	g = (pixel >> 5) & 0x3f;
 	b = (pixel >> 11) & 0x1f;
 
-	color = r * 8225 / 1024 + ((g * 4047 / 1024) << 8) + ((b * 8225 / 1024) << 16);
+	color = r * 255 / 31 + ((g * 255 / 63) << 8) + ((b * 255 / 31) << 16);
 
 	return color;
 }
@@ -112,7 +112,7 @@ rt_inline rtgui_color_t rtgui_color_from_565p(rt_uint16_t pixel)
 	g = (pixel >> 5)  & 0x3f;
 	b = pixel & 0x1f;
 
-	color = r * 8225 / 1024 + ((g * 4047 / 1024) << 8) + ((b * 8225 / 1024) << 16);
+	color = r * 255 / 31 + ((g * 255 / 63) << 8) + ((b * 255 / 31) << 16);
 
 	return color;
 }

+ 2 - 0
components/rtgui/include/rtgui/dc.h

@@ -86,6 +86,8 @@ void rtgui_dc_draw_sector(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_in
 void rtgui_dc_fill_sector(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t r, rt_int16_t start, rt_int16_t end);
 
 void rtgui_dc_draw_text (struct rtgui_dc* dc, const char* text, struct rtgui_rect* rect);
+void rtgui_dc_draw_text_stroke (struct rtgui_dc* dc, const char* text, struct rtgui_rect* rect,
+	rtgui_color_t color_stroke, rtgui_color_t color_core);
 
 void rtgui_dc_draw_mono_bmp(struct rtgui_dc* dc, int x, int y, int w, int h, const rt_uint8_t* data);
 void rtgui_dc_draw_byte(struct rtgui_dc*dc, int x, int y, int h, const rt_uint8_t* data);

+ 3 - 1
components/rtgui/include/rtgui/event.h

@@ -63,12 +63,14 @@ enum _rtgui_event_type
 	RTGUI_EVENT_KBD,                   /* keyboard info         */
 
 	/* user command event */
-	RTGUI_EVENT_COMMAND,               /* user command          */
+	RTGUI_EVENT_COMMAND=0x0100,        /* user command          */
 
 	/* widget event */
 	RTGUI_EVENT_FOCUSED,               /* widget focused        */
 	RTGUI_EVENT_SCROLLED,              /* scroll bar scrolled   */
 	RTGUI_EVENT_RESIZE,                /* widget resize         */
+	RTGUI_EVENT_SELECTED,			   /* widget selected       */
+	RTGUI_EVENT_UNSELECTED,			   /* widget un-selected    */
 };
 typedef enum _rtgui_event_type rtgui_event_type;
 

+ 1 - 0
components/rtgui/include/rtgui/region.h

@@ -94,6 +94,7 @@ void rtgui_rect_intersect(rtgui_rect_t *src, rtgui_rect_t *dest);
 int  rtgui_rect_contains_point(const rtgui_rect_t *rect, int x, int y);
 int  rtgui_rect_is_intersect(const rtgui_rect_t *rect1, const rtgui_rect_t *rect2);
 int  rtgui_rect_is_equal(const rtgui_rect_t *rect1, const rtgui_rect_t *rect2);
+rt_bool_t rtgui_rect_is_empty(const rtgui_rect_t *rect);
 
 #if defined(__cplusplus) || defined(c_plusplus)
 }

+ 16 - 1
components/rtgui/include/rtgui/rtgui.h

@@ -29,10 +29,12 @@ struct rtgui_win;
 struct rtgui_font;
 
 typedef struct rtgui_win rtgui_win_t;
-typedef struct rtgui_workbench rtgui_workbench_t;
 typedef rt_bool_t (*rtgui_event_handler_ptr)(struct rtgui_object* object, struct rtgui_event* event);
 typedef void (*rtgui_onbutton_func_t)(struct rtgui_object* object, struct rtgui_event* event);
 
+/**
+ * Coordinate point
+ */
 struct rtgui_point
 {
 	rt_int16_t x, y;
@@ -40,6 +42,9 @@ struct rtgui_point
 typedef struct rtgui_point rtgui_point_t;
 extern rtgui_point_t rtgui_empty_point;
 
+/**
+ * Rectangle structure
+ */
 struct rtgui_rect
 {
 	rt_int16_t x1, y1, x2, y2;
@@ -50,6 +55,9 @@ typedef struct rtgui_rect rtgui_rect_t;
 
 typedef unsigned long rtgui_color_t;
 
+/**
+ * Graphic context
+ */
 struct rtgui_gc
 {
 	/* foreground and background color */
@@ -73,6 +81,10 @@ enum RTGUI_MARGIN_STYLE
 	RTGUI_MARGIN_BOTTOM = 0x08,
 	RTGUI_MARGIN_ALL = RTGUI_MARGIN_LEFT | RTGUI_MARGIN_RIGHT | RTGUI_MARGIN_TOP | RTGUI_MARGIN_BOTTOM
 };
+
+/**
+ * Border style 
+ */
 enum RTGUI_BORDER_STYLE
 {
 	RTGUI_BORDER_NONE = 0,
@@ -88,6 +100,9 @@ enum RTGUI_BORDER_STYLE
 #define RTGUI_BORDER_DEFAULT_WIDTH	2
 #define RTGUI_WIDGET_DEFAULT_MARGIN	3
 
+/**
+ * Orientation
+ */
 enum RTGUI_ORIENTATION
 {
     RTGUI_HORIZONTAL		= 0x01,

+ 14 - 11
components/rtgui/include/rtgui/rtgui_app.h

@@ -1,7 +1,7 @@
 /*
- * File      : rtgui_application.h
+ * File      : rtgui_app.h
  * This file is part of RTGUI in RT-Thread RTOS
- * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
+ * COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team
  *
  * The license and distribution terms for this file may be
  * found in the file LICENSE in this distribution or at
@@ -11,8 +11,9 @@
  * Date           Author       Notes
  * 2012-01-13     Grissiom     first version
  */
-#ifndef __RTGUI_APPLICATION_H__
-#define __RTGUI_APPLICATION_H__
+
+#ifndef __RTGUI_APP_H__
+#define __RTGUI_APP_H__
 
 #include <rtthread.h>
 #include <rtgui/rtgui.h>
@@ -34,7 +35,7 @@ enum rtgui_app_flag
 	RTGUI_APP_FLAG_SHOWN   = 0x08
 };
 
-typedef void (*rtgui_idle_func_t)(struct rtgui_object* obj, struct rtgui_event *event);
+typedef void (*rtgui_idle_func_t)(struct rtgui_object *obj, struct rtgui_event *event);
 
 struct rtgui_app
 {
@@ -52,7 +53,7 @@ struct rtgui_app
 	/* the thread id */
 	rt_thread_t tid;
 	/* the RTGUI server id */
-    rt_thread_t server;
+	rt_thread_t server;
 
 	/* the message queue of thread */
 	rt_mq_t mq;
@@ -71,18 +72,20 @@ struct rtgui_app
 /**
  * create an application named @myname on thread @param tid
  */
-struct rtgui_app* rtgui_app_create(rt_thread_t tid, const char *title);
+struct rtgui_app *rtgui_app_create(rt_thread_t tid, const char *title);
 void rtgui_app_destroy(struct rtgui_app *app);
-rt_bool_t rtgui_app_event_handler(struct rtgui_object* obj, rtgui_event_t* event);
+rt_bool_t rtgui_app_event_handler(struct rtgui_object *obj, rtgui_event_t *event);
 
 rt_base_t rtgui_app_run(struct rtgui_app *app);
 void rtgui_app_exit(struct rtgui_app *app, rt_uint16_t code);
+void rtgui_app_activate(struct rtgui_app *app);
+void rtgui_app_close(struct rtgui_app *app);
 
 void rtgui_app_set_onidle(rtgui_idle_func_t onidle);
 rtgui_idle_func_t rtgui_app_get_onidle(void);
-struct rtgui_app* rtgui_app_self(void);
+struct rtgui_app *rtgui_app_self(void);
 
 rt_err_t rtgui_app_set_as_wm(void);
-void rtgui_app_set_main_win(struct rtgui_win* win);
+void rtgui_app_set_main_win(struct rtgui_win *win);
 
-#endif /* end of include guard: RTGUI_APPLICATION_H */
+#endif /* end of include guard: __RTGUI_APP_H__ */

+ 6 - 4
components/rtgui/include/rtgui/rtgui_config.h

@@ -35,15 +35,19 @@
 	#define RTGUI_DEFAULT_FONT_SIZE	12
 
 	#define RTGUI_USING_STDIO_FILERW
+	// #define RTGUI_USING_DFS_FILERW
 	#define RTGUI_IMAGE_CONTAINER
 	#define RTGUI_IMAGE_XPM
 	#define RTGUI_IMAGE_BMP
 	#define RTGUI_IMAGE_PNG
-	#define RTGUI_IMAGE_JPEG
+	// #define RTGUI_IMAGE_JPEG
+	// #define RTGUI_IMAGE_TJPGD
 	#define RTGUI_USING_FONT12
 	#define RTGUI_USING_HZ_BMP
 	#define RTGUI_MEM_TRACE
 	#define RTGUI_USING_WINMOVE
+	#define RTGUI_USING_NOTEBOOK_IMAGE
+
 #else
 	/* native running under RT-Thread */
 	#ifndef RT_USING_DFS
@@ -75,8 +79,6 @@
 #define RTGUI_USING_CAST_CHECK
 
 //#define RTGUI_USING_DESKTOP_WINDOW
-
-#define  RTGUI_EVENT_DEBUG
-// #undef RTGUI_USING_SMALL_SIZE
+#undef RTGUI_USING_SMALL_SIZE
 
 #endif

+ 13 - 0
components/rtgui/include/rtgui/rtgui_object.h

@@ -125,6 +125,19 @@ rt_bool_t rtgui_object_event_handler(struct rtgui_object *object, struct rtgui_e
 	/* supress compiler warning */ \
 	widget = widget;
 
+/** handle @param event on @param object's own event handler
+ *
+ * If the @param object does not have an event handler, which means the object
+ * does not interested in any event, it will return RT_FALSE. Otherwise, the
+ * return code of that handler is returned.
+ */
+rt_inline rt_bool_t rtgui_object_handle(struct rtgui_object *object, struct rtgui_event *event)
+{
+    if (object->event_handler)
+        return object->event_handler(object, event);
+    return RT_FALSE;
+}
+
 rtgui_object_t *rtgui_object_check_cast(rtgui_object_t *object, rtgui_type_t *type, const char* func, int line);
 rtgui_type_t   *rtk_object_object_type_get(rtgui_object_t *object);
 

+ 6 - 1
components/rtgui/include/rtgui/rtgui_system.h

@@ -54,6 +54,12 @@ void* rtgui_realloc(void* ptr, rt_size_t size);
 #define rtgui_exit_critical		rt_exit_critical
 
 rt_thread_t rtgui_get_server(void);
+void rtgui_set_mainwin_rect(struct rtgui_rect *rect);
+void rtgui_get_mainwin_rect(struct rtgui_rect *rect);
+void rtgui_get_screen_rect(struct rtgui_rect *rect);
+
+void rtgui_screen_lock(rt_int32_t timeout);
+void rtgui_screen_unlock(void);
 
 struct rtgui_event;
 rt_err_t rtgui_send(rt_thread_t tid, struct rtgui_event* event, rt_size_t event_size);
@@ -65,4 +71,3 @@ rt_err_t rtgui_recv_nosuspend(struct rtgui_event* event, rt_size_t event_size);
 rt_err_t rtgui_recv_filter(rt_uint32_t type, struct rtgui_event* event, rt_size_t event_size);
 
 #endif
-

+ 1 - 1
components/rtgui/include/rtgui/widgets/box.h

@@ -46,10 +46,10 @@ struct rtgui_box* rtgui_box_create(int orientation, int border_size);
 void rtgui_box_destroy(struct rtgui_box* box);
 
 void rtgui_box_layout(rtgui_box_t* box);
+void rtgui_box_layout_rect(rtgui_box_t* box, struct rtgui_rect* rect);
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif
-

+ 129 - 0
components/rtgui/include/rtgui/widgets/edit.h

@@ -0,0 +1,129 @@
+/*
+ * File      : edit.h
+ * 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
+ * 2012-06-04     amsl         first version
+ */
+#ifndef __RTGUI_EDIT_H__
+#define __RTGUI_EDIT_H__
+
+#include <rtgui/widgets/widget.h>
+#include <rtgui/widgets/container.h>
+
+#ifdef _WIN32
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <io.h>
+#else
+#include <dfs_posix.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _WIN32
+#define open	_open
+#define close	_close
+#define read	_read
+#define write	_write
+#define unlink	_unlink
+#endif
+
+DECLARE_CLASS_TYPE(edit);
+
+/** Gets the type of a edit */
+#define RTGUI_EDIT_TYPE       (RTGUI_TYPE(edit))
+/** Casts the object to a rtgui_edit */
+#define RTGUI_EDIT(obj)       (RTGUI_OBJECT_CAST((obj), RTGUI_EDIT_TYPE, struct rtgui_edit))
+/** Checks if the object is a rtgui_edit */
+#define RTGUI_IS_EDIT(obj)    (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_EDIT_TYPE))
+
+#define RTGUI_EDIT_NONE				0x00
+#define RTGUI_EDIT_CARET			0x01
+#define RTGUI_EDIT_VSCROLL			0x02
+#define RTGUI_EDIT_HSCROLL			0x04
+#define RTGUI_EDIT_SHIFT			0x10
+#define RTGUI_EDIT_CTRL				0x20
+#define RTGUI_EDIT_ALT				0x40
+#define RTGUI_EDIT_CAPSLOCK			0x80
+#define RTGUI_EDIT_NUMLOCK			0x100
+
+struct edit_update
+{
+	/* rt_uint32_t type; */ /* update type */
+	rtgui_point_t start, end; /* update area */
+};
+
+struct edit_line
+{
+	rt_size_t   zsize; /* zone size */
+	rt_uint32_t len;
+	struct edit_line *prev;
+	struct edit_line *next;
+	char *text;
+};
+
+struct rtgui_edit
+{
+	/* inherit from container */
+	rtgui_container_t parent;
+
+	/* edit flag */
+	rt_uint32_t   flag;
+	rt_uint32_t   max_rows, max_cols;
+	rt_uint16_t   row_per_page, col_per_page;
+	rtgui_point_t upleft;
+	rtgui_point_t visual;
+	rt_uint8_t    tabsize;
+	rt_uint8_t    item_height;
+	rt_uint8_t    font_width,font_height;
+	rt_uint8_t    margin;
+	rt_size_t     bzsize; /* base zone size */
+	
+	struct rtgui_timer *caret_timer;
+	rtgui_color_t *caret;
+	rtgui_rect_t  caret_rect;
+	struct edit_update update;
+	char          *update_buf; /* speed up renewal process */
+	
+	struct edit_line  *head;
+	struct edit_line  *tail;
+	struct edit_line  *first_line;
+#ifdef RTGUI_EDIT_USING_SCROLL
+	struct rtgui_scrollbar *hscroll;
+	struct rtgui_scrollbar *vscroll;
+#endif
+};
+
+rt_bool_t rtgui_edit_append_line(struct rtgui_edit *edit, const char *text);
+rt_bool_t rtgui_edit_insert_line(struct rtgui_edit *edit, struct edit_line *p, char *text);
+rt_bool_t rtgui_edit_delete_line(struct rtgui_edit *edit, struct edit_line *line);
+rt_bool_t rtgui_edit_connect_line(struct rtgui_edit *edit, struct edit_line *line, struct edit_line *connect);
+
+void _rtgui_edit_constructor(struct rtgui_edit *box);
+void _rtgui_edit_deconstructor(struct rtgui_edit *textbox);
+
+struct rtgui_edit* rtgui_edit_create(struct rtgui_container* container, int left, int top, int w, int h);
+void rtgui_edit_destroy(struct rtgui_edit *edit);
+void rtgui_edit_update(struct rtgui_edit *edit);
+void rtgui_edit_ondraw(struct rtgui_edit *edit);
+rt_bool_t rtgui_edit_event_handler(struct rtgui_object* object, rtgui_event_t* event);
+void rtgui_edit_set_text(struct rtgui_edit *edit, const char* text);
+
+rt_bool_t rtgui_edit_readin_file(struct rtgui_edit *edit, const char *filename);
+rt_bool_t rtgui_edit_saveas_file(struct rtgui_edit *edit, const char *filename);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 73 - 0
components/rtgui/include/rtgui/widgets/groupbox.h

@@ -0,0 +1,73 @@
+/*
+ * File      : groupbox.h
+ * 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
+ * 2012-07-29     Bernard      first version
+ */
+#ifndef __RTGUI_GROUPBOX_H__
+#define __RTGUI_GROUPBOX_H__
+
+#include <rtgui/rtgui.h>
+#include <rtgui/event.h>
+#include <rtgui/widgets/panel.h>
+#include <rtgui/widgets/box.h>
+
+DECLARE_CLASS_TYPE(groupbox);
+
+/** Gets the type of a groupbox */
+#define RTGUI_GROUPBOX_TYPE       (RTGUI_TYPE(groupbox))
+/** Casts the object to an groupbox */
+#define RTGUI_GROUPBOX(obj)       (RTGUI_OBJECT_CAST((obj), RTGUI_GROUPBOX_TYPE, rtgui_groupbox_t))
+/** Checks if the object is an rtgui_groupbox */
+#define RTGUI_IS_GROUPBOX(obj)    (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_GROUPBOX_TYPE))
+
+typedef void (*widget_select_t)(struct rtgui_widget* widget, rt_bool_t selected);
+
+/*
+ * the groupbox widget
+ *
+ * The Group Box is a container widget, in which user can place some other widget into it. 
+ * However, the current selected in group box must be notified by user:
+ * - invoke rtgui_groupbox_select_widget to notify group box the current selected widget;
+ * - when a widget has been selected, group box invokes groupbox->select_func to change 
+ *   the status of widget, for example un-select this widget. 
+ */
+struct rtgui_groupbox
+{
+	struct rtgui_panel parent;
+
+	char* label;
+	struct rtgui_box *box;
+	struct rtgui_widget *selected;
+
+	widget_select_t select_func;
+	rtgui_event_handler_ptr on_selected;
+};
+typedef struct rtgui_groupbox rtgui_groupbox_t;
+
+rtgui_groupbox_t* rtgui_groupbox_create(const char* label, struct rtgui_rect *rect, int style, widget_select_t select_func);
+void rtgui_groupbox_destroy(rtgui_groupbox_t* groupbox);
+
+void rtgui_groupbox_layout(struct rtgui_groupbox *box);
+
+void rtgui_groupbox_add_widget(struct rtgui_groupbox *box, struct rtgui_widget *widget);
+void rtgui_groupbox_select_widget(struct rtgui_groupbox *box, struct rtgui_widget *widget);
+struct rtgui_widget* rtgui_groupbox_get_selected(struct rtgui_groupbox *box);
+
+rt_bool_t rtgui_groupbox_event_handler(struct rtgui_object* object, struct rtgui_event* event);
+
+rt_inline void rtgui_groupbox_set_onselected(struct rtgui_groupbox* box, rtgui_event_handler_ptr on_selected)
+{
+	RT_ASSERT(box != RT_NULL);
+	box->on_selected = on_selected;
+}
+
+#endif
+

+ 1 - 0
components/rtgui/include/rtgui/widgets/iconbox.h

@@ -51,5 +51,6 @@ void rtgui_iconbox_destroy(struct rtgui_iconbox* iconbox);
 rt_bool_t rtgui_iconbox_event_handler(struct rtgui_object* object, struct rtgui_event* event);
 
 void rtgui_iconbox_set_text_position(struct rtgui_iconbox* iconbox, int position);
+void rtgui_iconbox_set_selected(struct rtgui_iconbox* iconbox, rt_bool_t selected);
 
 #endif

+ 2 - 0
components/rtgui/include/rtgui/widgets/listctrl.h

@@ -42,6 +42,7 @@ struct rtgui_listctrl
     rt_uint16_t page_items;
     /* current item */
     rt_int16_t current_item;
+	rt_uint16_t item_height;
 
 	/* item event handler */
 	rtgui_event_handler_ptr on_item;
@@ -59,5 +60,6 @@ rt_bool_t rtgui_listctrl_event_handler(struct rtgui_object* object, struct rtgui
 void rtgui_listctrl_set_onitem(rtgui_listctrl_t* ctrl, rtgui_event_handler_ptr func);
 void rtgui_listctrl_set_items(rtgui_listctrl_t* ctrl, rt_uint32_t items, rt_uint16_t count);
 rt_bool_t rtgui_listctrl_get_item_rect(rtgui_listctrl_t* ctrl, rt_uint16_t item, rtgui_rect_t* item_rect);
+void rtgui_listctrl_set_itemheight(struct rtgui_listctrl* ctrl, int height);
 
 #endif

+ 22 - 0
components/rtgui/include/rtgui/widgets/notebook.h

@@ -2,6 +2,7 @@
 #define __RTGUI_NOTEBOOK_H__
 
 #include <rtgui/rtgui.h>
+#include <rtgui/image.h>
 #include <rtgui/widgets/widget.h>
 
 DECLARE_CLASS_TYPE(notebook);
@@ -15,6 +16,8 @@ DECLARE_CLASS_TYPE(notebook);
 #define RTGUI_NOTEBOOK_TOP			0x00
 #define RTGUI_NOTEBOOK_BOTTOM		0x01
 #define RTGUI_NOTEBOOK_NOTAB		0x02
+#define RTGUI_NOTEBOOK_LEFT			0x03
+#define RTGUI_NOTEBOOK_RIGHT		0x04
 
 struct rtgui_notebook_tab;
 
@@ -28,17 +31,36 @@ struct rtgui_notebook
 	struct rtgui_notebook_tab *childs;
 	rt_uint16_t count;
 	rt_int16_t current;
+
+	rt_uint16_t tab_w, tab_h;
 };
 
 struct rtgui_notebook* rtgui_notebook_create(const rtgui_rect_t* rect, rt_uint8_t style);
 void rtgui_notebook_destroy(struct rtgui_notebook* notebook);
 
+rt_inline void rtgui_notebook_set_tab_height(struct rtgui_notebook *notebook, rt_uint16_t height)
+{
+	RT_ASSERT(notebook != RT_NULL);
+	notebook->tab_h = height;
+}
+
+rt_inline void rtgui_notebook_set_tab_width(struct rtgui_notebook *notebook, rt_uint16_t width)
+{
+	RT_ASSERT(notebook != RT_NULL);
+	notebook->tab_w = width;
+}
+
 void rtgui_notebook_add(struct rtgui_notebook* notebook, const char* label, struct rtgui_widget* child);
+#ifdef RTGUI_USING_NOTEBOOK_IMAGE
+void rtgui_notebook_add_image(struct rtgui_notebook* notebook, const char* label, struct rtgui_widget* child, 
+	struct rtgui_image *pressed_image, struct rtgui_image *unpressed_image);
+#endif
 void rtgui_notebook_remove(struct rtgui_notebook* notebook, rt_uint16_t index);
 struct rtgui_widget* rtgui_notebook_get_current(struct rtgui_notebook* notebook);
 rt_int16_t rtgui_notebook_get_current_index(struct rtgui_notebook* notebook);
 
 int rtgui_notebook_get_count(struct rtgui_notebook* notebook);
+void rtgui_notebook_get_client_rect(struct rtgui_notebook* notebook, struct rtgui_rect *rect);
 
 void rtgui_notebook_set_current(struct rtgui_notebook* notebook, struct rtgui_widget* child);
 void rtgui_notebook_set_current_by_index(struct rtgui_notebook* notebook, rt_uint16_t index);

+ 7 - 1
components/rtgui/include/rtgui/widgets/panel.h

@@ -23,7 +23,7 @@ DECLARE_CLASS_TYPE(panel);
 #define RTGUI_PANEL_TYPE       (RTGUI_TYPE(panel))
 /** Casts the object to an panel */
 #define RTGUI_PANEL(obj)       (RTGUI_OBJECT_CAST((obj), RTGUI_PANEL_TYPE, rtgui_panel_t))
-/** Checks if the object is an rtgui_button */
+/** Checks if the object is an rtgui_panel */
 #define RTGUI_IS_PANEL(obj)    (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_PANEL_TYPE))
 
 /*
@@ -40,6 +40,12 @@ typedef struct rtgui_panel rtgui_panel_t;
 rtgui_panel_t* rtgui_panel_create(int border_style);
 void rtgui_panel_destroy(rtgui_panel_t* panel);
 
+rt_inline void rtgui_panel_set_border(struct rtgui_panel* panel, int border_style)
+{
+	RT_ASSERT(panel != RT_NULL);
+	panel->border_style = border_style;
+}
+
 rt_bool_t rtgui_panel_event_handler(struct rtgui_object* object, struct rtgui_event* event);
 
 #endif

+ 24 - 20
components/rtgui/include/rtgui/widgets/widget.h

@@ -33,25 +33,6 @@ extern "C" {
 #define RTGUI_WIDGET_FLAG_FOCUSABLE		0x0010
 #define RTGUI_WIDGET_FLAG_DC_VISIBLE	0x0100
 
-#define RTGUI_WIDGET_UNHIDE(w)			(w)->flag |= RTGUI_WIDGET_FLAG_SHOWN
-#define RTGUI_WIDGET_HIDE(w)			(w)->flag &= ~RTGUI_WIDGET_FLAG_SHOWN
-#define RTGUI_WIDGET_IS_HIDE(w)			(!((w)->flag & RTGUI_WIDGET_FLAG_SHOWN))
-
-#define RTGUI_WIDGET_ENABLE(w)			(w)->flag &= ~RTGUI_WIDGET_FLAG_DISABLE
-#define RTGUI_WIDGET_DISABLE(w)			(w)->flag |= RTGUI_WIDGET_FLAG_DISABLE
-#define RTGUI_WIDGET_IS_ENABLE(w)		!(w->flag & RTGUI_WIDGET_FLAG_DISABLE)
-
-#define RTGUI_WIDGET_UNFOCUS(w)			(w)->flag &= ~RTGUI_WIDGET_FLAG_FOCUS
-#define RTGUI_WIDGET_FOCUS(w)			(w)->flag |= RTGUI_WIDGET_FLAG_FOCUS
-#define RTGUI_WIDGET_IS_FOCUSED(w)		((w)->flag & RTGUI_WIDGET_FLAG_FOCUS)
-
-#define RTGUI_WIDGET_IS_FOCUSABLE(w) 	((w)->flag & RTGUI_WIDGET_FLAG_FOCUSABLE)
-
-#define RTGUI_WIDGET_IS_DC_VISIBLE(w)	((w)->flag & RTGUI_WIDGET_FLAG_DC_VISIBLE)
-#define RTGUI_WIDGET_DC_SET_VISIBLE(w)	(w)->flag |= RTGUI_WIDGET_FLAG_DC_VISIBLE 
-#define RTGUI_WIDGET_DC_SET_UNVISIBLE(w) (w)->flag &= ~RTGUI_WIDGET_FLAG_DC_VISIBLE
-#define RTGUI_WIDGET_DC(w)				((struct rtgui_dc*)&((w)->dc_type))
-
 /* rtgui widget attribute */
 #define RTGUI_WIDGET_FOREGROUND(w) 		(RTGUI_WIDGET(w)->gc.foreground)
 #define RTGUI_WIDGET_BACKGROUND(w)		(RTGUI_WIDGET(w)->gc.background)
@@ -59,6 +40,27 @@ extern "C" {
 #define RTGUI_WIDGET_FONT(w)			(RTGUI_WIDGET(w)->gc.font)
 #define RTGUI_WIDGET_FLAG(w)			(RTGUI_WIDGET(w)->flag)
 #define RTGUI_WIDGET_ALIGN(w)			(RTGUI_WIDGET(w)->align)
+#define RTGUI_WIDGET_BORDER(w)			(RTGUI_WIDGET(w)->border)
+#define RTGUI_WIDGET_BORDER_STYLE(w)	(RTGUI_WIDGET(w)->border_style)
+
+#define RTGUI_WIDGET_UNHIDE(w)			RTGUI_WIDGET_FLAG(w) |= RTGUI_WIDGET_FLAG_SHOWN
+#define RTGUI_WIDGET_HIDE(w)			RTGUI_WIDGET_FLAG(w) &= ~RTGUI_WIDGET_FLAG_SHOWN
+#define RTGUI_WIDGET_IS_HIDE(w)			(!(RTGUI_WIDGET_FLAG(w) & RTGUI_WIDGET_FLAG_SHOWN))
+
+#define RTGUI_WIDGET_ENABLE(w)			RTGUI_WIDGET_FLAG(w) &= ~RTGUI_WIDGET_FLAG_DISABLE
+#define RTGUI_WIDGET_DISABLE(w)			RTGUI_WIDGET_FLAG(w) |= RTGUI_WIDGET_FLAG_DISABLE
+#define RTGUI_WIDGET_IS_ENABLE(w)		(!((RTGUI_WIDGET_FLAG(w) & RTGUI_WIDGET_FLAG_DISABLE)))
+
+#define RTGUI_WIDGET_UNFOCUS(w)			RTGUI_WIDGET_FLAG(w) &= ~RTGUI_WIDGET_FLAG_FOCUS
+#define RTGUI_WIDGET_FOCUS(w)			RTGUI_WIDGET_FLAG(w) |= RTGUI_WIDGET_FLAG_FOCUS
+#define RTGUI_WIDGET_IS_FOCUSED(w)		(RTGUI_WIDGET_FLAG(w) & RTGUI_WIDGET_FLAG_FOCUS)
+
+#define RTGUI_WIDGET_IS_FOCUSABLE(w) 	(RTGUI_WIDGET_FLAG(w) & RTGUI_WIDGET_FLAG_FOCUSABLE)
+
+#define RTGUI_WIDGET_IS_DC_VISIBLE(w)	(RTGUI_WIDGET_FLAG(w) & RTGUI_WIDGET_FLAG_DC_VISIBLE)
+#define RTGUI_WIDGET_DC_SET_VISIBLE(w)	RTGUI_WIDGET_FLAG(w) |= RTGUI_WIDGET_FLAG_DC_VISIBLE 
+#define RTGUI_WIDGET_DC_SET_UNVISIBLE(w) RTGUI_WIDGET_FLAG(w) &= ~RTGUI_WIDGET_FLAG_DC_VISIBLE
+#define RTGUI_WIDGET_DC(w)				((struct rtgui_dc*)&((w)->dc_type))
 
 DECLARE_CLASS_TYPE(widget);
 
@@ -101,7 +103,8 @@ struct rtgui_widget
 	rt_int16_t mini_width, mini_height;
 	/* widget align */
 	rt_int32_t align;
-
+	rt_uint16_t border;
+	rt_uint16_t border_style;
 	/* the rect clip */
 	rtgui_region_t clip;
 
@@ -155,6 +158,7 @@ void rtgui_widget_set_oncommand(rtgui_widget_t* widget, rtgui_event_handler_ptr
 
 /* get and set rect of widget */
 void rtgui_widget_get_rect(rtgui_widget_t* widget, rtgui_rect_t *rect);
+void rtgui_widget_set_border(rtgui_widget_t* widget, rt_uint32_t style);
 void rtgui_widget_set_rect(rtgui_widget_t* widget, const rtgui_rect_t* rect);
 void rtgui_widget_set_rectangle(rtgui_widget_t* widget, int x, int y, int width, int height);
 void rtgui_widget_get_extent(rtgui_widget_t* widget, rtgui_rect_t *rect);

+ 11 - 9
components/rtgui/include/rtgui/widgets/window.h

@@ -29,16 +29,16 @@ DECLARE_CLASS_TYPE(win);
 /** Checks if the object is an rtgui_win */
 #define RTGUI_IS_WIN(obj)    (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_WIN_TYPE))
 
-#define RTGUI_WIN_STYLE_NO_FOCUS	        0x001	/* non-focused window			*/
+#define RTGUI_WIN_STYLE_NO_FOCUS	        0x0001	/* non-focused window			*/
+#define RTGUI_WIN_STYLE_NO_TITLE	        0x0002	/* no title window				*/
+#define RTGUI_WIN_STYLE_NO_BORDER	        0x0004	/* no border window				*/
+#define RTGUI_WIN_STYLE_CLOSEBOX	        0x0008	/* window has the close button	*/
+#define RTGUI_WIN_STYLE_MINIBOX		        0x0010	/* window has the mini button	*/
 
-#define RTGUI_WIN_STYLE_NO_TITLE	        0x002	/* no title window				*/
-#define RTGUI_WIN_STYLE_NO_BORDER	        0x004	/* no border window				*/
-#define RTGUI_WIN_STYLE_CLOSEBOX	        0x008	/* window has the close button	*/
-#define RTGUI_WIN_STYLE_MINIBOX		        0x010	/* window has the mini button	*/
-
-#define RTGUI_WIN_STYLE_DESTROY_ON_CLOSE	0x020   /* window is destroyed when closed */
-#define RTGUI_WIN_STYLE_ONTOP               0x040   /* window is in the top layer */
-#define RTGUI_WIN_STYLE_ONBTM               0x080   /* window is in the bottom layer */
+#define RTGUI_WIN_STYLE_DESTROY_ON_CLOSE	0x0020	/* window is destroyed when closed */
+#define RTGUI_WIN_STYLE_ONTOP               0x0040	/* window is in the top layer */
+#define RTGUI_WIN_STYLE_ONBTM               0x0080	/* window is in the bottom layer */
+#define RTGUI_WIN_STYLE_MAINWIN				0x0106	/* window is a main window */
 
 #define RTGUI_WIN_STYLE_DEFAULT		(RTGUI_WIN_STYLE_CLOSEBOX | RTGUI_WIN_STYLE_MINIBOX)
 
@@ -109,6 +109,8 @@ struct rtgui_win
 
 rtgui_win_t* rtgui_win_create(struct rtgui_win *parent_window, const char* title,
 							  rtgui_rect_t *rect, rt_uint16_t style);
+rtgui_win_t* rtgui_mainwin_create(struct rtgui_win *parent_window, const char* title, rt_uint16_t style);
+
 void rtgui_win_destroy(rtgui_win_t* win);
 
 /** Close window.

+ 24 - 1
components/rtgui/server/mouse.c

@@ -124,10 +124,12 @@ static void rtgui_winrect_show		(void);
 #endif
 
 #define WIN_MOVE_BORDER	4
-void rtgui_mouse_init()
+void rtgui_mouse_init(void)
 {
 	const struct rtgui_graphic_driver* gd = rtgui_graphic_driver_get_default();
 
+	if (_rtgui_cursor != RT_NULL) rtgui_mouse_fini();
+
 	_rtgui_cursor = (struct rtgui_cursor*) rtgui_malloc(sizeof(struct rtgui_cursor));
 	rt_memset(_rtgui_cursor, 0, sizeof(struct rtgui_cursor));
 
@@ -178,6 +180,27 @@ void rtgui_mouse_init()
 #endif
 }
 
+void rtgui_mouse_fini(void)
+{
+	if (_rtgui_cursor != RT_NULL)
+	{
+#ifdef RTGUI_USING_WINMOVE
+		rtgui_free(_rtgui_cursor->win_left);
+		rtgui_free(_rtgui_cursor->win_right);
+		rtgui_free(_rtgui_cursor->win_top);
+		rtgui_free(_rtgui_cursor->win_bottom);
+#endif
+#ifdef RTGUI_USING_MOUSE_CURSOR
+		rt_mutex_detach(&cursor_mutex);
+		rtgui_image_destroy(_rtgui_cursor->cursor_image);
+		rtgui_free(_rtgui_cursor->rtgui_malloc);
+#endif
+		rtgui_free(_rtgui_cursor);
+
+		_rtgui_cursor = RT_NULL;
+	}
+}
+
 void rtgui_mouse_moveto(int x, int y)
 {
 #ifdef RTGUI_USING_MOUSE_CURSOR

+ 1 - 0
components/rtgui/server/mouse.h

@@ -29,6 +29,7 @@ struct rtgui_mouse_monitor
 typedef struct rtgui_mouse_monitor rtgui_mouse_monitor_t;
 
 void rtgui_mouse_init(void);
+void rtgui_mouse_fini(void);
 void rtgui_mouse_moveto(int x, int y);
 
 void rtgui_mouse_set_cursor_enable(rt_bool_t enable);

+ 5 - 5
components/rtgui/server/topwin.c

@@ -551,23 +551,23 @@ rt_inline void _rtgui_topwin_mark_hidden(struct rtgui_topwin *topwin)
 	topwin->flag &= ~WINTITLE_SHOWN;
 	if (topwin->title != RT_NULL)
 	{
-		RTGUI_WIDGET_HIDE(RTGUI_WIDGET(topwin->title));
+		RTGUI_WIDGET_HIDE(topwin->title);
 	}
-	RTGUI_WIDGET_HIDE(RTGUI_WIDGET(topwin->wid));
+	RTGUI_WIDGET_HIDE(topwin->wid);
 }
 
 rt_inline void _rtgui_topwin_mark_shown(struct rtgui_topwin *topwin)
 {
 	if (!(topwin->flag & WINTITLE_SHOWN)
-		&& RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(topwin->wid)))
+		&& RTGUI_WIDGET_IS_HIDE(topwin->wid))
 		return;
 
 	topwin->flag |= WINTITLE_SHOWN;
 	if (topwin->title != RT_NULL)
 	{
-		RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(topwin->title));
+		RTGUI_WIDGET_UNHIDE(topwin->title);
 	}
-	RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(topwin->wid));
+	RTGUI_WIDGET_UNHIDE(topwin->wid);
 }
 
 static void _rtgui_topwin_draw_tree(struct rtgui_topwin *topwin, struct rtgui_event_paint *epaint)

+ 41 - 17
components/rtgui/widgets/box.c

@@ -45,7 +45,12 @@ struct rtgui_box* rtgui_box_create(int orientation, int border_size)
 	return box;
 }
 
-static void rtgui_box_layout_vertical(rtgui_box_t* box)
+void rtgui_box_destroy(struct rtgui_box* box)
+{
+	rtgui_object_destroy(RTGUI_OBJECT(box));
+}
+
+static void rtgui_box_layout_vertical(struct rtgui_box* box, struct rtgui_rect* extent)
 {
 	rtgui_list_t *node;
 	rt_int32_t box_width;
@@ -53,11 +58,9 @@ static void rtgui_box_layout_vertical(rtgui_box_t* box)
 	rt_int32_t next_x, next_y;
 	rt_int32_t total_height, space_height;
 	struct rtgui_event_resize size_event;
-	struct rtgui_widget *container_widget;
 	
 	/* prepare the resize event */
 	RTGUI_EVENT_RESIZE_INIT(&size_event);
-	container_widget = RTGUI_WIDGET(box->container);
 
 	/* find spaces */
 	space_count  = 0;
@@ -74,18 +77,18 @@ static void rtgui_box_layout_vertical(rtgui_box_t* box)
 	/* calculate the height for each spaces */
 	if (space_count != 0)
 	{
-		space_height = (rtgui_rect_height(container_widget->extent) - total_height - (box->border_size << 1)) / space_count;
+		space_height = (rtgui_rect_height(*extent) - total_height - (box->border_size << 1)) / space_count;
 	}
 
 	/* init (x, y) and box width */
-	next_x = container_widget->extent.x1 + box->border_size;
-	next_y = container_widget->extent.y1 + box->border_size;
-	box_width = rtgui_rect_width(container_widget->extent) - (box->border_size << 1);
+	next_x = extent->x1 + box->border_size;
+	next_y = extent->y1 + box->border_size;
+	box_width = rtgui_rect_width(*extent) - (box->border_size << 1);
 
 	/* layout each widget */
 	rtgui_list_foreach(node, &(box->container->children))
 	{
-		rtgui_rect_t *rect;
+		struct rtgui_rect *rect;
 		rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
 
 		/* get extent of widget */
@@ -140,7 +143,7 @@ static void rtgui_box_layout_vertical(rtgui_box_t* box)
 	}
 }
 
-static void rtgui_box_layout_horizontal(rtgui_box_t* box)
+static void rtgui_box_layout_horizontal(struct rtgui_box* box, struct rtgui_rect* extent)
 {
 	rtgui_list_t *node;
 	rt_int32_t box_height;
@@ -148,11 +151,9 @@ static void rtgui_box_layout_horizontal(rtgui_box_t* box)
 	rt_int32_t next_x, next_y;
 	rt_int32_t total_width, space_width;
 	struct rtgui_event_resize size_event;
-	struct rtgui_widget *container_widget;
 
 	/* prepare the resize event */
 	RTGUI_EVENT_RESIZE_INIT(&size_event);
-	container_widget = RTGUI_WIDGET(box->container);
 
 	/* find spaces */
 	space_count = 0;
@@ -169,13 +170,13 @@ static void rtgui_box_layout_horizontal(rtgui_box_t* box)
 	if (space_count != 0)
 	{
 		/* calculate the height for each spaces */
-		space_width = (rtgui_rect_width(container_widget->extent) - total_width) / space_count;
+		space_width = (rtgui_rect_width(*extent) - total_width) / space_count;
 	}
 
 	/* init (x, y) and box height */
-	next_x = container_widget->extent.x1 + box->border_size;
-	next_y = container_widget->extent.y1 + box->border_size;
-	box_height = rtgui_rect_height(container_widget->extent) - (box->border_size << 1);
+	next_x = extent->x1 + box->border_size;
+	next_y = extent->y1 + box->border_size;
+	box_height = rtgui_rect_height(*extent) - (box->border_size << 1);
 
 	/* layout each widget */
 	rtgui_list_foreach(node, &(box->container->children))
@@ -237,17 +238,19 @@ static void rtgui_box_layout_horizontal(rtgui_box_t* box)
 
 void rtgui_box_layout(rtgui_box_t* box)
 {
+	struct rtgui_rect extent;
     RT_ASSERT(box != RT_NULL);
 
 	if (box->container == RT_NULL) return;
 
+	rtgui_widget_get_extent(RTGUI_WIDGET(box->container), &extent);
 	if (box->orient & RTGUI_VERTICAL)
 	{
-		rtgui_box_layout_vertical(box);
+		rtgui_box_layout_vertical(box, &extent);
 	}
 	else
 	{
-		rtgui_box_layout_horizontal(box);
+		rtgui_box_layout_horizontal(box, &extent);
 	}
 
 	/* update box and its children clip */
@@ -257,3 +260,24 @@ void rtgui_box_layout(rtgui_box_t* box)
 	}
 }
 
+void rtgui_box_layout_rect(rtgui_box_t* box, struct rtgui_rect* rect)
+{
+	RT_ASSERT(box != RT_NULL);
+
+	if (box->container == RT_NULL) return;
+
+	if (box->orient & RTGUI_VERTICAL)
+	{
+		rtgui_box_layout_vertical(box, rect);
+	}
+	else
+	{
+		rtgui_box_layout_horizontal(box, rect);
+	}
+
+	/* update box and its children clip */
+	if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(box->container)))
+	{
+		rtgui_widget_update_clip(RTGUI_WIDGET(box->container));
+	}
+}

+ 3 - 3
components/rtgui/widgets/button.c

@@ -31,9 +31,9 @@ static void _rtgui_button_constructor(rtgui_button_t *button)
 	button->on_button = RT_NULL;
 
 	/* set gc */
-	RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(button)) = default_foreground;
-	RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(button)) = RTGUI_RGB(212, 208, 200);
-	RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(button)) = RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL;
+	RTGUI_WIDGET_FOREGROUND(button) = default_foreground;
+	RTGUI_WIDGET_BACKGROUND(button) = RTGUI_RGB(212, 208, 200);
+	RTGUI_WIDGET_TEXTALIGN(button) = RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL;
 }
 
 static void _rtgui_button_destructor(rtgui_button_t *button)

+ 1 - 1
components/rtgui/widgets/checkbox.c

@@ -13,7 +13,7 @@ static void _rtgui_checkbox_constructor(rtgui_checkbox_t *box)
 	box->on_button = RT_NULL;
 
 	/* set default gc */
-	RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(box)) = RTGUI_ALIGN_LEFT | RTGUI_ALIGN_CENTER_VERTICAL;
+	RTGUI_WIDGET_TEXTALIGN(box) = RTGUI_ALIGN_LEFT | RTGUI_ALIGN_CENTER_VERTICAL;
 }
 
 DEFINE_CLASS_TYPE(checkbox, "checkbox",

+ 4 - 4
components/rtgui/widgets/combobox.c

@@ -13,7 +13,7 @@ static void _rtgui_combobox_constructor(rtgui_combobox_t *box)
 	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;
+	RTGUI_WIDGET_TEXTALIGN(box) = RTGUI_ALIGN_CENTER_VERTICAL;
 
 	box->pd_pressed = RT_FALSE;
 	box->current_item = 0;
@@ -96,11 +96,11 @@ static void rtgui_combobox_ondraw(struct rtgui_combobox* box)
 	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(box));
 	if (dc == RT_NULL) return;
 
-	bc = RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(box));
+	bc = RTGUI_WIDGET_BACKGROUND(box);
 
 	/* get widget rect */
 	rtgui_widget_get_rect(RTGUI_WIDGET(box), &rect);
-	RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(box)) = white;
+	RTGUI_WIDGET_BACKGROUND(box) = white;
 
 	/* fill widget rect with background color */
 	rtgui_dc_fill_rect(dc, &rect);
@@ -114,7 +114,7 @@ static void rtgui_combobox_ondraw(struct rtgui_combobox* box)
 	}
 
 	/* restore background color */
-	RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(box)) = bc;
+	RTGUI_WIDGET_BACKGROUND(box) = bc;
 
 	/* draw pull down button */
 	rect.x1 = rect.x2 - RTGUI_COMBOBOX_BUTTON_WIDTH;

+ 1 - 1
components/rtgui/widgets/container.c

@@ -74,7 +74,7 @@ rt_bool_t rtgui_container_broadcast_event(struct rtgui_container *container, str
 		w = rtgui_list_entry(node, struct rtgui_widget, sibling);
 
 		if (RTGUI_OBJECT(w)->event_handler)
-			RTGUI_OBJECT(w)->event_handler(RTGUI_OBJECT(w), event) == RT_TRUE;
+			RTGUI_OBJECT(w)->event_handler(RTGUI_OBJECT(w), event);
 	}
 
 	return RT_FALSE;

+ 1666 - 0
components/rtgui/widgets/edit.c

@@ -0,0 +1,1666 @@
+/*
+ * File      : edit.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2012, 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
+ * 2012-06-04     amsl         firist version.
+ * 2012-08-09     amsl         beta 0.1
+ */
+#include <rtgui/dc.h>
+#include <rtgui/widgets/edit.h>
+#include <rtgui/widgets/scrollbar.h>
+#include <rtgui/rtgui_system.h>
+
+static void rtgui_edit_draw_caret(struct rtgui_edit *edit);
+static void rtgui_edit_timeout(struct rtgui_timer* timer, void* parameter);
+static rt_bool_t rtgui_edit_onfocus(struct rtgui_object* object, rtgui_event_t* event);
+static rt_bool_t rtgui_edit_onunfocus(struct rtgui_object* object, rtgui_event_t* event);
+static rt_bool_t rtgui_edit_hscroll_handle(struct rtgui_widget* widget, rtgui_event_t* event);
+static rt_bool_t rtgui_edit_vscroll_handle(struct rtgui_widget* widget, rtgui_event_t* event);
+
+void _rtgui_edit_constructor(struct rtgui_edit *edit)
+{
+	rtgui_rect_t font_rect;
+	RTGUI_WIDGET_FLAG(edit) |= RTGUI_WIDGET_FLAG_FOCUSABLE;
+
+	rtgui_object_set_event_handler(RTGUI_OBJECT(edit), rtgui_edit_event_handler);
+	rtgui_widget_set_onfocus(RTGUI_WIDGET(edit), rtgui_edit_onfocus);
+	rtgui_widget_set_onunfocus(RTGUI_WIDGET(edit), rtgui_edit_onunfocus);
+	
+	RTGUI_WIDGET_FOREGROUND(edit) = black;
+	RTGUI_WIDGET_BACKGROUND(edit) = white;
+	/* set default text align */
+	RTGUI_WIDGET_TEXTALIGN(edit) = RTGUI_ALIGN_CENTER_VERTICAL;
+	rtgui_widget_set_border(RTGUI_WIDGET(edit), RTGUI_BORDER_SUNKEN);
+	/* set proper of control */
+	edit->caret_timer = RT_NULL;
+	edit->caret = RT_NULL;
+
+	edit->tabsize = 4;
+	edit->margin  = 1;
+	edit->max_rows = edit->max_cols = 0;
+	edit->visual.x = edit->visual.y = 0;
+	edit->upleft.x = edit->upleft.y = 0;
+	edit->row_per_page = edit->col_per_page = 0;
+
+	edit->update_buf = RT_NULL;
+	edit->flag = RTGUI_EDIT_NONE;
+#ifdef RTGUI_EDIT_USING_SCROLL
+	edit->flag |= RTGUI_EDIT_VSCROLL;
+	edit->flag |= RTGUI_EDIT_HSCROLL;
+#endif
+	/* allocate default line buffer */
+	edit->bzsize = 16;
+	
+	rtgui_font_get_metrics(RTGUI_WIDGET_FONT(edit), "H", &font_rect);
+	edit->font_width = rtgui_rect_width(font_rect);
+	edit->font_height = rtgui_rect_height(font_rect);
+	
+	edit->head = RT_NULL;
+	edit->tail = RT_NULL;
+	edit->first_line = RT_NULL;
+#ifdef RTGUI_EDIT_USING_SCROLL	
+	edit->hscroll = RT_NULL;
+	edit->vscroll = RT_NULL;
+#endif
+}
+
+void _rtgui_edit_deconstructor(struct rtgui_edit *edit)
+{
+	if(edit->max_rows > 0)
+	{
+		while(edit->max_rows > 0)
+			rtgui_edit_delete_line(edit, edit->head);
+		edit->max_rows = 0;
+	}
+	if(edit->caret_timer != RT_NULL)
+		rtgui_timer_destory(edit->caret_timer);
+	edit->caret_timer = RT_NULL;
+
+	if(edit->caret != RT_NULL)
+		rtgui_free(edit->caret);
+	edit->caret = RT_NULL;
+	if(edit->update_buf != RT_NULL)
+		rtgui_free(edit->update_buf);
+}
+
+DEFINE_CLASS_TYPE(edit, "edit",
+                  RTGUI_CONTAINER_TYPE,
+                  _rtgui_edit_constructor,
+                  _rtgui_edit_deconstructor,
+                  sizeof(struct rtgui_edit));
+
+#ifdef RTGUI_EDIT_USING_SCROLL
+void rtgui_edit_adjust_scroll(rtgui_scrollbar_t *bar)
+{
+	struct rtgui_edit *edit;
+	
+	RT_ASSERT(bar != RT_NULL);
+	
+	if(bar->widget_link != RT_NULL)
+	{
+		rtgui_rect_t rect;
+		rt_uint32_t _left=0,_top=0,_width=RTGUI_DEFAULT_SB_WIDTH,_len=0;
+
+		edit = bar->widget_link;
+		rtgui_widget_get_rect(edit, &rect);
+		rtgui_widget_rect_to_device(edit,&rect);
+		if(bar->orient==RTGUI_HORIZONTAL)
+		{
+			if(RTGUI_WIDGET_IS_HIDE(edit->hscroll))
+			{
+				if(edit->max_rows > edit->row_per_page)
+				{
+					RTGUI_WIDGET_SHOW(edit->hscroll);
+					rtgui_scrollbar_set_line_step(edit->hscroll, 1);
+					rtgui_scrollbar_set_page_step(edit->hscroll, edit->row_per_page);
+					rtgui_scrollbar_set_range(edit->hscroll, edit->max_rows);
+				}
+				else
+					RTGUI_WIDGET_HIDE(edit->vscroll);
+				rtgui_widget_update_clip(RTGUI_WIDGET(edit));
+			}
+			else
+			{
+				_left = RTGUI_WIDGET_BORDER(edit);
+				_top = rtgui_rect_height(rect)-RTGUI_WIDGET_BORDER(edit)-_width;
+				_len = rtgui_rect_width(rect)-RTGUI_WIDGET_BORDER(edit)*2;
+				
+				if(!RTGUI_WIDGET_IS_HIDE(edit->vscroll)) 
+					_len -= _width;
+				rect.x1 += _left;
+				rect.y1 += _top;
+				rect.x2 = rect.x1+_len;
+				rect.y2 = rect.y1+_width;
+			}
+		}
+		else if(bar->orient==RTGUI_VERTICAL)
+		{
+			_left = rtgui_rect_width(rect)-RTGUI_WIDGET_BORDER(edit)-_width;
+			_top = RTGUI_WIDGET_BORDER(edit);
+			_len = rtgui_rect_height(rect)-RTGUI_WIDGET_BORDER(edit)*2;
+			
+			if(!RTGUI_WIDGET_IS_HIDE(edit->hscroll))  
+				_len -= _width;
+			rect.x1 += _left;
+			rect.y1 += _top;
+			rect.x2 = rect.x1+_width;
+			rect.y2 = rect.y1+_len;
+		}
+		rtgui_widget_set_rect(bar,&rect);
+	}
+}
+#endif
+
+struct rtgui_edit* rtgui_edit_create(struct rtgui_container* container, int left, int top, int w, int h)
+{
+	struct rtgui_edit* edit;
+
+	RT_ASSERT(container != RT_NULL);
+
+	edit = (struct rtgui_edit*)rtgui_widget_create(RTGUI_EDIT_TYPE);
+	if(edit != RT_NULL)
+	{
+		rtgui_rect_t rect;
+		int effe;
+		rtgui_widget_get_rect(RTGUI_WIDGET(container), &rect);
+		rtgui_widget_rect_to_device(RTGUI_WIDGET(container),&rect);
+		rect.x1 += left;
+		rect.y1 += top;
+		rect.x2 = rect.x1+w;
+		rect.y2 = rect.y1+h;
+		rtgui_widget_set_rect(RTGUI_WIDGET(edit),&rect);
+		rtgui_container_add_child(container, RTGUI_WIDGET(edit));
+
+		/* set character number */
+		edit->item_height = edit->font_height; /* the same height */
+		effe = h-(edit->margin + RTGUI_WIDGET_BORDER(edit))*2;
+		edit->row_per_page = effe / edit->item_height;
+		if(effe % edit->item_height)
+			edit->row_per_page += 1;
+		
+		effe = w-(edit->margin + RTGUI_WIDGET_BORDER(edit))*2;
+		edit->col_per_page = effe / edit->font_width;
+		if(effe % edit->font_width)
+			edit->col_per_page += 1;
+		edit->update_buf = rtgui_malloc(edit->col_per_page + 1);
+
+#ifdef RTGUI_EDIT_USING_SCROLL
+		if(edit->hscroll == RT_NULL && edit->flag & RTGUI_EDIT_HSCROLL)
+		{
+			/* create horizontal scrollbar */
+			rt_uint32_t _left,_top,_width=RTGUI_DEFAULT_SB_WIDTH,_len;
+			_left = RTGUI_WIDGET_BORDER(edit);
+			_top = rtgui_rect_height(rect)-RTGUI_WIDGET_BORDER(edit)-_width;
+			_len = rtgui_rect_width(rect)-RTGUI_WIDGET_BORDER(edit)*2;
+			if(edit->max_rows > edit->row_per_page)	_len -= _width;
+
+			edit->hscroll = rtgui_scrollbar_create(edit,_left,_top,_width,_len,RTGUI_HORIZONTAL);
+
+			if(edit->hscroll != RT_NULL)
+			{
+				edit->hscroll->widget_link = (pvoid)edit;
+				edit->hscroll->on_scroll = rtgui_edit_hscroll_handle;
+				RTGUI_WIDGET_HIDE(edit->hscroll);
+			}
+		}
+		if(edit->vscroll == RT_NULL && edit->flag & RTGUI_EDIT_VSCROLL)
+		{
+			/* create vertical scrollbar */
+			rt_uint32_t _left,_top,_width=RTGUI_DEFAULT_SB_WIDTH,_len;
+			_left = rtgui_rect_width(rect)-RTGUI_WIDGET_BORDER(edit)-_width;
+			_top = RTGUI_WIDGET_BORDER(edit);
+			_len = rtgui_rect_height(rect)-RTGUI_WIDGET_BORDER(edit)*2;
+			if(edit->max_cols > edit->col_per_page) _len -= _width;
+
+			edit->vscroll = rtgui_scrollbar_create(edit,_left,_top,_width,_len,RTGUI_VERTICAL);
+
+			if(edit->vscroll != RT_NULL)
+			{
+				edit->vscroll->widget_link = (pvoid)edit;
+				edit->vscroll->on_scroll = rtgui_edit_vscroll_handle;
+				RTGUI_WIDGET_HIDE(edit->vscroll);
+			}
+		}
+#endif
+	}
+
+	return edit;
+}
+
+void rtgui_edit_destroy(struct rtgui_edit* edit)
+{
+	rtgui_widget_destroy(RTGUI_WIDGET(edit));
+}
+
+/**
+ * calc line buffer alloc length
+ *
+ * @param n a standard buffer value, please use edit->bzsize
+ * @param m given a reference value
+ *
+ * @return get a proper standard values 
+ */
+rt_inline rt_size_t rtgui_edit_alloc_len(rt_size_t n, rt_size_t m)
+{
+	if(n > m) return n;
+#ifndef RTGUI_USING_SMALL_SIZE
+	return rtgui_edit_alloc_len(n*2, m);
+#else
+	return rtgui_edit_alloc_len(n+16, m);
+#endif
+}
+
+/**
+ * please use it to replace rt_strlen
+ * especially in reading the source file.
+ */
+rt_inline rt_size_t rtgui_edit_line_strlen(const char *s)
+{
+	const char *sc;
+	/* ascii text end of 0x0A or 0x0D-0x0A*/
+	for(sc = s; *sc != 0x0D && *sc != 0x0A && *sc != 0x00; ++sc);  
+	return sc - s;
+}
+
+rt_bool_t rtgui_edit_append_line(struct rtgui_edit* edit, const char *text)
+{
+	rt_size_t len;
+	struct edit_line *line, *node;
+
+	RT_ASSERT(edit != RT_NULL);
+
+	line = rtgui_malloc(sizeof(struct edit_line));
+	if(line == RT_NULL) return RT_FALSE;
+
+	len = rtgui_edit_line_strlen(text);
+	line->zsize = rtgui_edit_alloc_len(edit->bzsize, len+1);
+	line->text = rtgui_malloc(line->zsize);
+	rt_memcpy(line->text, text, len);
+	*(line->text+len) = '\0';
+	line->len = rtgui_edit_line_strlen(line->text);
+	
+	line->next = RT_NULL;
+	edit->max_rows++;
+	if(edit->max_cols < len) edit->max_cols = len;
+
+	node = edit->head;
+	if(node == RT_NULL)
+	{
+		edit->head = line;
+		edit->tail = line;
+		line->prev = RT_NULL;
+		return RT_TRUE;
+	}
+	while(node->next != RT_NULL) node = node->next;
+	/* to tail item on to queue */
+	node->next = line;
+	line->prev = node;
+	/* re-fixed position tail */
+	edit->tail = line;
+	
+	return RT_TRUE;
+}
+
+rt_bool_t rtgui_edit_insert_line(struct rtgui_edit *edit, struct edit_line *p, char *text)
+{
+	rt_size_t len;
+	struct edit_line *line;
+
+	RT_ASSERT(edit != RT_NULL);
+	RT_ASSERT(p != RT_NULL);
+
+	if(p->next == RT_NULL)
+	{
+		rtgui_edit_append_line(edit, text);
+		return RT_TRUE;
+	}
+
+	line = rtgui_malloc(sizeof(struct edit_line));
+	if(line == RT_NULL) return RT_FALSE;
+
+	line->prev = p;
+	line->next = p->next;
+	p->next = line;
+	if(line->next != RT_NULL)
+	{
+		line->next->prev = line;
+	}
+
+	len = rtgui_edit_line_strlen(text);
+	line->zsize = rtgui_edit_alloc_len(edit->bzsize, len+1);
+	
+	line->text = rtgui_malloc(line->zsize);
+	rt_memset(line->text, 0, line->zsize);
+	rt_memcpy(line->text, text, len);
+	*(line->text+len) = '\0';
+	
+	edit->max_rows ++;
+	line->len = rtgui_edit_line_strlen(line->text);
+	
+	return RT_TRUE;
+}
+
+rt_bool_t rtgui_edit_delete_line(struct rtgui_edit* edit, struct edit_line *line)
+{
+	RT_ASSERT(edit != RT_NULL);
+	RT_ASSERT(line != RT_NULL);
+
+	if(edit->max_rows == 0) return RT_FALSE;
+
+	if(line->prev == RT_NULL)
+	{
+		if(line->next == RT_NULL)
+		{
+			/* only one item */
+			edit->head = RT_NULL;
+			edit->tail = RT_NULL;
+		}
+		else
+		{
+			/* first item */
+			line->next->prev = RT_NULL;
+			edit->head = line->next;
+		}
+	}
+	else
+	{
+		if(line->next == RT_NULL)
+		{
+			/* last item */
+			line->prev->next = RT_NULL;
+			edit->tail = line->prev;
+		}
+		else
+		{
+			/* middle item */
+			line->prev->next = line->next;
+			line->next->prev = line->prev;
+		}
+	}
+
+	if(edit->max_rows > 0)edit->max_rows--;
+	if(line->text)
+	{
+		rtgui_free(line->text);
+		line->text = RT_NULL;
+	}
+	rtgui_free(line);
+	line = RT_NULL;
+
+	return RT_TRUE;
+}
+
+rt_bool_t rtgui_edit_connect_line(struct rtgui_edit* edit, struct edit_line *line, struct edit_line *connect)
+{
+	rt_size_t len1,len2;
+	
+	RT_ASSERT(edit != RT_NULL);
+	RT_ASSERT(line != RT_NULL);
+	RT_ASSERT(connect != RT_NULL);
+
+	len1 = rtgui_edit_line_strlen(line->text);
+	len2 = rtgui_edit_line_strlen(connect->text);
+
+	line->zsize = rtgui_edit_alloc_len(edit->bzsize, len1+len2+1);
+	line->text = rt_realloc(line->text, line->zsize);
+	rt_memcpy(line->text+len1, connect->text, len2);
+	*(line->text+len1+len2) = '\0';
+
+	line->len = rtgui_edit_line_strlen(line->text);
+	return RT_TRUE;
+}
+
+static void rtgui_edit_get_caret_rect(struct rtgui_edit *edit, rtgui_rect_t *rect, rtgui_point_t visual)
+{
+	RT_ASSERT(edit != RT_NULL);
+
+	rtgui_widget_get_rect(RTGUI_WIDGET(edit), rect);
+
+	rect->x1 += visual.x * edit->font_width + RTGUI_WIDGET_BORDER(edit) + edit->margin;
+	rect->x2 = rect->x1+1; /* caret width: 1 */
+	rect->y1 += visual.y * edit->item_height + RTGUI_WIDGET_BORDER(edit) + edit->margin;
+	if((rect->y1 + edit->font_height) < (rect->y2 - RTGUI_WIDGET_BORDER(edit) - edit->margin))
+		rect->y2 = rect->y1 + edit->font_height;
+	else
+		rect->y2 = rect->y2 - RTGUI_WIDGET_BORDER(edit) - edit->margin;
+}
+
+static void rtgui_edit_init_caret(struct rtgui_edit *edit, rtgui_point_t visual)
+{
+	struct rtgui_graphic_driver *hw_driver = rtgui_graphic_driver_get_default();
+	int x, y;
+	rtgui_color_t color;
+	rtgui_rect_t rect;
+	int ofs=0;
+
+	RT_ASSERT(edit != RT_NULL);
+	if(!RTGUI_WIDGET_IS_FOCUSED(edit)) return;
+
+	rtgui_edit_get_caret_rect(edit, &edit->caret_rect, visual);
+	rect = edit->caret_rect;
+	rtgui_widget_rect_to_device(RTGUI_WIDGET(edit), &rect);
+
+	if(edit->caret == RT_NULL)
+		edit->caret = (rtgui_color_t*)rtgui_malloc(rtgui_rect_width(rect) * rtgui_rect_height(rect)*sizeof(rtgui_color_t));
+	rtgui_timer_stop(edit->caret_timer);
+
+	for(x=rect.x1; x<rect.x2; x++)
+	{
+		for(y=rect.y1; y<rect.y2; y++)
+		{
+			hw_driver->ops->get_pixel(&color,x,y);
+			*(edit->caret + ofs++) = color;
+		}
+	}
+
+	rtgui_timer_start(edit->caret_timer);
+}
+
+/* draw caret */
+static void rtgui_edit_draw_caret(struct rtgui_edit *edit)
+{
+	int x,y;
+	rtgui_color_t color;
+	rtgui_rect_t rect;
+	int ofs=0;
+	struct rtgui_dc *dc;
+
+	RT_ASSERT(edit != RT_NULL);
+	if(edit->caret == RT_NULL) return;
+
+	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(edit));
+	if(dc == RT_NULL)return;
+
+	rect = edit->caret_rect;
+
+	for(x=rect.x1; x<rect.x2; x++)
+	{
+		for(y=rect.y1; y<rect.y2; y++)
+		{
+			color = *(edit->caret + ofs);
+			ofs++;
+			if(edit->flag & RTGUI_EDIT_CARET)
+			{
+				color = ~color;
+				rtgui_dc_draw_color_point(dc, x,y, color);
+			}
+			else
+			{
+				rtgui_dc_draw_color_point(dc, x,y, color);
+			}
+		}
+	}
+
+	rtgui_dc_end_drawing(dc);
+}
+
+static void rtgui_edit_timeout(struct rtgui_timer* timer, void* parameter)
+{
+	struct rtgui_edit* edit;
+
+	edit = RTGUI_EDIT(parameter);
+	/* set caret flag */
+	if(edit->flag & RTGUI_EDIT_CARET)
+		edit->flag &= ~RTGUI_EDIT_CARET;
+	else
+		edit->flag |= RTGUI_EDIT_CARET;
+
+	rtgui_edit_draw_caret(edit);
+
+	return;
+}
+
+struct edit_line* rtgui_edit_get_line_by_index(struct rtgui_edit *edit, rt_uint32_t index)
+{
+	struct edit_line *line = RT_NULL;
+	
+	RT_ASSERT(edit != RT_NULL);
+	
+	if(edit->head != RT_NULL)
+	{
+		int i=0;
+		line = edit->first_line;
+		while(line)
+		{
+			if((edit->upleft.y + i++)  == index) 
+				break;
+			line = line->next;
+		}
+	}
+	return line;
+}
+
+rt_uint32_t rtgui_edit_get_index_by_line(struct rtgui_edit *edit, struct edit_line *line)
+{
+	rt_uint32_t  index=0;
+	struct edit_line *tmp;
+	
+	RT_ASSERT(edit != RT_NULL);
+	RT_ASSERT(line != RT_NULL);
+	
+	if(edit->head != RT_NULL)
+	{
+		tmp = edit->first_line;
+		index = edit->upleft.y;
+		while(tmp)
+		{
+			if(tmp == line)
+				break;
+			index ++;
+			tmp = tmp->next;
+		}
+	}
+	return index;
+}
+
+static void rtgui_edit_onmouse(struct rtgui_edit* edit, struct rtgui_event_mouse* emouse)
+{
+	rtgui_rect_t rect;
+
+	RT_ASSERT(edit != RT_NULL);
+	RT_ASSERT(emouse != RT_NULL);
+
+	rtgui_widget_get_rect(RTGUI_WIDGET(edit), &rect);
+	if((rtgui_region_contains_point(&(RTGUI_WIDGET(edit)->clip), emouse->x, emouse->y, &rect) == RT_EOK))
+	{
+		rt_uint16_t x, y;
+
+		/* multiline text */
+		x = (emouse->x - rect.x1) / (edit->font_width);
+		y = (emouse->y - rect.y1) / (edit->item_height);
+		if((x < edit->col_per_page) && (y < edit->row_per_page))
+		{
+			if(emouse->button & RTGUI_MOUSE_BUTTON_DOWN)
+			{
+				struct edit_line *line;
+				
+				edit->visual.x = x;
+				edit->visual.y = y;
+				
+				line = rtgui_edit_get_line_by_index(edit, edit->upleft.y+edit->visual.y);
+				if(line == RT_NULL)
+					return;
+				
+				if(edit->visual.x > line->len)
+					edit->visual.x = line->len;
+				
+				if(edit->flag & RTGUI_EDIT_CARET)
+				{
+					if(edit->caret_timer != RT_NULL)
+						rtgui_timer_stop(edit->caret_timer);
+
+					edit->flag &= ~RTGUI_EDIT_CARET;
+					rtgui_edit_draw_caret(edit);
+
+					if(edit->caret_timer != RT_NULL)
+						rtgui_timer_start(edit->caret_timer);
+				}
+
+				/* set widget focus */
+				rtgui_widget_focus(RTGUI_WIDGET(edit));
+
+				if(RTGUI_WIDGET_IS_FOCUSED(edit))
+				{
+					rtgui_edit_init_caret(edit, edit->visual);
+					edit->flag |= RTGUI_EDIT_CARET;
+					rtgui_edit_draw_caret(edit);
+				}
+			}
+			else if(emouse->button & RTGUI_MOUSE_BUTTON_UP)
+			{
+				/* please add codes at here. */
+			}
+#ifdef RTGUI_EDIT_USING_SCROLL			
+			if(edit->vscroll && !RTGUI_WIDGET_IS_HIDE(edit))
+			{
+				if(!RTGUI_WIDGET_IS_HIDE(edit->vscroll))
+					rtgui_scrollbar_set_value(edit->vscroll,edit->upleft.y);
+			}
+			if(edit->hscroll && !RTGUI_WIDGET_IS_HIDE(edit))
+			{
+				if(!RTGUI_WIDGET_IS_HIDE(edit->hscroll))
+					rtgui_scrollbar_set_value(edit->hscroll,edit->upleft.x);
+			}
+#endif
+		}
+	}		
+}
+
+rt_inline rt_uint16_t query_shift_code(rt_uint16_t key)
+{
+	if(key >= RTGUIK_a && key <= RTGUIK_z)
+		return (key - ('a'-'A'));
+	else
+	{
+		switch (key)
+		{
+		case '1': return '!';
+		case '2': return '@';
+		case '3': return '#';
+		case '4': return '$';
+		case '5': return '%';
+		case '6': return '^';
+		case '7': return '&';
+		case '8': return '*';
+		case '9': return '(';
+		case '0': return ')';
+		case '-': return '_';
+		case '=': return '+';
+		case '\\':return '|';
+		case ';': return ':';
+		case '\'':return '"';
+		case ',': return '<';
+		case '.': return '>';
+		case '/': return '?';
+		case '`': return '~';
+		}
+	}
+	return key;
+}
+
+rt_inline rt_uint16_t query_caps_code(rt_uint16_t key)
+{
+	if(key >= RTGUIK_a && key <= RTGUIK_z)
+		return (key - ('a'-'A'));
+	return key;
+}
+
+rt_inline rt_bool_t is_small_keyboard(rt_uint16_t *key)
+{
+	if(*key >= RTGUIK_KP0 && *key <= RTGUIK_KP9)
+	{
+		*key = *key - (RTGUIK_KP0 - RTGUIK_0);
+		return RT_TRUE;
+	}
+	else if(*key == RTGUIK_KP_PERIOD)
+	{
+		*key = '.';
+		return RT_TRUE;
+	}
+	else if(*key == RTGUIK_KP_DIVIDE)
+	{
+		*key = '/';
+		return RT_TRUE;
+	}
+	else if(*key == RTGUIK_KP_MULTIPLY)
+	{
+		*key = '*';
+		return RT_TRUE;
+	}
+	else if(*key == RTGUIK_KP_MINUS)
+	{
+		*key = '-';
+		return RT_TRUE;
+	}
+	else if(*key == RTGUIK_KP_PLUS)
+	{
+		*key = '+';
+		return RT_TRUE;
+	}
+	else if(*key == RTGUIK_KP_ENTER)
+	{
+		*key = RTGUIK_RETURN;
+		return RT_TRUE;
+	}
+	return RT_FALSE;
+}
+
+void kbd_event_set_key(struct rtgui_event_kbd *ekbd, rt_uint16_t key)
+{
+	RTGUI_EVENT_KBD_INIT(ekbd);
+	ekbd->mod  = RTGUI_KMOD_NONE;
+	ekbd->unicode = 0;
+
+	ekbd->key = key;
+	ekbd->type = RTGUI_KEYDOWN;
+}
+
+static rt_bool_t rtgui_edit_onkey(struct rtgui_object* object, rtgui_event_t* event)
+{
+	enum { EDIT_NONE, EDIT_ONDRAW, EDIT_UPDATE };
+	struct rtgui_edit *edit = RTGUI_EDIT(object);
+	struct rtgui_event_kbd *ekbd = (struct rtgui_event_kbd*)event;
+	struct edit_line *line=RT_NULL;
+	rt_bool_t update_type = EDIT_NONE;
+	
+	RT_ASSERT(edit != RT_NULL);
+	RT_ASSERT(ekbd != RT_NULL);
+
+	if (RTGUI_KBD_IS_UP(ekbd))
+	{	/* reset function key */
+		if(ekbd->key == RTGUIK_RCTRL || ekbd->key == RTGUIK_LCTRL)
+			edit->flag &= ~RTGUI_EDIT_CTRL;
+		else if(ekbd->key == RTGUIK_RALT || ekbd->key == RTGUIK_LALT)
+			edit->flag &= ~RTGUI_EDIT_ALT;
+		else if(ekbd->key == RTGUIK_RSHIFT || ekbd->key == RTGUIK_LSHIFT)
+			edit->flag &= ~RTGUI_EDIT_SHIFT;
+		else if(ekbd->key == RTGUIK_CAPSLOCK)
+			edit->flag &= ~RTGUI_EDIT_CAPSLOCK;
+		else if(ekbd->key == RTGUIK_NUMLOCK)
+			edit->flag &= ~RTGUI_EDIT_NUMLOCK;
+		return RT_TRUE;
+	}
+	
+	line = rtgui_edit_get_line_by_index(edit, edit->upleft.y + edit->visual.y);
+	if(line == RT_NULL) 
+		return RT_FALSE;
+
+	/* rt_kprintf("key=%04X ",ekbd->key); */
+	if(ekbd->key == RTGUIK_RCTRL || ekbd->key == RTGUIK_LCTRL)
+	{	/* use CTRL key */
+		edit->flag |= RTGUI_EDIT_CTRL;
+		return RT_FALSE;
+	}
+	else if(ekbd->key == RTGUIK_RALT || ekbd->key == RTGUIK_LALT)
+	{	/* use ALT key */
+		edit->flag |= RTGUI_EDIT_ALT;
+		return RT_FALSE;
+	}
+	else if(ekbd->key == RTGUIK_RSHIFT || ekbd->key == RTGUIK_LSHIFT)
+	{	/* use SHIFT key */
+		edit->flag |= RTGUI_EDIT_SHIFT;
+		return RT_FALSE;
+	}
+	else if(ekbd->key == RTGUIK_CAPSLOCK)
+	{
+		edit->flag |= RTGUI_EDIT_CAPSLOCK;
+		return RT_FALSE;
+	}
+	else if(ekbd->key == RTGUIK_NUMLOCK)
+	{
+		edit->flag |= RTGUI_EDIT_NUMLOCK;
+		return RT_FALSE;
+	}
+	else if(ekbd->key == RTGUIK_DELETE)
+	{	/* delete latter character */
+		int ofs = edit->upleft.x + edit->visual.x;
+		if(ofs > line->len - 1 || (ofs==0 && line->len==0))
+		{	/* will the next line marges into the current line */
+			struct edit_line* next_line = line->next;
+			if(next_line != RT_NULL)
+			{
+				struct edit_line *update_end_line;
+				
+				update_type = EDIT_UPDATE;
+				edit->update.start = edit->visual;
+
+				rtgui_edit_connect_line(edit, line, next_line);
+				rtgui_edit_delete_line(edit, next_line);
+
+				if(edit->max_rows-edit->upleft.y > edit->row_per_page)
+				{
+					update_end_line = rtgui_edit_get_line_by_index(edit, edit->upleft.y+edit->row_per_page);
+					if(update_end_line != RT_NULL)
+					{
+						edit->update.end.x = edit->col_per_page;
+						edit->update.end.y = edit->upleft.y + edit->row_per_page;
+					}
+				}
+				else
+				{
+					int update_end_index = rtgui_edit_get_index_by_line(edit, edit->tail);
+					edit->update.end.x = edit->col_per_page;
+					edit->update.end.y = update_end_index+1;
+				}
+			}
+			line->len = rtgui_edit_line_strlen(line->text);
+			goto _edit_exit;
+		}
+		else if(ofs == line->len - 1)
+		{
+			line->text[ofs] = '\0';
+		}
+		else
+		{
+			char *c;
+			/* remove character */
+			for(c = &line->text[ofs]; c[1] != '\0'; c++)
+				*c = c[1];
+			*c = '\0';
+		}
+		update_type = EDIT_UPDATE;
+		edit->update.start = edit->visual;
+		edit->update.end.x = line->len-edit->upleft.x;
+		if (edit->update.end.x > edit->col_per_page)
+			edit->update.end.x = edit->col_per_page;
+		edit->update.end.y = edit->visual.y;
+	}
+	else if(ekbd->key == RTGUIK_BACKSPACE)
+	{	
+		if(edit->visual.x == 0)
+		{   /* incorporated into prev line */
+			struct rtgui_event_kbd event_kbd;
+			struct edit_line* prev_line = line->prev;
+			if(prev_line != RT_NULL)
+			{
+				struct edit_line *update_end_line;
+				
+				update_type = EDIT_UPDATE;
+				edit->visual.x = prev_line->len;
+
+				rtgui_edit_connect_line(edit, prev_line, line);
+				kbd_event_set_key(&event_kbd, RTGUIK_UP);
+				rtgui_edit_onkey(object, (rtgui_event_t*)&event_kbd);
+				rtgui_edit_delete_line(edit, line);
+
+				edit->update.start = edit->visual; /* update.start.y is changed */
+				if(edit->max_rows-edit->upleft.y > edit->row_per_page)
+				{
+					update_end_line = rtgui_edit_get_line_by_index(edit, edit->upleft.y+edit->row_per_page);
+					if(update_end_line != RT_NULL)
+					{
+						edit->update.end.x = edit->col_per_page;
+						edit->update.end.y = edit->upleft.y + edit->row_per_page;
+					}
+				}
+				else
+				{
+					int update_end_index = rtgui_edit_get_index_by_line(edit, edit->tail);
+					edit->update.end.x = edit->col_per_page;
+					edit->update.end.y = update_end_index+1;
+				}
+			}
+			goto _edit_exit;
+		}
+		
+		/* delete front character */
+		if(edit->visual.x == line->len)
+		{
+			line->text[edit->visual.x-1] = '\0';
+			edit->visual.x --;
+		}
+		else if(edit->visual.x != 0)
+		{	/* remove current character */
+			char *c;
+			/* remove character */
+			for(c = &line->text[edit->visual.x - 1]; c[1] != '\0'; c++)
+			{
+				*c = c[1];
+			}
+			*c = '\0';
+			edit->visual.x --;
+		}
+		/* adjusted line buffer length */
+		if(rtgui_edit_alloc_len(edit->bzsize, line->len+2) < line->zsize)
+		{	
+			line->zsize = rtgui_edit_alloc_len(edit->bzsize, line->len+1);
+			line->text = rt_realloc(line->text, line->zsize);
+		}
+		update_type = EDIT_UPDATE;
+		edit->update.start = edit->visual; 
+		edit->update.end.x = line->len;
+		edit->update.end.y = edit->visual.y;
+	}
+	else if(ekbd->key == RTGUIK_UP)
+	{	/* move to prev line */
+		struct edit_line* prev_line;
+		if(edit->visual.y > 0)
+			edit->visual.y --;
+		else
+		{
+			/* change first row */
+			if(edit->upleft.y > 0)
+			{
+				edit->upleft.y --;
+				if(edit->first_line->prev != RT_NULL)
+					edit->first_line = edit->first_line->prev;
+				update_type = EDIT_ONDRAW;
+			}
+		}
+		
+		/* The position of the recount X */
+		prev_line = rtgui_edit_get_line_by_index(edit, edit->upleft.y+edit->visual.y);
+		if(prev_line == RT_NULL)
+			return RT_FALSE;
+
+		if(edit->upleft.x > 0)
+		{
+			if(prev_line->len <= edit->upleft.x)
+			{
+				edit->upleft.x = 0;
+				edit->visual.x = prev_line->len;
+				update_type = EDIT_ONDRAW;
+			}
+			else if(prev_line->len - edit->upleft.x < edit->col_per_page)
+				edit->visual.x = prev_line->len - edit->upleft.x;
+		}
+		else if(edit->visual.x > prev_line->len)
+			edit->visual.x = prev_line->len;
+
+#ifdef RTGUI_EDIT_USING_SCROLL		
+		/* update vscroll */
+		if(edit->vscroll && !RTGUI_WIDGET_IS_HIDE(edit))
+		{
+			if(!RTGUI_WIDGET_IS_HIDE(edit->vscroll))
+				rtgui_scrollbar_set_value(edit->vscroll,edit->upleft.y);
+		}
+#endif
+	}
+	else if(ekbd->key == RTGUIK_DOWN)
+	{	
+		struct edit_line *tail_line, *next_line;
+		tail_line = rtgui_edit_get_line_by_index(edit, edit->upleft.y + edit->visual.y);
+		if(tail_line != RT_NULL)
+		{	/* it is tail line */
+			if(tail_line == edit->tail) return RT_FALSE;
+		}
+		/* move to next line */
+		if(edit->visual.y < edit->row_per_page - 2)
+		{
+			edit->visual.y ++;
+		}
+		else if(edit->visual.y+edit->upleft.y < edit->max_rows-1)
+		{
+			/* change first row */
+			edit->upleft.y++;
+			if(edit->first_line->next != RT_NULL)
+				edit->first_line = edit->first_line->next;
+			update_type = EDIT_ONDRAW;
+		}
+		
+		/* adjust next line end position */
+		next_line = rtgui_edit_get_line_by_index(edit, edit->upleft.y+edit->visual.y);
+		if(next_line == RT_NULL)	
+			return RT_FALSE;
+		
+		if(edit->upleft.x > 0)
+		{
+			if(next_line->len <= edit->upleft.x)
+			{
+				edit->upleft.x = 0;
+				edit->visual.x = next_line->len;
+				update_type = EDIT_ONDRAW;
+			}
+			else if(next_line->len - edit->upleft.x < edit->col_per_page)
+				edit->visual.x = next_line->len - edit->upleft.x;
+		}
+		else if(edit->visual.x > next_line->len)
+			edit->visual.x = next_line->len;
+
+#ifdef RTGUI_EDIT_USING_SCROLL		
+		/* update vscroll */
+		if(edit->vscroll && !RTGUI_WIDGET_IS_HIDE(edit))
+		{
+			if(!RTGUI_WIDGET_IS_HIDE(edit->vscroll))
+				rtgui_scrollbar_set_value(edit->vscroll,edit->upleft.y);
+		}
+#endif
+	}
+	else if(ekbd->key == RTGUIK_LEFT)
+	{	/* move to prev char */
+		if(edit->visual.x > 0)
+			edit->visual.x --;
+		else
+		{
+			if(edit->upleft.x > 0)
+			{
+				edit->upleft.x --;
+				update_type = EDIT_ONDRAW;
+			}
+			else
+			{	
+				struct rtgui_event_kbd event_kbd;
+				struct edit_line* first_line;
+				first_line = rtgui_edit_get_line_by_index(edit, edit->upleft.y + edit->visual.y);
+				if(first_line != RT_NULL)
+				{	/* it is head line */
+					if(first_line == edit->head) return RT_FALSE;
+				}
+				/* move the caret to the prev line end */
+				kbd_event_set_key(&event_kbd, RTGUIK_UP);
+				rtgui_edit_onkey(object, (rtgui_event_t*)&event_kbd);
+				kbd_event_set_key(&event_kbd, RTGUIK_END);
+				rtgui_edit_onkey(object, (rtgui_event_t*)&event_kbd);
+			}
+		}
+	}
+	else if(ekbd->key == RTGUIK_RIGHT)
+	{	/* move to next char */
+		if(line->len >= edit->col_per_page)
+		{
+			if(edit->upleft.x+edit->col_per_page <= line->len)
+			{
+				if(edit->visual.x < edit->col_per_page-1)
+					edit->visual.x ++;
+				else if(edit->visual.x == edit->col_per_page-1)
+				{
+					if(edit->upleft.x+edit->col_per_page < line->len)
+						edit->upleft.x ++;
+					else
+						edit->upleft.x = line->len - edit->col_per_page + 1;
+					update_type = EDIT_ONDRAW;
+				}
+			}
+			else
+			{
+				struct rtgui_event_kbd event_kbd;
+				/* move to next head */
+				kbd_event_set_key(&event_kbd, RTGUIK_DOWN);
+				rtgui_edit_onkey(object, (rtgui_event_t*)&event_kbd);
+				kbd_event_set_key(&event_kbd, RTGUIK_HOME);
+				rtgui_edit_onkey(object, (rtgui_event_t*)&event_kbd);
+			}
+		}
+		else
+		{
+			if(edit->visual.x < line->len)
+				edit->visual.x ++;
+			else
+			{
+				struct rtgui_event_kbd event_kbd;
+				struct edit_line* tail_line;
+				tail_line = rtgui_edit_get_line_by_index(edit, edit->upleft.y + edit->visual.y);
+				if(tail_line != RT_NULL)
+				{	/* it is tail line */
+					if(tail_line == edit->tail) return RT_FALSE;
+				}
+				/* move the caret to the next line head */
+				kbd_event_set_key(&event_kbd, RTGUIK_DOWN);
+				rtgui_edit_onkey(object, (rtgui_event_t*)&event_kbd);
+				kbd_event_set_key(&event_kbd, RTGUIK_HOME);
+				rtgui_edit_onkey(object, (rtgui_event_t*)&event_kbd);
+			}
+		}
+	}
+	else if(ekbd->key == RTGUIK_HOME)
+	{	/* move cursor to line head */
+		edit->visual.x = 0;
+		if(edit->upleft.x > 0)
+		{
+			edit->upleft.x = 0;
+			update_type = EDIT_ONDRAW;
+		}
+	}
+	else if(ekbd->key == RTGUIK_END)
+	{	/* move cursor to line tail */
+		if(line->len >= edit->col_per_page)
+		{
+			edit->visual.x = edit->col_per_page - 1;
+			edit->upleft.x = line->len - (edit->col_per_page-1);
+			update_type = EDIT_ONDRAW;
+		}
+		else
+			edit->visual.x = line->len;
+	}
+	else if(ekbd->key == RTGUIK_TAB)
+	{
+		int space_nums;
+		struct rtgui_event_kbd event_kbd;
+		/* using spaces to replace TAB */
+		space_nums = edit->tabsize - (edit->upleft.x+edit->visual.x) % edit->tabsize;
+		while(space_nums--)
+		{
+			kbd_event_set_key(&event_kbd, RTGUIK_SPACE);
+			rtgui_edit_onkey(object, (rtgui_event_t*)&event_kbd);
+		}
+	}
+	else if(ekbd->key == RTGUIK_RETURN)
+	{
+		struct edit_line *update_end_line;
+		struct rtgui_event_kbd event_kbd;
+		
+		update_type = EDIT_UPDATE;
+		edit->update.start = edit->visual;
+	
+		/* insert a new line buffer */
+		rtgui_edit_insert_line(edit, line, line->text + edit->upleft.x + edit->visual.x);
+		line->text[edit->upleft.x + edit->visual.x] = '\0';
+		line->len = rtgui_edit_line_strlen(line->text);
+		
+		/* adjust update line end position */
+		if((edit->max_rows-edit->upleft.y) >= edit->row_per_page)
+		{	
+			update_end_line = rtgui_edit_get_line_by_index(edit, edit->upleft.y+edit->row_per_page-1);
+			if(update_end_line != RT_NULL)
+			{
+				edit->update.end.x = update_end_line->len;
+				edit->update.end.y = edit->upleft.y + edit->row_per_page;
+			}
+		}
+		else
+		{
+			int update_end_index = rtgui_edit_get_index_by_line(edit, edit->tail);
+			edit->update.end.x = edit->tail->len;
+			edit->update.end.y = update_end_index;
+		}
+		
+		/* move the caret to the next line head */
+		kbd_event_set_key(&event_kbd, RTGUIK_DOWN);
+		rtgui_edit_onkey(object, (rtgui_event_t*)&event_kbd);
+		kbd_event_set_key(&event_kbd, RTGUIK_HOME);
+		rtgui_edit_onkey(object, (rtgui_event_t*)&event_kbd);
+	}
+	else
+	{
+		if(isprint(ekbd->key))
+		{	/* it's may print character */
+			update_type = EDIT_UPDATE;
+			edit->update.start = edit->visual;
+			
+			if(edit->flag & RTGUI_EDIT_SHIFT)
+				ekbd->key = query_shift_code(ekbd->key);
+			if(edit->flag & RTGUI_EDIT_CAPSLOCK)
+				ekbd->key = query_caps_code(ekbd->key);
+
+			if(line->len < line->zsize-1)
+			{
+				int ofs = edit->upleft.x + edit->visual.x;
+				if(edit->visual.x >= edit->col_per_page-1)
+				{
+					edit->upleft.x ++;
+					update_type = EDIT_ONDRAW;
+				}
+
+				if(ofs < line->len)
+				{
+					char* c;
+					for(c = &line->text[line->len]; c != &line->text[ofs]; c--)
+						*c = *(c-1);
+				}
+				line->text[ofs] = ekbd->key;
+				if(edit->visual.x < edit->col_per_page-1)
+					edit->visual.x ++;
+				line->text[line->len+1] = '\0';
+				line->len = rtgui_edit_line_strlen(line->text);
+				edit->update.end.x = line->len;
+				if(edit->update.end.x > edit->col_per_page)
+					edit->update.end.x = edit->col_per_page;
+				edit->update.end.y = edit->visual.y;
+			}
+			else
+			{	/* adjust line buffer's zone size */
+				line->zsize = rtgui_edit_alloc_len(edit->bzsize, line->len+1);
+				line->text = rt_realloc(line->text, line->zsize);
+				rtgui_edit_onkey(object, event); /* reentry */
+			}
+		}
+		else
+		{
+			/* Is small keyboard ? */
+			if(edit->flag & RTGUI_EDIT_NUMLOCK)
+			{
+				if(is_small_keyboard(&ekbd->key))
+					rtgui_edit_onkey(object, event);
+				/* small keyboard another value reserved */
+			}
+		}
+	}
+	line->len = rtgui_edit_line_strlen(line->text); 
+
+_edit_exit:
+	if(edit->flag & RTGUI_EDIT_CARET)
+	{
+		if(edit->caret_timer != RT_NULL)
+			rtgui_timer_stop(edit->caret_timer);
+
+		edit->flag &= ~RTGUI_EDIT_CARET;
+		rtgui_edit_draw_caret(edit);/* refresh it */
+		if(edit->caret_timer != RT_NULL)
+			rtgui_timer_start(edit->caret_timer);
+	}
+
+	/* re-draw edit widget */
+	if(update_type == EDIT_ONDRAW)
+		rtgui_edit_ondraw(edit);
+	else if(update_type == EDIT_UPDATE)
+		rtgui_edit_update(edit);
+
+	if(RTGUI_WIDGET_IS_FOCUSED(edit))
+	{
+		rtgui_edit_init_caret(edit, edit->visual);
+		edit->flag |= RTGUI_EDIT_CARET;
+		rtgui_edit_draw_caret(edit);
+	}
+	return RT_TRUE;
+}
+
+static rt_bool_t rtgui_edit_onfocus(struct rtgui_object* object, rtgui_event_t* event)
+{
+	struct rtgui_edit* edit = RTGUI_EDIT(object);
+
+	edit->caret_timer = rtgui_timer_create(50, RT_TIMER_FLAG_PERIODIC,
+											rtgui_edit_timeout, (void*)edit);
+	/* set caret to show */
+	edit->flag |= RTGUI_EDIT_CARET;
+	/* start caret timer */
+	if(edit->caret_timer != RT_NULL)
+		rtgui_timer_start(edit->caret_timer);
+
+	return RT_TRUE;
+}
+
+static rt_bool_t rtgui_edit_onunfocus(struct rtgui_object* object, rtgui_event_t* event)
+{
+	struct rtgui_edit* edit = RTGUI_EDIT(object);
+
+	/* stop caret timer */
+	if(edit->caret_timer != RT_NULL)
+	{
+		rtgui_timer_stop(edit->caret_timer);
+		rtgui_timer_destory(edit->caret_timer);
+	}
+	/* set caret to hide */
+	edit->flag &= ~RTGUI_EDIT_CARET;
+	rtgui_edit_draw_caret(edit);
+	
+	return RT_TRUE;
+}
+
+#ifdef RTGUI_EDIT_USING_SCROLL
+static rt_bool_t rtgui_edit_hscroll_handle(struct rtgui_widget* widget, rtgui_event_t* event)
+{
+	struct rtgui_edit *edit = RTGUI_EDIT(widget);
+
+	/* adjust first display row when dragging */
+	edit->upleft.y = edit->hscroll->value;
+
+	rtgui_edit_ondraw(edit);
+
+	return RT_TRUE;
+}
+
+static rt_bool_t rtgui_edit_vscroll_handle(struct rtgui_widget* widget, rtgui_event_t* event)
+{
+	struct rtgui_edit *edit = RTGUI_EDIT(widget);
+
+	/* adjust first display row when dragging */
+	edit->upleft.x = edit->vscroll->value;
+
+	rtgui_edit_ondraw(edit);
+
+	return RT_TRUE;
+}
+#endif
+
+/* local area update */
+void rtgui_edit_update(struct rtgui_edit *edit)
+{
+	rt_uint32_t i,cpy_len=0,prev_len;
+	rtgui_rect_t rect, r;
+	struct rtgui_dc *dc;
+	char *src;
+	
+	RT_ASSERT(edit != RT_NULL);
+	
+	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(edit));
+	if(dc == RT_NULL) return;
+	
+	rtgui_widget_get_rect(RTGUI_WIDGET(edit), &rect);
+	rtgui_rect_inflate(&rect, -(edit->margin + RTGUI_WIDGET_BORDER(edit)));
+
+	if(edit->update_buf == RT_NULL) 
+	{   /* try again allocate */
+		edit->update_buf = rtgui_malloc(edit->col_per_page+1);
+	}
+	
+	prev_len = edit->col_per_page;
+	for(i=edit->update.start.y; i<=edit->update.end.y; i++)
+	{
+		struct edit_line *line = rtgui_edit_get_line_by_index(edit, edit->upleft.y + i);
+
+		if(i > edit->upleft.y+edit->row_per_page) break;
+		if(line == RT_NULL) 
+		{	/* when use "RTGUIK_BACKSPACE" backspace forward,
+			 * the last line is blank, that only fill background. */
+			r.x1 = rect.x1;
+			r.x2 = rect.x1 + prev_len * edit->font_width;
+			r.y1 = rect.y1 + i * edit->font_height;
+			r.y2 = r.y1 + edit->font_height;
+			if(r.x2 > rect.x2) r.x2 = rect.x2;
+			if(r.y2 > rect.y2) r.y2 = rect.y2;
+			rtgui_dc_fill_rect(dc, &r);
+			break;
+		}
+		
+		if(edit->update.start.y == edit->update.end.y)
+		{
+			r.x1 = rect.x1 + edit->update.start.x * edit->font_width;
+			r.x2 = rect.x1 + edit->update.end.x * edit->font_width;
+			r.y1 = rect.y1 + i * edit->font_height;
+			r.y2 = r.y1 + edit->font_height;
+			cpy_len = edit->update.end.x - edit->update.start.x;
+			src = line->text + edit->update.start.x + edit->upleft.x;
+		}
+		else 
+		{
+			if(i == edit->update.start.y)
+			{
+				r.x1 = rect.x1 + edit->update.start.x * edit->font_width;
+				r.x2 = rect.x2;
+				r.y1 = rect.y1 + i * edit->font_height;
+				r.y2 = r.y1 + edit->font_height;
+				cpy_len = line->len - edit->update.start.x - edit->upleft.x;
+				if(cpy_len > (edit->col_per_page-edit->update.start.x))
+					cpy_len = edit->col_per_page-edit->update.start.x;
+				src = line->text + edit->update.start.x + edit->upleft.x;
+			}
+			else if(i == edit->update.end.y)
+			{
+				r.x1 = rect.x1;
+				r.x2 = rect.x1 + edit->update.end.x * edit->font_width;
+				cpy_len = edit->update.end.x;
+				r.y1 = rect.y1 + i * edit->font_height;
+				r.y2 = r.y1 + edit->font_height;
+				src = line->text + edit->upleft.x;
+			}
+			else
+			{
+				r.x1 = rect.x1;
+				r.x2 = rect.x2;
+				r.y1 = rect.y1 + i * edit->font_height;
+				r.y2 = r.y1 + edit->font_height;
+				cpy_len = line->len - edit->upleft.x;
+				if(cpy_len > edit->col_per_page)
+					cpy_len = edit->col_per_page;
+				src = line->text + edit->upleft.x;
+			}
+		} 
+		if(r.y1 > rect.y2) break;
+		if(r.x2 > rect.x2) r.x2 = rect.x2;
+		if(r.y2 > rect.y2) r.y2 = rect.y2;
+		
+		rt_memcpy(edit->update_buf, src, cpy_len);
+		*(edit->update_buf + cpy_len) = '\0';
+		
+		rtgui_dc_fill_rect(dc, &r);
+		rtgui_dc_draw_text(dc, edit->update_buf, &r);
+		prev_len = line->len;
+	}
+	
+	rtgui_dc_end_drawing(dc);
+}
+
+void rtgui_edit_ondraw(struct rtgui_edit *edit)
+{
+	rtgui_rect_t rect, r;
+	struct rtgui_dc *dc;
+	int hscroll_flag=0;
+	int vscroll_flag=0;
+
+	RT_ASSERT(edit != RT_NULL);
+
+	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(edit));
+	if(dc == RT_NULL) return;
+
+	/* get widget rect */
+	rtgui_widget_get_rect(RTGUI_WIDGET(edit), &rect);
+	rtgui_rect_inflate(&rect, -RTGUI_WIDGET_BORDER(edit));
+
+	/* fill widget rect with edit background color */
+	RTGUI_DC_BC(dc) = RTGUI_WIDGET_BACKGROUND(edit);
+	rtgui_dc_fill_rect(dc, &rect);
+
+	rtgui_rect_inflate(&rect, RTGUI_WIDGET_BORDER(edit));
+	/* draw border */
+	rtgui_dc_draw_border(dc, &rect, RTGUI_WIDGET_BORDER_STYLE(edit));
+
+	rtgui_rect_inflate(&rect, -(edit->margin + RTGUI_WIDGET_BORDER(edit)));
+
+#ifdef RTGUI_EDIT_USING_SCROLL
+	if(edit->vscroll && !RTGUI_WIDGET_IS_HIDE(edit->vscroll))
+	{
+		rect.x2 = rect.x2 - rtgui_rect_width(edit->vscroll->parent.extent);
+	}
+	if(edit->hscroll && !RTGUI_WIDGET_IS_HIDE(edit->hscroll))
+	{
+		rect.y2 = rect.y2 - rtgui_rect_height(edit->hscroll->parent.extent);
+	}
+#endif
+	r = rect;
+	
+	/* draw text */
+	if(edit->head != RT_NULL)
+	{
+		struct edit_line *line = edit->first_line;
+		int num=0;
+		
+		rect.y2 = rect.y1 + edit->item_height;
+		while(line)
+		{
+			if(edit->upleft.x < line->len)
+				rtgui_dc_draw_text(dc, line->text+edit->upleft.x, &rect);
+			line = line->next;
+			rect.y1 += edit->item_height;
+			if((rect.y1 + edit->item_height) < r.y2)
+				rect.y2 = rect.y1 + edit->item_height;
+			else
+				rect.y2 = r.y2;
+			
+			if(num++ >= edit->row_per_page)
+				break;
+		}
+	}
+
+#ifdef RTGUI_EDIT_USING_SCROLL
+	if(edit->hscroll && !RTGUI_WIDGET_IS_HIDE(edit->hscroll))
+	{
+		hscroll_flag = 1;
+		rtgui_scrollbar_ondraw(edit->hscroll);
+	}
+	if(edit->vscroll && !RTGUI_WIDGET_IS_HIDE(edit->vscroll))
+	{
+		vscroll_flag = 1;
+		rtgui_scrollbar_ondraw(edit->vscroll);
+	}
+
+	if(hscroll_flag && vscroll_flag)
+	{
+		rtgui_color_t _bc;
+		rtgui_widget_get_rect(RTGUI_WIDGET(edit), &rect);
+		rect.x1 = rect.x2-RTGUI_WIDGET_BORDER(edit);
+		rect.y1 = rect.y2-RTGUI_WIDGET_BORDER(edit);
+		_bc = RTGUI_DC_BC(dc);
+		RTGUI_DC_BC(dc) = default_background;
+		rtgui_dc_fill_rect(dc,&rect);
+		RTGUI_DC_BC(dc) = _bc;
+	}
+#endif
+	rtgui_dc_end_drawing(dc);
+}
+
+/* set edit text */
+void rtgui_edit_set_text(struct rtgui_edit* edit, const char* text)
+{
+	const char *begin, *ptr;
+	int hscroll_flag=0;
+	int vscroll_flag=0;
+
+	RT_ASSERT(edit != RT_NULL);
+
+	while(edit->max_rows > 0)
+		rtgui_edit_delete_line(edit, edit->head);
+	edit->max_rows = 0;
+
+	begin = text;
+	for(ptr=begin; *ptr != '\0'; ptr++)
+	{
+		if(*ptr == 0x0A)
+		{	/* unix style */
+			rtgui_edit_append_line(edit, begin);
+			begin = ptr+1;
+		}
+		else if(*ptr == 0x0D && *(ptr+1) == 0x0A)
+		{	/* windows style */
+			rtgui_edit_append_line(edit, begin);
+			begin = ptr+2;
+		}
+	}
+	if(*ptr == '\0')
+	{
+		if(begin < ptr)
+			rtgui_edit_append_line(edit, begin);
+	}
+	edit->first_line = edit->head;
+	
+#ifdef RTGUI_EDIT_USING_SCROLL
+	if(edit->hscroll != RT_NULL)
+	{
+		if(edit->max_cols > edit->col_per_page)
+		{
+			RTGUI_WIDGET_SHOW(edit->hscroll);
+			rtgui_scrollbar_set_line_step(edit->hscroll, 1);
+			rtgui_scrollbar_set_page_step(edit->hscroll, edit->col_per_page);
+			rtgui_scrollbar_set_range(edit->hscroll, edit->max_cols);
+			hscroll_flag = 1;
+		}
+		else
+		{
+			RTGUI_WIDGET_HIDE(edit->hscroll);
+		}
+	}
+	if(edit->vscroll != RT_NULL)
+	{
+		if(edit->max_rows > edit->row_per_page)
+		{
+			RTGUI_WIDGET_SHOW(edit->vscroll);
+			rtgui_scrollbar_set_line_step(edit->vscroll, 1);
+			rtgui_scrollbar_set_page_step(edit->vscroll, edit->row_per_page);
+			rtgui_scrollbar_set_range(edit->vscroll, edit->max_rows);
+			vscroll_flag = 1;
+		}
+		else
+		{
+			RTGUI_WIDGET_HIDE(edit->vscroll);
+		}
+	}
+
+	if(edit->hscroll != RT_NULL && !RTGUI_WIDGET_IS_HIDE(edit->hscroll))
+	{
+		rtgui_edit_adjust_scroll(edit->hscroll);
+	}
+	if(edit->vscroll != RT_NULL && !RTGUI_WIDGET_IS_HIDE(edit->vscroll))
+	{
+		rtgui_edit_adjust_scroll(edit->vscroll);
+	}
+#endif
+	if(hscroll_flag || vscroll_flag)
+	{
+		rtgui_widget_update_clip(RTGUI_WIDGET(edit));
+	}
+}
+
+rt_bool_t rtgui_edit_event_handler(struct rtgui_object* object, rtgui_event_t* event)
+{
+	rtgui_widget_t *widget = RTGUI_WIDGET(object);
+	struct rtgui_edit* edit = RTGUI_EDIT(object);
+
+	switch(event->type)
+	{
+	case RTGUI_EVENT_PAINT:
+#ifndef RTGUI_USING_SMALL_SIZE
+		if(widget->on_draw != RT_NULL)
+			widget->on_draw(object, event);
+		else
+#endif
+			rtgui_edit_ondraw(edit);
+		break;
+
+	case RTGUI_EVENT_MOUSE_BUTTON:
+#ifndef RTGUI_USING_SMALL_SIZE
+		if(widget->on_mouseclick != RT_NULL)
+			widget->on_mouseclick(object, event);
+		else
+#endif
+			rtgui_edit_onmouse(edit, (struct rtgui_event_mouse*)event);
+		return RT_TRUE;
+
+	case RTGUI_EVENT_KBD:
+#ifndef RTGUI_USING_SMALL_SIZE
+		if(widget->on_key != RT_NULL)
+			widget->on_key(object, event);
+		else
+#endif
+		rtgui_edit_onkey(object, event);
+		return RT_TRUE;
+
+	default:
+		return rtgui_widget_event_handler(object, event);
+	}
+
+	return RT_FALSE;
+}
+
+/** 
+ * File access component, General File Access Interface
+ */
+
+rt_bool_t rtgui_edit_readin_file(struct rtgui_edit *edit, const char *filename)
+{
+	int fd, num=0, read_bytes, size ,len=0;
+	char *text ,ch;
+
+	fd = open(filename, O_RDONLY, 0);
+	if (fd < 0)
+	{
+		return RT_FALSE;
+	}
+	
+	while(edit->max_rows > 0)
+		rtgui_edit_delete_line(edit, edit->head);
+	edit->max_rows = 0;
+
+	size = edit->bzsize;
+	text = rtgui_malloc(size);
+	if(text == RT_NULL) return RT_FALSE;
+	
+	do {
+		if ( (read_bytes = read(fd, &ch, 1)) > 0 )
+		{
+			if(num >= size - 1)
+				text = rt_realloc(text, rtgui_edit_alloc_len(size, num));
+			if(ch == 0x09) //Tab
+			{
+				len = edit->tabsize - num%edit->tabsize;
+				while(len--)
+					*(text + num++) = ' ';
+			}
+			else
+				*(text + num++) = ch;
+			if(ch == 0x0A)
+			{
+				rtgui_edit_append_line(edit, text);
+				num = 0;
+			}
+			
+		}
+	} while(read_bytes);
+	
+	close(fd);
+	rtgui_free(text);
+	rtgui_edit_ondraw(edit);
+
+	return RT_TRUE;
+}
+
+rt_bool_t rtgui_edit_saveas_file(struct rtgui_edit *edit, const char *filename)
+{
+	int fd;
+	char ch_tailed = 0x0A;
+	struct edit_line *line;
+
+	fd = open(filename, O_WRONLY | O_CREAT, 0);
+	if (fd < 0)
+	{
+		return RT_FALSE;
+	}
+	
+	line = edit->head;
+	while(line)
+	{
+		write(fd, line->text, line->len);
+		if(line != edit->tail)
+			write(fd, &ch_tailed, 1);
+		line = line->next;
+	}
+	
+	close(fd);
+
+	return RT_TRUE;
+}

+ 13 - 5
components/rtgui/widgets/filelist_view.c

@@ -260,7 +260,7 @@ static rt_bool_t rtgui_filelist_view_on_folder_item(rtgui_object_t* object, stru
 			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);
+			rtgui_free(dir_ptr);
 		}
 		break;
 	case 1:
@@ -332,8 +332,8 @@ static void _rtgui_filelist_view_constructor(struct rtgui_filelist_view *view)
 
 	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;
+	RTGUI_WIDGET_BACKGROUND(view) = white;
+	RTGUI_WIDGET_TEXTALIGN(view) = RTGUI_ALIGN_CENTER_VERTICAL;
 
 	file_image = rtgui_image_create_from_mem("xpm",
 		(rt_uint8_t*)file_xpm, sizeof(file_xpm), RT_TRUE);
@@ -346,8 +346,16 @@ 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;
+	if (view->current_directory != RT_NULL)
+	{
+		rt_free(view->current_directory); 
+		view->current_directory = RT_NULL;
+	}
+	if (view->pattern != RT_NULL) 
+	{
+		rt_free(view->pattern); 
+		view->pattern = RT_NULL;
+	}
 
 	/* delete image */
 	rtgui_image_destroy(file_image);

+ 155 - 0
components/rtgui/widgets/groupbox.c

@@ -0,0 +1,155 @@
+/*
+ * File      : groupbox.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2012, 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
+ * 2012-07-29     Bernard      first version
+ */
+#include <rtgui/dc.h>
+#include <rtgui/rtgui_system.h>
+#include <rtgui/rtgui_theme.h>
+#include <rtgui/widgets/groupbox.h>
+
+static void _rtgui_groupbox_constructor(rtgui_groupbox_t *box)
+{
+	/* init widget and set event handler */
+	rtgui_object_set_event_handler(RTGUI_OBJECT(box), rtgui_groupbox_event_handler);
+
+	/* set field */
+	box->box = RT_NULL;
+	box->label = RT_NULL;
+	box->selected = RT_NULL;
+
+	box->on_selected = RT_NULL;
+}
+
+DEFINE_CLASS_TYPE(groupbox, "groupbox", 
+	RTGUI_PANEL_TYPE,
+	_rtgui_groupbox_constructor,
+	RT_NULL,
+	sizeof(struct rtgui_groupbox));
+
+rt_bool_t rtgui_groupbox_event_handler(struct rtgui_object *object, struct rtgui_event* event)
+{
+	struct rtgui_groupbox* box;
+
+	box = RTGUI_GROUPBOX(object);
+	switch (event->type)
+	{
+	case RTGUI_EVENT_PAINT:
+		{
+			rtgui_panel_event_handler(RTGUI_OBJECT(box), event);
+
+			/* dispatch paint event to child */
+			rtgui_container_dispatch_event(RTGUI_CONTAINER(box), event);
+		}
+		break;
+	default:
+		return rtgui_container_event_handler(object, event);
+	}
+
+	return RT_FALSE;
+}
+
+rtgui_groupbox_t* rtgui_groupbox_create(const char* label, struct rtgui_rect *rect, 
+										int style, widget_select_t select_func)
+{
+    struct rtgui_groupbox *box;
+
+	RT_ASSERT(select_func != RT_NULL);
+
+    box = (struct rtgui_groupbox*) rtgui_widget_create(RTGUI_GROUPBOX_TYPE);
+    if (box != RT_NULL)
+    {
+		rtgui_widget_set_rect(RTGUI_WIDGET(box), rect);
+
+		if (label != RT_NULL)
+		{
+			box->label = rt_strdup(label);
+		}
+
+		/* create layout box */
+		box->box = rtgui_box_create(style, RTGUI_WIDGET_DEFAULT_MARGIN + 1);
+		rtgui_container_set_box(RTGUI_CONTAINER(box), box->box);
+
+		rtgui_panel_set_border(RTGUI_PANEL(box), RTGUI_BORDER_NONE);
+
+		box->select_func = select_func;
+    }
+
+    return box;
+}
+
+void rtgui_groupbox_destroy(rtgui_groupbox_t* groupbox)
+{
+	rtgui_object_destroy(RTGUI_OBJECT(groupbox));
+}
+
+void rtgui_groupbox_select_widget(struct rtgui_groupbox *box, struct rtgui_widget *widget)
+{
+	struct rtgui_event event;
+
+	RT_ASSERT(box != RT_NULL);
+	RT_ASSERT(widget != RT_NULL);
+
+	if (box->selected != widget)
+	{
+		if (box->selected != RT_NULL)
+		{
+			box->select_func(box->selected, RT_FALSE);
+			if (box->on_selected != RT_NULL)
+			{
+				RTGUI_EVENT_INIT(&event, RTGUI_EVENT_UNSELECTED);
+				box->on_selected(RTGUI_OBJECT(widget), &event);
+			}
+			rtgui_widget_update(widget);
+		}
+		box->selected = widget;
+	}
+
+	box->select_func(box->selected, RT_TRUE);
+
+	if (box->on_selected != RT_NULL)
+	{
+		RTGUI_EVENT_INIT(&event, RTGUI_EVENT_SELECTED);
+		box->on_selected(RTGUI_OBJECT(widget), &event);
+	}
+}
+
+struct rtgui_widget *rtgui_groupbox_get_selected(struct rtgui_groupbox *box)
+{
+	RT_ASSERT(box != RT_NULL);
+
+	return box->selected;
+}
+
+void rtgui_groupbox_add_widget(struct rtgui_groupbox *box, struct rtgui_widget *widget)
+{
+	widget->user_data = (rt_uint32_t)box;
+	rtgui_container_add_child(RTGUI_CONTAINER(box), widget);
+	RTGUI_WIDGET_ALIGN(widget) = RTGUI_ALIGN_CENTER;
+	RTGUI_WIDGET_BACKGROUND(widget) = RTGUI_WIDGET_BACKGROUND(box);
+}
+
+void rtgui_groupbox_layout(struct rtgui_groupbox *box)
+{
+	if (RTGUI_PANEL(box)->border_style != RTGUI_BORDER_NONE)
+	{
+		rtgui_box_layout(box->box);
+	}
+	else
+	{
+		struct rtgui_rect extent;
+
+		RT_ASSERT(box != RT_NULL);
+		rtgui_widget_get_extent(RTGUI_WIDGET(box), &extent);
+		rtgui_rect_inflate(&extent, -RTGUI_WIDGET_DEFAULT_MARGIN);
+		rtgui_box_layout_rect(box->box, &extent);
+	}
+}

+ 33 - 16
components/rtgui/widgets/iconbox.c

@@ -18,7 +18,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(iconbox)->flag |= (RTGUI_WIDGET_FLAG_TRANSPARENT | RTGUI_WIDGET_FLAG_FOCUSABLE);
 	rtgui_object_set_event_handler(RTGUI_OBJECT(iconbox), rtgui_iconbox_event_handler);
 
 	/* set proper of control */
@@ -36,8 +36,11 @@ static void _rtgui_iconbox_destructor(rtgui_iconbox_t *iconbox)
 		iconbox->image = RT_NULL;
 	}
 
-	rt_free(iconbox->text);
-	iconbox->text = RT_NULL;
+	if (iconbox->text != RT_NULL)
+	{
+		rt_free(iconbox->text);
+		iconbox->text = RT_NULL;
+	}
 }
 
 DEFINE_CLASS_TYPE(iconbox, "iconbox", 
@@ -49,23 +52,35 @@ DEFINE_CLASS_TYPE(iconbox, "iconbox",
 rt_bool_t rtgui_iconbox_event_handler(struct rtgui_object* object, struct rtgui_event* event)
 {
 	struct rtgui_iconbox* iconbox;
-	RTGUI_WIDGET_EVENT_HANDLER_PREPARE
 
 	iconbox = RTGUI_ICONBOX(object);
 
 	switch (event->type)
 	{
 	case RTGUI_EVENT_PAINT:
-#ifndef RTGUI_USING_SMALL_SIZE
-		if (widget->on_draw != RT_NULL)
-			widget->on_draw(RTGUI_OBJECT(widget), event);
-		else
-#endif
+		rtgui_theme_draw_iconbox(iconbox);
+		break;
+
+	case RTGUI_EVENT_MOUSE_BUTTON:
+		if (RTGUI_WIDGET_IS_HIDE(object)) return RT_FALSE;
+
 		{
-			rtgui_theme_draw_iconbox(iconbox);
+			struct rtgui_event_mouse* emouse = (struct rtgui_event_mouse*)event;
+
+			/* it's not this widget event, clean status */
+			if (rtgui_rect_contains_point(&(RTGUI_WIDGET(iconbox)->extent), 
+				emouse->x, emouse->y) != RT_EOK)
+			{
+				if (iconbox->selected != RT_TRUE)
+				{
+					rtgui_iconbox_set_selected(iconbox, RT_TRUE);
+					rtgui_widget_focus(RTGUI_WIDGET(iconbox));
+				}
+				break;
+			}
 		}
+		return RT_TRUE;
 
-		break;
 	default:
 		return rtgui_widget_event_handler(object, event);
 	}
@@ -127,7 +142,7 @@ void rtgui_iconbox_destroy(struct rtgui_iconbox* iconbox)
 
 void rtgui_iconbox_set_text_position(struct rtgui_iconbox* iconbox, int position)
 {
-	rtgui_rect_t rect = {0, 0, 0, 0}, text_rect;
+	struct rtgui_rect rect = {0, 0, 0, 0}, text_rect;
 
 	RT_ASSERT(iconbox != RT_NULL);
 
@@ -161,9 +176,11 @@ void rtgui_iconbox_set_text_position(struct rtgui_iconbox* iconbox, int position
 			rect.x2 += text_rect.x2;
 		}
 	}
+}
+
+void rtgui_iconbox_set_selected(struct rtgui_iconbox* iconbox, rt_bool_t selected)
+{
+	RT_ASSERT(iconbox != RT_NULL);
 
-#ifndef RTGUI_USING_SMALL_SIZE
-	rtgui_widget_set_miniwidth(RTGUI_WIDGET(iconbox), rect.x2);
-	rtgui_widget_set_miniheight(RTGUI_WIDGET(iconbox), rect.y2);
-#endif
+	iconbox->selected = selected;
 }

+ 3 - 2
components/rtgui/widgets/label.c

@@ -28,7 +28,8 @@ static void _rtgui_label_constructor(rtgui_label_t *label)
 static void _rtgui_label_destructor(rtgui_label_t *label)
 {
 	/* release text memory */
-	rt_free(label->text);
+	if (label->text)
+		rt_free(label->text);
 	label->text = RT_NULL;
 }
 
@@ -100,7 +101,7 @@ void rtgui_label_set_text(rtgui_label_t* label, const char* text)
 		if (rt_strncmp(text, label->text, rt_strlen(text)) == 0) return;
 		
 		/* release old text memory */
-		rt_free(label->text);
+		rtgui_free(label->text);
 	}
 
 	if (text != RT_NULL) label->text = (char*)rt_strdup((const char*)text);

+ 6 - 6
components/rtgui/widgets/list_view.c

@@ -33,8 +33,8 @@ static void _rtgui_list_view_constructor(struct rtgui_list_view *view)
 	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;
+	RTGUI_WIDGET_BACKGROUND(view) = white;
+	RTGUI_WIDGET_TEXTALIGN(view) = RTGUI_ALIGN_CENTER_VERTICAL;
 }
 
 DEFINE_CLASS_TYPE(listview, "listview", 
@@ -84,7 +84,7 @@ static void rtgui_list_view_onicondraw(struct rtgui_list_view* view, struct rtgu
 
 				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, 
+				rtgui_font_get_metrics(RTGUI_WIDGET_FONT(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);
@@ -144,7 +144,7 @@ static void rtgui_list_view_update_icon(struct rtgui_list_view* view, rt_int16_t
 	/* 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, 
+	rtgui_font_get_metrics(RTGUI_WIDGET_FONT(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);
@@ -170,7 +170,7 @@ static void rtgui_list_view_update_icon(struct rtgui_list_view* view, rt_int16_t
 	/* 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)), 
+	rtgui_font_get_metrics(RTGUI_WIDGET_FONT(view), 
 		view->items[view->current_item].name, 
 		&drawing_rect);
 	rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL);
@@ -586,7 +586,7 @@ static void rtgui_list_view_calc(struct rtgui_list_view* view)
 		image_height = 0;
 	}
 
-	rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), "HHHHHH", &rect);
+	rtgui_font_get_metrics(RTGUI_WIDGET_FONT(view), "HHHHHH", &rect);
 
 	text_height = rtgui_rect_height(rect);
 	text_width = rtgui_rect_width(rect);

+ 4 - 4
components/rtgui/widgets/listbox.c

@@ -29,8 +29,8 @@ static void _rtgui_listbox_constructor(struct rtgui_listbox *box)
 	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;
+	RTGUI_WIDGET_BACKGROUND(box) = white;
+	RTGUI_WIDGET_TEXTALIGN(box) = RTGUI_ALIGN_CENTER_VERTICAL;
 }
 
 DEFINE_CLASS_TYPE(listbox, "listbox", 
@@ -54,7 +54,7 @@ void rtgui_listbox_ondraw(struct rtgui_listbox* box)
 
 	rect.x2 -= 1; rect.y2 -= 1;
 	/* draw focused border */
-	if (RTGUI_WIDGET_IS_FOCUSED(RTGUI_WIDGET(box)))
+	if (RTGUI_WIDGET_IS_FOCUSED(box))
 		rtgui_dc_draw_focus_rect(dc, &rect);
 
 	/* get item base rect */
@@ -227,7 +227,7 @@ rt_bool_t rtgui_listbox_event_handler(struct rtgui_object* object, struct rtgui_
 						/* update focus border */
 						rect.x2 -= 1; rect.y2 -= 1;
 						/* draw focused border */
-						if (RTGUI_WIDGET_IS_FOCUSED(RTGUI_WIDGET(box)))
+						if (RTGUI_WIDGET_IS_FOCUSED(box))
 							rtgui_dc_draw_focus_rect(dc, &rect);
 						rtgui_dc_end_drawing(dc);
 					}

+ 30 - 18
components/rtgui/widgets/listctrl.c

@@ -25,13 +25,14 @@ static void _rtgui_listctrl_constructor(struct rtgui_listctrl *ctrl)
 	RTGUI_WIDGET(ctrl)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
 
 	ctrl->current_item = -1;
+	ctrl->item_height = rtgui_theme_get_selected_height();
 	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;
+	RTGUI_WIDGET_BACKGROUND(ctrl) = white;
+	RTGUI_WIDGET_TEXTALIGN(ctrl) = RTGUI_ALIGN_CENTER_VERTICAL;
 }
 
 DEFINE_CLASS_TYPE(listctrl, "listctrl",
@@ -43,7 +44,7 @@ DEFINE_CLASS_TYPE(listctrl, "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())
+	if (ctrl->items_count > rtgui_rect_height(*rect)/ctrl->item_height)
 	{
 		rect->x2 = rect->x2 - 8;
 	}
@@ -52,7 +53,7 @@ static void _rtgui_listctrl_get_rect(struct rtgui_listctrl* ctrl, rtgui_rect_t*
 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())
+	if (ctrl->items_count > rtgui_rect_height(*rect)/ctrl->item_height)
 	{
 		rect->x1 = rect->x2 - 8;
 	}
@@ -70,10 +71,11 @@ static void _rtgui_listctrl_scrollbar_ondraw(struct rtgui_listctrl* ctrl, struct
 
 	/* get scrollbar rect */
 	_rtgui_listctrl_get_scrollbar_rect(ctrl, &rect);
+	if (rtgui_rect_is_empty(&rect) == RT_TRUE) return;
+
 	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;
 
@@ -132,7 +134,7 @@ static void _rtgui_listctrl_ondraw(struct rtgui_listctrl* ctrl)
 	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());
+	item_rect.y2 = item_rect.y1 + (2 + ctrl->item_height);
 
 	/* get current page */
 	page_index = (ctrl->current_item / ctrl->page_items) * ctrl->page_items;
@@ -151,8 +153,8 @@ static void _rtgui_listctrl_ondraw(struct rtgui_listctrl* ctrl)
 		}
 
         /* move to next item position */
-		item_rect.y1 += (rtgui_theme_get_selected_height() + 2);
-		item_rect.y2 += (rtgui_theme_get_selected_height() + 2);
+		item_rect.y1 += (ctrl->item_height + 2);
+		item_rect.y2 += (ctrl->item_height + 2);
 	}
 
 	/* draw scrollbar */
@@ -182,8 +184,8 @@ void rtgui_listctrl_update_current(struct rtgui_listctrl* ctrl, rt_uint16_t old_
 	/* 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());
+	item_rect.y1 += (old_item % ctrl->page_items) * (2 + ctrl->item_height);
+	item_rect.y2 = item_rect.y1 + (2 + ctrl->item_height);
 
 	/* draw old item */
 	rtgui_dc_fill_rect(dc, &item_rect);
@@ -195,8 +197,8 @@ void rtgui_listctrl_update_current(struct rtgui_listctrl* ctrl, rt_uint16_t old_
 	/* 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());
+	item_rect.y1 += (ctrl->current_item % ctrl->page_items) * (2 + ctrl->item_height);
+	item_rect.y2 = item_rect.y1 + (2 + ctrl->item_height);
 
 	/* draw current item */
 	rtgui_theme_draw_selected(dc, &item_rect);
@@ -225,7 +227,7 @@ rt_bool_t rtgui_listctrl_event_handler(struct rtgui_object* object, struct rtgui
 			resize = (struct rtgui_event_resize*)event;
 
             /* recalculate page items */
-			ctrl->page_items = resize->h  / (2 + rtgui_theme_get_selected_height());
+			ctrl->page_items = resize->h  / (2 + ctrl->item_height);
         }
         break;
 
@@ -255,7 +257,7 @@ rt_bool_t rtgui_listctrl_event_handler(struct rtgui_object* object, struct rtgui
 					(ctrl->items_count > 0))
 			{
 				rt_uint16_t index;
-				index = (emouse->y - rect.y1) / (2 + rtgui_theme_get_selected_height());
+				index = (emouse->y - rect.y1) / (2 + ctrl->item_height);
 
 				/* set focus */
 				rtgui_widget_focus(widget);
@@ -372,7 +374,7 @@ rtgui_listctrl_t* rtgui_listctrl_create(rt_uint32_t items, rt_uint16_t count, rt
 	    ctrl->items_count = count;
 		ctrl->on_item_draw = ondraw;
 
-		ctrl->page_items = rtgui_rect_height(*rect) / (2 + rtgui_theme_get_selected_height());
+		ctrl->page_items = rtgui_rect_height(*rect) / (2 + ctrl->item_height);
 		rtgui_widget_set_rect(RTGUI_WIDGET(ctrl), rect);
 	}
 
@@ -401,7 +403,7 @@ void rtgui_listctrl_set_items(rtgui_listctrl_t* ctrl, rt_uint32_t items, rt_uint
 	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());
+	ctrl->page_items = rtgui_rect_height(rect) / (2 + ctrl->item_height);
 
 	rtgui_widget_update(RTGUI_WIDGET(ctrl));
 }
@@ -418,10 +420,20 @@ rt_bool_t rtgui_listctrl_get_item_rect(rtgui_listctrl_t* ctrl, rt_uint16_t item,
 
 		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());
+		item_rect->y1 += (item % ctrl->page_items) * (2 + ctrl->item_height);
+		item_rect->y2 = item_rect->y1 + (2 + ctrl->item_height);
 		return RT_TRUE;
 	}
 
 	return RT_FALSE;
 }
+
+void rtgui_listctrl_set_itemheight(struct rtgui_listctrl* ctrl, int height)
+{
+	RT_ASSERT(ctrl != RT_NULL);
+	if (height <= 0) return;
+
+	ctrl->item_height = height;
+	ctrl->page_items = rtgui_rect_height(RTGUI_WIDGET(ctrl)->extent) / (2 + ctrl->item_height);
+}
+

+ 6 - 6
components/rtgui/widgets/menu.c

@@ -58,7 +58,7 @@ static rt_bool_t _rtgui_menu_onitem(struct rtgui_object* object, struct rtgui_ev
 		{
 			if (menu->sub_menu->items == items)
 			{
-				if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(menu->sub_menu)))
+				if (!RTGUI_WIDGET_IS_HIDE(menu->sub_menu))
 				{
 					/* hide this sub menu */
 					rtgui_win_hiden(RTGUI_WIN(menu->sub_menu));
@@ -114,10 +114,10 @@ static void _rtgui_menu_item_ondraw(struct rtgui_listctrl *list,
 	{
 		rtgui_color_t bc;
 
-		bc = RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(list));
-		RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(list)) = blue;
+		bc = RTGUI_WIDGET_BACKGROUND(list);
+		RTGUI_WIDGET_BACKGROUND(list) = blue;
 		rtgui_dc_fill_rect(dc, rect);
-		RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(list)) = bc;
+		RTGUI_WIDGET_BACKGROUND(list) = bc;
 	}
 
 	/* get menu item */
@@ -178,7 +178,7 @@ static rt_bool_t rtgui_menu_on_deactivate(struct rtgui_object *object, rtgui_eve
 		 * 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)))
+			!RTGUI_WIDGET_IS_HIDE(menu->sub_menu))
 			return RT_TRUE;
 	}
 
@@ -219,7 +219,7 @@ struct rtgui_menu* rtgui_menu_create(const char* title, struct rtgui_menu* paren
 		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_WIDGET_BACKGROUND(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);
 	}

+ 239 - 27
components/rtgui/widgets/notebook.c

@@ -3,11 +3,18 @@
 #include <rtgui/rtgui_system.h>
 #include <rtgui/widgets/notebook.h>
 #include <rtgui/widgets/window.h>
+#include <rtgui/image.h>
 
-#define RTGUI_NOTEBOOK_TAB_WIDTH     80
+#define RTGUI_NOTEBOOK_TAB_DEFAULT_WIDTH  80
+#define RTGUI_NOTEBOOK_TAB_DEFAULT_HEIGHT 25
 
 struct rtgui_notebook_tab
 {
+#ifdef RTGUI_USING_NOTEBOOK_IMAGE
+	struct rtgui_image *pressed_image;
+	struct rtgui_image *unpressed_image;
+#endif
+
 	struct rtgui_widget *widget;
 	char *title;
 };
@@ -22,6 +29,9 @@ static void _rtgui_notebook_constructor(struct rtgui_notebook *notebook)
 	notebook->count   = 0;
 	notebook->current = 0;
 
+	notebook->tab_h = RTGUI_NOTEBOOK_TAB_DEFAULT_HEIGHT;
+	notebook->tab_w = RTGUI_NOTEBOOK_TAB_DEFAULT_WIDTH;
+
 	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);
 }
@@ -55,31 +65,137 @@ DEFINE_CLASS_TYPE(notebook, "notebook",
 static void _rtgui_notebook_draw_bar(struct rtgui_notebook *notebook,
 		struct rtgui_dc *dc)
 {
-	struct rtgui_rect rect;
 	int index;
+	struct rtgui_rect rect;
+	struct rtgui_rect text_rect;
+#ifdef RTGUI_USING_NOTEBOOK_IMAGE
+	struct rtgui_image* image = RT_NULL;
+	struct rtgui_rect image_rect;
+#endif
 
 	RT_ASSERT((notebook != RT_NULL) && (dc != RT_NULL));
 
-	if (notebook->flag & RTGUI_NOTEBOOK_NOTAB)
+	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->flag == RTGUI_NOTEBOOK_TOP ||
+		notebook->flag == RTGUI_NOTEBOOK_BOTTOM)
 	{
-		if (notebook->current == index)
-			rtgui_dc_draw_border(dc, &rect, RTGUI_BORDER_SUNKEN);
-		else
-			rtgui_dc_draw_border(dc, &rect, RTGUI_BORDER_BOX);
+		rect.x2 = rect.x1 + notebook->tab_w;
+		/* draw tab bar */
+		for (index = 0; index < notebook->count; index++)
+		{
+			if (notebook->current == index)
+			{
+#ifdef RTGUI_USING_NOTEBOOK_IMAGE
+				if (notebook->childs[index].pressed_image != RT_NULL)
+					image = notebook->childs[index].pressed_image;
+				else
+#endif
+				rtgui_dc_draw_border(dc, &rect, RTGUI_BORDER_SUNKEN);
+			}
+			else
+			{
+#ifdef RTGUI_USING_NOTEBOOK_IMAGE
+				if (notebook->childs[index].unpressed_image != RT_NULL)
+					image = notebook->childs[index].unpressed_image;
+				else
+#endif
+					rtgui_dc_draw_border(dc, &rect, RTGUI_BORDER_BOX);
+			}
+
+			rtgui_font_get_metrics(RTGUI_WIDGET_FONT(notebook), 
+				notebook->childs[index].title, &text_rect);
+			rtgui_rect_moveto_align(&rect, &text_rect, RTGUI_ALIGN_CENTER);
 
-		rtgui_dc_draw_text(dc, notebook->childs[index].title, &rect);
-		rect.x1 += RTGUI_NOTEBOOK_TAB_WIDTH;
-		rect.x2 += RTGUI_NOTEBOOK_TAB_WIDTH;
+#ifdef RTGUI_USING_NOTEBOOK_IMAGE
+			if (image != RT_NULL)
+			{
+				image_rect.x1 = 0;
+				image_rect.y1 = RTGUI_WIDGET_DEFAULT_MARGIN;
+				image_rect.x2 = image_rect.x1 + image->w;
+				image_rect.y2 = image_rect.y1 + image->h;
+				rtgui_rect_moveto_align(&rect, &image_rect, RTGUI_ALIGN_CENTER_HORIZONTAL);
+				
+				rtgui_image_blit(image, dc, &image_rect);
+			}
+			if (image != RT_NULL)
+			{
+				int text_height = text_rect.y2 - text_rect.y1;
+				
+				text_rect.y1 = image_rect.y2 +  RTGUI_WIDGET_DEFAULT_MARGIN;
+				text_rect.y2 = text_rect.y1 + text_height;
+			}
+			image = RT_NULL;
+#endif
+
+			rtgui_dc_draw_text(dc, notebook->childs[index].title, &text_rect);
+
+			/* move to next tab */
+			rect.x1 = rect.x2;
+			rect.x2 = rect.x1 + notebook->tab_w;
+		}
 	}
+	else
+	{
+		rect.y2 = rect.y1 + notebook->tab_h;
+		/* draw tab bar */
+		for (index = 0; index < notebook->count; index++)
+		{
+			if (notebook->current == index)
+			{
+#ifdef RTGUI_USING_NOTEBOOK_IMAGE
+				if (notebook->childs[index].pressed_image != RT_NULL)
+					image = notebook->childs[index].pressed_image;
+				else
+#endif
+					rtgui_dc_draw_border(dc, &rect, RTGUI_BORDER_SUNKEN);
+			}
+			else
+			{
+#ifdef RTGUI_USING_NOTEBOOK_IMAGE
+				if (notebook->childs[index].unpressed_image != RT_NULL)
+					image = notebook->childs[index].unpressed_image;
+				else
+#endif
+					rtgui_dc_draw_border(dc, &rect, RTGUI_BORDER_BOX);
+			}
+
+			rtgui_font_get_metrics(RTGUI_WIDGET_FONT(notebook), 
+				notebook->childs[index].title, &text_rect);
+			rtgui_rect_moveto_align(&rect, &text_rect, RTGUI_ALIGN_CENTER);
+#ifdef RTGUI_USING_NOTEBOOK_IMAGE
+			if (image != RT_NULL)
+			{
+				image_rect.x1 = 0;
+				image_rect.y1 = RTGUI_WIDGET_DEFAULT_MARGIN;
+				image_rect.x2 = image->w;
+				image_rect.y2 = image_rect.y1 + image->h;
+				rtgui_rect_moveto_align(&rect, &image_rect, RTGUI_ALIGN_CENTER_HORIZONTAL);
+				
+				rtgui_image_blit(image, dc, &image_rect);
+			}
+
+			if (image != RT_NULL)
+			{
+				int text_height = text_rect.y2 - text_rect.y1;
+				
+				text_rect.y1 = image_rect.y2 +  RTGUI_WIDGET_DEFAULT_MARGIN;
+				text_rect.y2 = text_rect.y1 + text_height;
+			}
+			image = RT_NULL;
+#endif
+			rtgui_dc_draw_text(dc, notebook->childs[index].title, &text_rect);
+
+			/* move to next tab */
+			rect.y1 = rect.y2;
+			rect.y2 = rect.y1 + notebook->tab_h;
+		}
 
+	}
 }
 
 static void _rtgui_notebook_ondraw(struct rtgui_notebook *notebook)
@@ -120,18 +236,36 @@ static void _rtgui_notebook_onmouse(struct rtgui_notebook *notebook, struct rtgu
 		int index;
 		struct rtgui_dc* dc;
 
-		index = (emouse->x - rect.x1) / RTGUI_NOTEBOOK_TAB_WIDTH;
-		if (index < notebook->count && index != notebook->current)
+		if (notebook->flag == RTGUI_NOTEBOOK_BOTTOM || notebook->flag == RTGUI_NOTEBOOK_TOP)
 		{
-			/* update tab bar */
-			dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(notebook));
-			if (dc == RT_NULL) return;
+			index = (emouse->x - rect.x1) / notebook->tab_w;
+			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_set_current_by_index(notebook, index);
 
-			_rtgui_notebook_draw_bar(notebook, dc);
+				_rtgui_notebook_draw_bar(notebook, dc);
 
-			rtgui_dc_end_drawing(dc);
+				rtgui_dc_end_drawing(dc);
+			}
+		}
+		else
+		{
+			index = (emouse->y - rect.y1) / notebook->tab_h;
+			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
@@ -146,17 +280,32 @@ static void _rtgui_notebook_onmouse(struct rtgui_notebook *notebook, struct rtgu
 
 static void _rtgui_notebook_get_page_rect(struct rtgui_notebook *notebook, struct rtgui_rect* rect)
 {
+	struct rtgui_rect tab_rect;
+
 	RT_ASSERT(notebook != RT_NULL);
 	RT_ASSERT(rect != RT_NULL);
 
+	_rtgui_notebook_get_bar_rect(notebook, &tab_rect);
 	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;
+	{
+		rect->y1 = tab_rect.y2;
+	}
 	else if (notebook->flag == RTGUI_NOTEBOOK_BOTTOM)
-		rect->y2 = rect->y2 - 25;
+	{
+		rect->y2 = tab_rect.y1;
+	}
+	else if (notebook->flag == RTGUI_NOTEBOOK_LEFT)
+	{
+		rect->x1 = tab_rect.x2;
+	}
+	else if (notebook->flag == RTGUI_NOTEBOOK_RIGHT)
+	{
+		rect->x2 = tab_rect.x1;
+	}
 }
 
 static void _rtgui_notebook_get_bar_rect(struct rtgui_notebook *notebook, struct rtgui_rect* rect)
@@ -170,9 +319,21 @@ static void _rtgui_notebook_get_bar_rect(struct rtgui_notebook *notebook, struct
 		rect->x1 = rect->y1 = rect->x2 = rect->y2 = 0;
 	}
 	else if (notebook->flag == RTGUI_NOTEBOOK_TOP)
-		rect->y2 = rect->y1 + 25;
+	{
+		rect->y2 = rect->y1 + notebook->tab_h;
+	}
 	else if (notebook->flag == RTGUI_NOTEBOOK_BOTTOM)
-		rect->y1 = rect->y2 - 25;
+	{
+		rect->y1 = rect->y2 - notebook->tab_h;
+	}
+	else if (notebook->flag == RTGUI_NOTEBOOK_LEFT)
+	{
+		rect->x2 = rect->x1 + notebook->tab_w;
+	}
+	else if (notebook->flag == RTGUI_NOTEBOOK_RIGHT)
+	{
+		rect->x1 = rect->x2 - notebook->tab_w;
+	}
 }
 
 struct rtgui_notebook* rtgui_notebook_create(const rtgui_rect_t* rect, rt_uint8_t style)
@@ -202,10 +363,14 @@ void rtgui_notebook_add(struct rtgui_notebook* notebook, const char* label, stru
 	notebook->count += 1;
 	notebook->childs = (struct rtgui_notebook_tab*)
 						rtgui_realloc(notebook->childs,
-									  sizeof(struct rtgui_notebook_tab) * notebook->count);
+						sizeof(struct rtgui_notebook_tab) * notebook->count);
 
 	notebook->childs[notebook->count - 1].title = rt_strdup(label);
 	notebook->childs[notebook->count - 1].widget = child;
+#ifdef RTGUI_USING_NOTEBOOK_IMAGE
+	notebook->childs[notebook->count - 1].pressed_image = RT_NULL;
+	notebook->childs[notebook->count - 1].unpressed_image = RT_NULL;
+#endif
 
 	/* set parent */
 	rtgui_widget_set_parent(child, RTGUI_WIDGET(notebook));
@@ -228,6 +393,47 @@ void rtgui_notebook_add(struct rtgui_notebook* notebook, const char* label, stru
 	}
 }
 
+#ifdef RTGUI_USING_NOTEBOOK_IMAGE
+void rtgui_notebook_add_image(struct rtgui_notebook* notebook, const char* label, struct rtgui_widget* child, 
+	struct rtgui_image *pressed_image, struct rtgui_image *unpressed_image)
+{
+	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;
+	notebook->childs[notebook->count - 1].pressed_image = pressed_image;
+	notebook->childs[notebook->count - 1].unpressed_image = unpressed_image;
+
+	/* 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);
+
+	if (RTGUI_WIDGET(notebook)->toplevel != RT_NULL &&
+		RTGUI_IS_TOPLEVEL(RTGUI_WIDGET(notebook)->toplevel))
+	{
+		struct rtgui_event_update_toplvl eup;
+		RTGUI_EVENT_UPDATE_TOPLVL_INIT(&eup);
+		eup.toplvl = RTGUI_WIDGET(notebook)->toplevel;
+		if (RTGUI_OBJECT(child)->event_handler)
+			RTGUI_OBJECT(child)->event_handler(RTGUI_OBJECT(child), (struct rtgui_event*)&eup);
+	}
+
+	return;
+}
+#endif
+
 void rtgui_notebook_remove(struct rtgui_notebook* notebook, rt_uint16_t index)
 {
 	struct rtgui_notebook_tab tab;
@@ -260,7 +466,7 @@ void rtgui_notebook_remove(struct rtgui_notebook* notebook, rt_uint16_t index)
 				sizeof(struct rtgui_notebook_tab) * notebook->count);
 		}
 
-		rtgui_free(tab.title);
+		rt_free(tab.title);
 
 		if (need_update)
 		{
@@ -281,6 +487,12 @@ int rtgui_notebook_get_count(struct rtgui_notebook* notebook)
 	return notebook->count;
 }
 
+void rtgui_notebook_get_client_rect(struct rtgui_notebook* notebook, struct rtgui_rect *rect)
+{
+	_rtgui_notebook_get_page_rect(notebook, rect);
+	rtgui_rect_moveto(rect, 0, 0);
+}
+
 struct rtgui_widget* rtgui_notebook_get_current(struct rtgui_notebook* notebook)
 {
 	RT_ASSERT(notebook != RT_NULL);

+ 2 - 2
components/rtgui/widgets/progressbar.c

@@ -16,7 +16,7 @@ static void _rtgui_progressbar_constructor(rtgui_progressbar_t *bar)
 	bar->position = 0;
 
 	/* set gc */
-	RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(bar)) = RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL;
+	RTGUI_WIDGET_TEXTALIGN(bar) = RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL;
 }
 
 DEFINE_CLASS_TYPE(progressbar, "progressbar", 
@@ -72,7 +72,7 @@ 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;
+	if (!RTGUI_WIDGET_IS_ENABLE(bar)) return;
 
     bar->position = value;
 

+ 7 - 7
components/rtgui/widgets/radiobox.c

@@ -11,7 +11,7 @@ static void _rtgui_radiobox_constructor(rtgui_radiobox_t *radiobox)
 
 	/* 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_TEXTALIGN(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);
 
@@ -34,8 +34,8 @@ static void rtgui_radiobox_onmouse(struct rtgui_radiobox* radiobox, struct rtgui
 	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 (RTGUI_WIDGET_IS_HIDE(radiobox) || 
+		!RTGUI_WIDGET_IS_ENABLE(radiobox)) return;
 
 	if (event->button & RTGUI_MOUSE_BUTTON_DOWN &&
 		event->button & RTGUI_MOUSE_BUTTON_LEFT)
@@ -57,7 +57,7 @@ static void rtgui_radiobox_onmouse(struct rtgui_radiobox* radiobox, struct rtgui
 		{
 			struct rtgui_rect bord_rect;
 			
-			rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(radiobox)), "H", &bord_rect);
+			rtgui_font_get_metrics(RTGUI_WIDGET_FONT(radiobox), "H", &bord_rect);
 			bord_size = rtgui_rect_height(bord_rect);
 		}
 		rtgui_rect_inflate(&rect, - bord_size);
@@ -97,7 +97,7 @@ rt_bool_t rtgui_radiobox_event_handler(struct rtgui_object* object, struct rtgui
 		break;
 
 	case RTGUI_EVENT_KBD:
-		if (RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(radiobox))) return RT_FALSE;
+		if (RTGUI_WIDGET_IS_HIDE(radiobox)) return RT_FALSE;
 
 #ifndef RTGUI_USING_SMALL_SIZE
 		if (widget->on_key != RT_NULL)
@@ -186,7 +186,7 @@ struct rtgui_radiobox* rtgui_radiobox_create(const char* label, int orient, char
 
 		/* set proper of control */
 		rtgui_radiobox_set_orientation(radiobox, orient);
-		rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(radiobox)), "H", &rect);
+		rtgui_font_get_metrics(RTGUI_WIDGET_FONT(radiobox), "H", &rect);
 		board_size = rtgui_rect_height(rect);
 
 		if (orient == RTGUI_VERTICAL)
@@ -202,7 +202,7 @@ struct rtgui_radiobox* rtgui_radiobox_create(const char* label, int orient, char
 			/* set init item size */
 			radiobox->item_size = 0;
 			
-			font = RTGUI_WIDGET_FONT(RTGUI_WIDGET(radiobox));
+			font = RTGUI_WIDGET_FONT(radiobox);
 			for (index = 0; index < number; index ++)
 			{
 				rtgui_font_get_metrics(font, radio_items[index], &rect);

+ 4 - 4
components/rtgui/widgets/scrollbar.c

@@ -35,7 +35,7 @@ static void _rtgui_scrollbar_constructor(rtgui_scrollbar_t *bar)
 	rtgui_widget_set_rect(RTGUI_WIDGET(bar), &rect);
 
 	/* set gc */
-	RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(bar)) = RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL;
+	RTGUI_WIDGET_TEXTALIGN(bar) = RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL;
 }
 
 rt_inline rt_uint32_t _rtgui_scrollbar_get_length(rtgui_scrollbar_t *bar)
@@ -362,7 +362,7 @@ void rtgui_scrollbar_set_range(struct rtgui_scrollbar* bar, int min, int max)
 
 	if (min >= max )
 	{
-		RTGUI_WIDGET_DISABLE(RTGUI_WIDGET(bar));
+		RTGUI_WIDGET_DISABLE(bar);
 		return;
 	}
 
@@ -380,12 +380,12 @@ void rtgui_scrollbar_set_page_step(struct rtgui_scrollbar* bar, int step)
 	if (bar->page_step > (bar->max_position - bar->min_position))
 	{
 		/* disable bar */
-		RTGUI_WIDGET_DISABLE(RTGUI_WIDGET(bar));
+		RTGUI_WIDGET_DISABLE(bar);
 	}
 	else
 	{
 		/* enable bar */
-		RTGUI_WIDGET_ENABLE(RTGUI_WIDGET(bar));
+		RTGUI_WIDGET_ENABLE(bar);
 	}
 }
 

+ 1 - 1
components/rtgui/widgets/slider.c

@@ -226,7 +226,7 @@ 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 (RTGUI_WIDGET_IS_ENABLE(slider))
 	{
 		if (value < slider->min) value = slider->min;
 		if (value > slider->max) value = slider->max;

+ 15 - 15
components/rtgui/widgets/textbox.c

@@ -39,10 +39,10 @@ static void _rtgui_textbox_constructor(rtgui_textbox_t *box)
 	rtgui_widget_set_onkey(RTGUI_WIDGET(box),rtgui_textbox_onkey);
 #endif
 
-	RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(box)) = black;
-	RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(box)) = white;
+	RTGUI_WIDGET_FOREGROUND(box) = black;
+	RTGUI_WIDGET_BACKGROUND(box) = white;
 	/* set default text align */
-	RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(box)) = RTGUI_ALIGN_CENTER_VERTICAL;
+	RTGUI_WIDGET_TEXTALIGN(box) = RTGUI_ALIGN_CENTER_VERTICAL;
 	/* set proper of control */
 	box->caret_timer = RT_NULL;
 	box->caret = RT_NULL;
@@ -52,7 +52,7 @@ static void _rtgui_textbox_constructor(rtgui_textbox_t *box)
 	/* allocate default line buffer */
 	box->text = RT_NULL;
 
-	rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(box)), "H", &rect);
+	rtgui_font_get_metrics(RTGUI_WIDGET_FONT(box), "H", &rect);
 	box->font_width = rtgui_rect_width(rect);
 	box->on_enter = RT_NULL;
 	box->dis_length = 0;
@@ -92,7 +92,7 @@ static void rtgui_textbox_get_caret_rect(rtgui_textbox_t *box, rtgui_rect_t *rec
 
 	rtgui_widget_get_rect(RTGUI_WIDGET(box), rect);
 
-	rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(box)), "H", &item_rect);
+	rtgui_font_get_metrics(RTGUI_WIDGET_FONT(box), "H", &item_rect);
 	font_h = rtgui_rect_height(item_rect);
 	box_h = rtgui_rect_height(*rect);
 
@@ -111,7 +111,7 @@ static void rtgui_textbox_init_caret(rtgui_textbox_t *box, rt_uint16_t position)
 
 	RT_ASSERT(box != RT_NULL);
 
-	if (!RTGUI_WIDGET_IS_FOCUSED(RTGUI_WIDGET(box)))
+	if (!RTGUI_WIDGET_IS_FOCUSED(box))
 		return;
 
 	rtgui_textbox_get_caret_rect(box, &box->caret_rect, position);
@@ -273,10 +273,11 @@ static rt_bool_t rtgui_textbox_onkey(struct rtgui_object* widget, rtgui_event_t*
 	}
 	else if(ekbd->key == RTGUIK_BACKSPACE)
 	{/* delete front character */
-
-		if(box->position == length - 1)
+		if(box->position == 0)
+			return RT_FALSE;
+		else if(box->position == length)
 		{
-			box->text[box->position] = '\0';
+			box->text[box->position-1] = '\0';
 			box->position --;
 		}
 		else if(box->position != 0)
@@ -369,7 +370,6 @@ static rt_bool_t rtgui_textbox_onkey(struct rtgui_object* widget, rtgui_event_t*
 						}
 					}
 				}
-				//rt_kprintf("%c ",ekbd->key);//debug printf
 			}
 			if(length+1 > box->line_length) return RT_FALSE;
 			if(length+1 > box->dis_length) return RT_FALSE;
@@ -417,7 +417,7 @@ static rt_bool_t rtgui_textbox_onfocus(struct rtgui_object* widget, rtgui_event_
 	/* if there is already a timer, don't create another one. */
 	if (box->caret_timer == RT_NULL)
 	{
-		box->caret_timer = rtgui_timer_create(100, RT_TIMER_FLAG_PERIODIC,rtgui_textbox_timeout, box);
+		box->caret_timer = rtgui_timer_create(50, RT_TIMER_FLAG_PERIODIC,rtgui_textbox_timeout, box);
 		/* set caret to show */
 		box->flag |= RTGUI_TEXTBOX_CARET_SHOW;
 		/* start caret timer */
@@ -485,21 +485,21 @@ void rtgui_textbox_ondraw(rtgui_textbox_t* box)
 
 	/* get widget rect */
 	rtgui_widget_get_rect(RTGUI_WIDGET(box), &rect);
-	fc = RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(box));
+	fc = RTGUI_WIDGET_FOREGROUND(box);
 
 	rtgui_rect_inflate(&rect, -1);
 
 	/* fill widget rect with white color */
-	RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(box)) = white;
+	RTGUI_WIDGET_BACKGROUND(box) = white;
 	rtgui_dc_fill_rect(dc,&rect);
 
 	rtgui_rect_inflate(&rect, 1);
 	/* draw border */
-	RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(box)) = RTGUI_RGB(123, 158, 189);
+	RTGUI_WIDGET_FOREGROUND(box) = RTGUI_RGB(123, 158, 189);
 	rtgui_dc_draw_rect(dc, &rect);
 
 	/* draw text */
-	RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(box)) = fc;
+	RTGUI_WIDGET_FOREGROUND(box) = fc;
 	if(box->text != RT_NULL)
 	{
 		rect.x1 += RTGUI_WIDGET_DEFAULT_MARGIN;

+ 5 - 5
components/rtgui/widgets/textview.c

@@ -35,7 +35,7 @@ static void _calc_line(rtgui_textview_t *textview, const char* text)
 
 	if (textview->lines != RT_NULL)
 	{
-		rt_free(textview->lines);
+		rtgui_free(textview->lines);
 		textview->lines = RT_NULL;
 		textview->line_count = 0;
 	}
@@ -100,7 +100,7 @@ static void _calc_line(rtgui_textview_t *textview, const char* text)
 	textview->line_count = line_index + 1;
 
 	/* allocate lines */
-	textview->lines = rt_malloc(textview->line_count * textview->line_width);
+	textview->lines = rtgui_malloc(textview->line_count * textview->line_width);
 	rt_memset(textview->lines, 0, (textview->line_count * textview->line_width));
 
 	/* fill lines */
@@ -177,7 +177,7 @@ static void _calc_width(rtgui_textview_t *textview)
 	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);
+	rtgui_font_get_metrics(RTGUI_WIDGET_FONT(textview), "W", &rect);
 	textview->line_width = width / rtgui_rect_width(rect) + 1;
 	textview->line_page_count = height / (rtgui_rect_height(rect) + 3);
 
@@ -192,7 +192,7 @@ static void _draw_textview(rtgui_textview_t *textview)
 	char* line;
 	rt_ubase_t line_index, item_height;
 
-	rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(textview)), "W", &font_rect);
+	rtgui_font_get_metrics(RTGUI_WIDGET_FONT(textview), "W", &font_rect);
 	item_height = rtgui_rect_height(font_rect) + 3;
 
 	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(textview));
@@ -236,7 +236,7 @@ static void _rtgui_textview_constructor(rtgui_textview_t *textview)
 static void _rtgui_textview_destructor(rtgui_textview_t *textview)
 {
 	/* release line memory */
-	rt_free(textview->lines);
+	rtgui_free(textview->lines);
 	textview->lines = RT_NULL;
 }
 

+ 4 - 3
components/rtgui/widgets/title.c

@@ -19,12 +19,13 @@ static void _rtgui_wintitle_constructor(rtgui_wintitle_t* wintitle)
 {
 	wintitle->title = RT_NULL;
 	RTGUI_WIDGET(wintitle)->flag = RTGUI_WIDGET_FLAG_DEFAULT;
-	RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(wintitle)) = RTGUI_ALIGN_CENTER_VERTICAL;
+	RTGUI_WIDGET_TEXTALIGN(wintitle) = RTGUI_ALIGN_CENTER_VERTICAL;
 }
 
 static void _rtgui_wintitle_deconstructor(rtgui_wintitle_t* wintitle)
 {
-	rt_free(wintitle->title);
+	if (wintitle->title != RT_NULL)
+		rt_free(wintitle->title);
 	wintitle->title = RT_NULL;
 }
 
@@ -58,7 +59,7 @@ void rtgui_wintitle_set_title(rtgui_wintitle_t* wintitle, const char* title)
 
 	if (wintitle->title != RT_NULL)
 	{
-		rtgui_free(wintitle->title);
+		rt_free(wintitle->title);
 	}
 
 	if (title != RT_NULL) wintitle->title = (char*)rt_strdup((const char*)title);

+ 1 - 1
components/rtgui/widgets/toplevel.c

@@ -31,7 +31,7 @@ static void _rtgui_toplevel_constructor(rtgui_toplevel_t *toplevel)
 	toplevel->drawing = 0;
 
 	/* hide toplevel default */
-	RTGUI_WIDGET_HIDE(RTGUI_WIDGET(toplevel));
+	RTGUI_WIDGET_HIDE(toplevel);
 }
 
 static void _rtgui_toplevel_destructor(rtgui_toplevel_t* toplevel)

+ 46 - 3
components/rtgui/widgets/widget.c

@@ -108,8 +108,20 @@ void rtgui_widget_destroy(rtgui_widget_t* widget)
 
 void rtgui_widget_set_rect(rtgui_widget_t* widget, const rtgui_rect_t* rect)
 {
+	int delta_x, delta_y;
+
 	if (widget == RT_NULL || rect == RT_NULL) return;
 
+	/* move to a logic position if it's a container widget */
+	if (RTGUI_IS_CONTAINER(widget))
+	{
+		delta_x = rect->x1 - widget->extent.x1;
+		delta_y = rect->y1 - widget->extent.y1;
+
+		rtgui_widget_move_to_logic(widget, delta_x, delta_y);
+	}
+
+	/* update extent rectangle */
 	widget->extent = *rect;
 
 	/* reset mini width and height */
@@ -205,6 +217,37 @@ void rtgui_widget_get_rect(rtgui_widget_t* widget, rtgui_rect_t *rect)
 	}
 }
 
+/**
+ * set widget draw style
+ */
+void rtgui_widget_set_border(rtgui_widget_t* widget, rt_uint32_t style)
+{
+	RT_ASSERT(widget != RT_NULL);
+
+	widget->border_style = style;
+	switch(style)
+	{
+	case RTGUI_BORDER_NONE:
+		widget->border = 0;
+		break;
+	case RTGUI_BORDER_SIMPLE:
+	case RTGUI_BORDER_UP:
+	case RTGUI_BORDER_DOWN:
+		widget->border = 1;
+		break;
+	case RTGUI_BORDER_STATIC:
+	case RTGUI_BORDER_RAISE:
+	case RTGUI_BORDER_SUNKEN:
+	case RTGUI_BORDER_BOX:
+	case RTGUI_BORDER_EXTRA:
+		widget->border = 2;
+		break;
+	default:
+		widget->border = 2;
+		break;
+	}
+}
+
 void rtgui_widget_set_onfocus(rtgui_widget_t* widget, rtgui_event_handler_ptr handler)
 {
 	RT_ASSERT(widget != RT_NULL);
@@ -451,7 +494,7 @@ rt_bool_t rtgui_widget_event_handler(struct rtgui_object* object, rtgui_event_t*
 #endif
 	}
 
-	return RT_FALSE;
+	return rtgui_object_event_handler(object, event);
 }
 
 /*
@@ -537,7 +580,7 @@ rt_bool_t rtgui_widget_onshow(struct rtgui_object *object, struct rtgui_event *e
 {
 	struct rtgui_widget *widget = RTGUI_WIDGET(object);
 
-    if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(object)))
+    if (!RTGUI_WIDGET_IS_HIDE(object))
         return RT_FALSE;
 
 	RTGUI_WIDGET_UNHIDE(widget);
@@ -552,7 +595,7 @@ rt_bool_t rtgui_widget_onhide(struct rtgui_object *object, struct rtgui_event *e
 {
 	struct rtgui_widget *widget = RTGUI_WIDGET(object);
 
-    if (RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(object)))
+    if (RTGUI_WIDGET_IS_HIDE(object))
         return RT_FALSE;
 
 	/* hide this widget */

+ 15 - 4
components/rtgui/widgets/window.c

@@ -38,7 +38,7 @@ static void _rtgui_win_constructor(rtgui_win_t *win)
 	win->focused_widget	= RT_NULL;
 
 	/* set window hide */
-	RTGUI_WIDGET_HIDE(RTGUI_WIDGET(win));
+	RTGUI_WIDGET_HIDE(win);
 
 	/* set window style */
 	win->style = RTGUI_WIN_STYLE_DEFAULT;
@@ -69,7 +69,8 @@ static void _rtgui_win_destructor(rtgui_win_t* win)
 	}
 
 	/* release field */
-	rt_free(win->title);
+	if (win->title != RT_NULL)
+		rt_free(win->title);
 }
 
 static rt_bool_t _rtgui_win_create_in_server(struct rtgui_win *win)
@@ -143,6 +144,16 @@ __on_err:
 	return RT_NULL;
 }
 
+rtgui_win_t* rtgui_mainwin_create(struct rtgui_win *parent_window, const char* title, rt_uint16_t style)
+{
+	struct rtgui_rect rect;
+
+	/* get rect of main window */
+	rtgui_get_mainwin_rect(&rect);
+
+	return rtgui_win_create(parent_window, title, &rect, style);
+}
+
 static rt_bool_t _rtgui_win_deal_close(struct rtgui_win *win,
 									   struct rtgui_event *event,
 									   rt_bool_t force_close)
@@ -303,7 +314,7 @@ void rtgui_win_hiden(struct rtgui_win* win)
 {
 	RT_ASSERT(win != RT_NULL);
 
-	if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(win)) &&
+	if (!RTGUI_WIDGET_IS_HIDE(win) &&
 		win->flag & RTGUI_WIN_FLAG_CONNECTED)
 	{
 		/* send hidden message to server */
@@ -436,7 +447,7 @@ rt_bool_t rtgui_win_event_handler(struct rtgui_object* object, struct rtgui_even
 	break;
 
 	case RTGUI_EVENT_WIN_ACTIVATE:
-		if (RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(win)))
+		if (RTGUI_WIDGET_IS_HIDE(win))
 		{
 			/* activate a hide window */
 			return RT_TRUE;