Browse Source

sync with RTGUI c074ff2898b9e

Full log is in GitHub.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2222 bbd45198-f89e-11dd-88c7-29a3b14d5316
chaos.proton@gmail.com 12 years ago
parent
commit
92a50c838d
78 changed files with 3667 additions and 2280 deletions
  1. 2 2
      components/rtgui/SConscript
  2. 66 0
      components/rtgui/common/blit.c
  3. 2 2
      components/rtgui/common/dc.c
  4. 3 3
      components/rtgui/common/dc_client.c
  5. 3 3
      components/rtgui/common/dc_hw.c
  6. 6 1
      components/rtgui/common/framebuffer_driver.c
  7. 3 2
      components/rtgui/common/image.c
  8. 734 557
      components/rtgui/common/image_bmp.c
  9. 479 0
      components/rtgui/common/image_jpg.c
  10. 49 7
      components/rtgui/common/image_png.c
  11. 51 4
      components/rtgui/common/pixel_driver.c
  12. 380 0
      components/rtgui/common/rtgui_app.c
  13. 416 3
      components/rtgui/common/rtgui_system.c
  14. 2 0
      components/rtgui/doc/attention.txt
  15. 2 2
      components/rtgui/doc/road_map.txt
  16. 1 0
      components/rtgui/include/rtgui/blit.h
  17. 25 0
      components/rtgui/include/rtgui/color.h
  18. 1 0
      components/rtgui/include/rtgui/driver.h
  19. 47 0
      components/rtgui/include/rtgui/event.h
  20. 1 1
      components/rtgui/include/rtgui/rtgui.h
  21. 88 0
      components/rtgui/include/rtgui/rtgui_app.h
  22. 0 99
      components/rtgui/include/rtgui/rtgui_application.h
  23. 2 1
      components/rtgui/include/rtgui/rtgui_config.h
  24. 1 4
      components/rtgui/include/rtgui/rtgui_object.h
  25. 5 3
      components/rtgui/include/rtgui/rtgui_server.h
  26. 11 0
      components/rtgui/include/rtgui/rtgui_system.h
  27. 0 44
      components/rtgui/include/rtgui/widgets/about_view.h
  28. 5 8
      components/rtgui/include/rtgui/widgets/box.h
  29. 6 5
      components/rtgui/include/rtgui/widgets/container.h
  30. 1 1
      components/rtgui/include/rtgui/widgets/filelist_view.h
  31. 1 1
      components/rtgui/include/rtgui/widgets/menu.h
  32. 45 0
      components/rtgui/include/rtgui/widgets/panel.h
  33. 32 21
      components/rtgui/include/rtgui/widgets/textbox.h
  34. 13 14
      components/rtgui/include/rtgui/widgets/widget.h
  35. 4 12
      components/rtgui/include/rtgui/widgets/window.h
  36. 4 0
      components/rtgui/server/driver.c
  37. 14 16
      components/rtgui/server/mouse.c
  38. 0 677
      components/rtgui/server/rtgui_application.c
  39. 91 53
      components/rtgui/server/server.c
  40. 183 120
      components/rtgui/server/topwin.c
  41. 2 2
      components/rtgui/server/topwin.h
  42. 0 101
      components/rtgui/widgets/about_view.c
  43. 29 114
      components/rtgui/widgets/box.c
  44. 3 1
      components/rtgui/widgets/button.c
  45. 2 0
      components/rtgui/widgets/checkbox.c
  46. 2 1
      components/rtgui/widgets/combobox.c
  47. 19 36
      components/rtgui/widgets/container.c
  48. 13 9
      components/rtgui/widgets/filelist_view.c
  49. 2 0
      components/rtgui/widgets/iconbox.c
  50. 2 0
      components/rtgui/widgets/label.c
  51. 10 11
      components/rtgui/widgets/listbox.c
  52. 5 5
      components/rtgui/widgets/listctrl.c
  53. 5 3
      components/rtgui/widgets/menu.c
  54. 27 12
      components/rtgui/widgets/notebook.c
  55. 89 0
      components/rtgui/widgets/panel.c
  56. 2 0
      components/rtgui/widgets/progressbar.c
  57. 15 1
      components/rtgui/widgets/radiobox.c
  58. 1 1
      components/rtgui/widgets/scrollbar.c
  59. 4 4
      components/rtgui/widgets/slider.c
  60. 2 0
      components/rtgui/widgets/staticline.c
  61. 422 177
      components/rtgui/widgets/textbox.c
  62. 2 0
      components/rtgui/widgets/textview.c
  63. 55 21
      components/rtgui/widgets/widget.c
  64. 82 64
      components/rtgui/widgets/window.c
  65. 1 0
      examples/gui/SConscript
  66. 13 12
      examples/gui/demo_application.c
  67. 0 4
      examples/gui/demo_listview_icon.c
  68. 3 3
      examples/gui/demo_view.c
  69. 1 1
      examples/gui/demo_view.h
  70. 13 2
      examples/gui/demo_view_benchmark.c
  71. 33 4
      examples/gui/demo_view_box.c
  72. 1 1
      examples/gui/demo_view_image.c
  73. 4 2
      examples/gui/demo_view_listbox.c
  74. 4 2
      examples/gui/demo_view_listctrl.c
  75. 6 4
      examples/gui/demo_view_menu.c
  76. 10 12
      examples/gui/demo_view_window.c
  77. 3 3
      examples/gui/mywidget.c
  78. 1 1
      examples/gui/mywidget.h

+ 2 - 2
components/rtgui/SConscript

@@ -9,6 +9,7 @@ common/rtgui_object.c
 common/rtgui_system.c
 common/rtgui_theme.c
 common/rtgui_xml.c
+common/rtgui_app.c
 common/dc.c
 common/dc_hw.c
 common/dc_buffer.c
@@ -34,7 +35,6 @@ common/pixel_driver.c
 """)
 
 server_src = Split("""
-server/rtgui_application.c
 server/driver.c
 server/mouse.c
 server/server.c
@@ -63,10 +63,10 @@ widgets/toplevel.c
 widgets/notebook.c
 widgets/container.c
 widgets/list_view.c
-widgets/about_view.c
 widgets/filelist_view.c
 widgets/widget.c
 widgets/window.c
+widgets/panel.c
 """)
 
 # The set of source files associated with this SConscript file.

+ 66 - 0
components/rtgui/common/blit.c

@@ -1,3 +1,9 @@
+/*
+ * Change Logs:
+ * Date           Author       Notes
+ * 2012-01-24     onelife      add one more blit table which exchanges the 
+ *  positions of R and B color components in output
+ */
 #include <rtgui/rtgui.h>
 #include <rtgui/blit.h>
 
@@ -305,3 +311,63 @@ rtgui_blit_line_func rtgui_blit_line_get(int dst_bpp, int src_bpp)
 
 	return _blit_table[dst_bpp][src_bpp];
 }
+
+
+static void rtgui_blit_line_3_2_inv(rt_uint8_t* dst_ptr, rt_uint8_t* src_ptr, int line)
+{
+	rt_uint16_t* dst;
+
+	dst = (rt_uint16_t*)dst_ptr;
+	line = line / 3;
+	while (line)
+	{
+		*dst = (((*src_ptr << 8) & 0x0000F800) |
+			((*(src_ptr + 1) << 3) & 0x000007E0)     |
+			((*(src_ptr + 2) >> 3) & 0x0000001F));
+
+		src_ptr += 3;
+		dst ++;
+		line --;
+	}
+
+	return;
+}
+
+void rtgui_blit_line_2_2_inv(rt_uint8_t* dst_ptr, rt_uint8_t* src_ptr, int line)
+{
+    rt_uint16_t *dst, *src;
+
+    dst = (rt_uint16_t *)dst_ptr;
+    src = (rt_uint16_t *)src_ptr;
+    line = line / 2;
+	while (line)
+	{
+		*dst = ((*src << 11) & 0xF800) | (*src & 0x07E0) | ((*src >> 11) & 0x001F);
+		src ++;
+		dst ++;
+		line --;
+	}
+}
+
+static const rtgui_blit_line_func _blit_table_inv[5][5] =
+{
+	/* 0_0, 1_0, 2_0, 3_0, 4_0 */
+	{RT_NULL, RT_NULL, RT_NULL, RT_NULL, RT_NULL },
+	/* 0_1, 1_1, 2_1, 3_1, 4_1 */
+	{RT_NULL, rtgui_blit_line_direct, rtgui_blit_line_2_1, rtgui_blit_line_3_1, rtgui_blit_line_4_1 },
+	/* 0_2, 1_2, 2_2, 3_2, 4_2 */
+	{RT_NULL, rtgui_blit_line_1_2, rtgui_blit_line_2_2_inv, rtgui_blit_line_3_2_inv, rtgui_blit_line_4_2 },
+	/* 0_3, 1_3, 2_3, 3_3, 4_3 */
+	{RT_NULL, rtgui_blit_line_1_3, rtgui_blit_line_2_3, rtgui_blit_line_direct, rtgui_blit_line_4_3 },
+	/* 0_4, 1_4, 2_4, 3_4, 4_4 */
+	{RT_NULL, rtgui_blit_line_1_4, rtgui_blit_line_2_4, rtgui_blit_line_3_4, rtgui_blit_line_direct },
+};
+
+rtgui_blit_line_func rtgui_blit_line_get_inv(int dst_bpp, int src_bpp)
+{
+	RT_ASSERT(dst_bpp>0 && dst_bpp < 5);
+	RT_ASSERT(src_bpp>0 && src_bpp < 5);
+
+	return _blit_table_inv[dst_bpp][src_bpp];
+}
+

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

@@ -138,12 +138,12 @@ void rtgui_dc_draw_vertical_line(struct rtgui_dc* dc, int x, int y1, int y2)
 	color = RTGUI_DC_FC(dc);
 
 	RTGUI_DC_FC(dc) = dark_grey;
-	rtgui_dc_draw_hline(dc, x, y1, y2);
+	rtgui_dc_draw_vline(dc, x, y1, y2);
 
 	x ++;
 
 	RTGUI_DC_FC(dc) = high_light;
-	rtgui_dc_draw_hline(dc, x, y1, y2);
+	rtgui_dc_draw_vline(dc, x, y1, y2);
 
 	/* restore color */
 	RTGUI_DC_FC(dc) = color;

+ 3 - 3
components/rtgui/common/dc_client.c

@@ -21,7 +21,7 @@
 
 #include <rtgui/driver.h>
 #include <rtgui/rtgui_system.h>
-#include <rtgui/rtgui_application.h>
+#include <rtgui/rtgui_app.h>
 #include <rtgui/rtgui_server.h>
 #include <rtgui/widgets/container.h>
 #include <rtgui/widgets/window.h>
@@ -139,7 +139,7 @@ struct rtgui_dc* rtgui_dc_client_create(rtgui_widget_t* owner)
 #endif
 		}
 	}
-	else if (RTGUI_IS_APPLICATION(owner->toplevel))
+	else if (RTGUI_IS_APP(owner->toplevel))
 	{
 		RT_ASSERT(0);
 	}
@@ -207,7 +207,7 @@ static rt_bool_t rtgui_dc_client_fini(struct rtgui_dc* dc)
 #endif
 		}
 	}
-	else if (RTGUI_IS_APPLICATION(owner->toplevel) ||
+	else if (RTGUI_IS_APP(owner->toplevel) ||
 		RTGUI_IS_WIN(owner->toplevel))
 	{
 		rtgui_toplevel_t* top = RTGUI_TOPLEVEL(owner->toplevel);

+ 3 - 3
components/rtgui/common/dc_hw.c

@@ -15,7 +15,7 @@
 #include <rtgui/dc_hw.h>
 #include <rtgui/driver.h>
 #include <rtgui/rtgui_system.h>
-#include <rtgui/rtgui_application.h>
+#include <rtgui/rtgui_app.h>
 #include <rtgui/rtgui_server.h>
 
 #include <rtgui/widgets/container.h>
@@ -117,7 +117,7 @@ struct rtgui_dc* rtgui_dc_hw_create(rtgui_widget_t* owner)
 #endif
 		}
 	}
-	else if (RTGUI_IS_APPLICATION(owner->toplevel) ||
+	else if (RTGUI_IS_APP(owner->toplevel) ||
 		RTGUI_IS_WIN(owner->toplevel))
 	{
 		rtgui_toplevel_t* top = RTGUI_TOPLEVEL(owner->toplevel);
@@ -184,7 +184,7 @@ static rt_bool_t rtgui_dc_hw_fini(struct rtgui_dc* dc)
 #endif
 		}
 	}
-	else if (RTGUI_IS_APPLICATION(owner->toplevel) ||
+	else if (RTGUI_IS_APP(owner->toplevel) ||
 		RTGUI_IS_WIN(owner->toplevel))
 	{
 		rtgui_toplevel_t* top = RTGUI_TOPLEVEL(owner->toplevel);

+ 6 - 1
components/rtgui/common/framebuffer_driver.c

@@ -1,3 +1,8 @@
+/*
+ * Change Logs:
+ * Date           Author       Notes
+ * 2012-01-24     onelife      fix a bug in framebuffer_draw_raw_hline
+ */
 #include <rtgui/rtgui_system.h>
 #include <rtgui/driver.h>
 
@@ -108,7 +113,7 @@ static void framebuffer_draw_raw_hline(rt_uint8_t *pixels, int x1, int x2, int y
 	rt_uint8_t *dst;
 
 	dst = GET_PIXEL(rtgui_graphic_get_device(), x1, y, rt_uint8_t);
-	rt_memcpy(dst, pixels, (x2 - x1) * (rtgui_graphic_get_device()->bits_per_pixel/8));
+	rt_memcpy(dst, pixels, (x2 - x1 + 1) * (rtgui_graphic_get_device()->bits_per_pixel/8));
 }
 
 const struct rtgui_graphic_driver_ops _framebuffer_rgb565_ops = 

+ 3 - 2
components/rtgui/common/image.c

@@ -10,6 +10,7 @@
  * Change Logs:
  * Date           Author       Notes
  * 2009-10-16     Bernard      first version
+ * 2012-01-24     onelife      add TJpgDec (Tiny JPEG Decompressor) support
  */
 #include <rtthread.h>
 #include <rtgui/image.h>
@@ -27,7 +28,7 @@
 #ifdef RTGUI_IMAGE_BMP
 #include <rtgui/image_bmp.h>
 #endif
-#ifdef RTGUI_IMAGE_JPEG
+#if (defined(RTGUI_IMAGE_JPEG) || defined(RTGUI_IMAGE_TJPGD))
 #include <rtgui/image_jpeg.h>
 #endif
 #ifdef RTGUI_IMAGE_PNG
@@ -50,7 +51,7 @@ void rtgui_system_image_init(void)
 	rtgui_image_bmp_init();
 #endif
 
-#ifdef RTGUI_IMAGE_JPEG
+#if (defined(RTGUI_IMAGE_JPEG) || defined(RTGUI_IMAGE_TJPGD))
 	rtgui_image_jpeg_init();
 #endif
 

+ 734 - 557
components/rtgui/common/image_bmp.c

@@ -1,3 +1,10 @@
+/*
+ * Change Logs:
+ * Date           Author       Notes
+ * 2012-01-24     onelife      Reimplement to improve efficiency and add 
+ *  features. The new decoder uses configurable fixed size working buffer and 
+ *  provides scaledown function.
+ */
 #include <rtthread.h>
 #include <rtgui/dc_hw.h>
 #include <rtgui/image.h>
@@ -5,6 +12,10 @@
 #include <rtgui/image_bmp.h>
 #include <rtgui/blit.h>
 
+#ifdef RTGUI_USING_DFS_FILERW
+#include <dfs_posix.h>
+#endif
+
 #ifdef RTGUI_IMAGE_BMP
 /* Compression encodings for BMP files */
 #ifndef BI_RGB
@@ -14,57 +25,32 @@
 #define BI_BITFIELDS	3
 #endif
 
-#define hw_driver				(rtgui_graphic_driver_get_default())
+#define BMP_WORKING_BUFFER_SIZE (384)   /* In multiple of 12 and bigger than 48 */
+#define BMP_MAX_SCALING_FACTOR  (10)    // TODO: find the max value!
+#define hw_driver			    (rtgui_graphic_driver_get_default())
 
 struct rtgui_image_bmp
 {
 	rt_bool_t is_loaded;
-
-	rt_uint32_t Rmask;
-	rt_uint32_t Gmask;
-	rt_uint32_t Bmask;
-
-	rt_size_t   pixel_offset;
-
-	rt_uint8_t  byte_per_pixel;
-	rt_uint8_t  pad;
-	rt_uint8_t  ExpandBMP;
-
 	rt_uint8_t *pixels;
-	rt_uint8_t *line_pixels;
-	rt_uint32_t pitch;
-
 	struct rtgui_filerw* filerw;
+	rt_uint32_t w, h;
+	rt_uint32_t pixel_offset;
+	rt_uint32_t pitch;    rt_uint8_t scale;
+	rt_uint8_t bit_per_pixel;
+	rt_uint8_t pad;
 };
 
-struct rtgui_image_bmp_header
-{
-	/* The Win32 BMP file header (14 bytes) */
-	char   magic[2];
-	rt_uint32_t bfSize;
-	rt_uint16_t bfReserved1;
-	rt_uint16_t bfReserved2;
-	rt_uint32_t bfOffBits;
-
-	/* The Win32 BITMAPINFOHEADER struct (40 bytes) */
-	rt_uint32_t biSize;
-	rt_int32_t  biWidth;
-	rt_int32_t  biHeight;
-	rt_uint16_t biPlanes;
-	rt_uint16_t biBitCount;
-	rt_uint32_t biCompression;
-	rt_uint32_t biSizeImage;
-	rt_int32_t  biXPelsPerMeter;
-	rt_int32_t  biYPelsPerMeter;
-	rt_uint32_t biClrUsed;
-	rt_uint32_t biClrImportant;
-};
-
+/* static rt_bool_t rtgui_image_bmp_check(struct rtgui_filerw* file,
+    rt_uint32_t *width, rt_uint32_t *height);
+static rt_bool_t rtgui_image_bmp_load(struct rtgui_image* image,
+    struct rtgui_filerw* file, rt_uint8_t scale, rt_bool_t load); */
 static rt_bool_t rtgui_image_bmp_check(struct rtgui_filerw* file);
 static rt_bool_t rtgui_image_bmp_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load);
 static void rtgui_image_bmp_unload(struct rtgui_image* image);
 static void rtgui_image_bmp_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect);
 
+
 struct rtgui_image_engine rtgui_image_bmp_engine =
 {
 	"bmp",
@@ -75,342 +61,429 @@ struct rtgui_image_engine rtgui_image_bmp_engine =
 	rtgui_image_bmp_blit
 };
 
-rt_inline rt_uint32_t rtgui_filerw_read32(struct rtgui_filerw* src)
-{
-	rt_uint32_t value;
-	rtgui_filerw_read(src, &value, (sizeof value), 1);
-	return value;
-}
-
-rt_inline rt_uint16_t rtgui_filerw_read16(struct rtgui_filerw* src)
-{
-	rt_uint16_t value;
-	rtgui_filerw_read(src, &value, (sizeof value), 1);
-	return value;
-
-}
-
 static rt_bool_t rtgui_image_bmp_check(struct rtgui_filerw* file)
+//static rt_bool_t rtgui_image_bmp_check(struct rtgui_filerw* file,
+//    rt_uint32_t *width, rt_uint32_t *height)
 {
-	char magic[2];
-	rt_bool_t is_bmp;
-	rt_off_t start;
-
-	if ( !file ) return 0;
-
-	start = rtgui_filerw_tell(file);
-
-	/* move to the beginning of file */
-	rtgui_filerw_seek(file, 0, RTGUI_FILE_SEEK_SET);
-
-	is_bmp = RT_FALSE;
-	if ( rtgui_filerw_read(file, magic, 1, sizeof(magic)) == sizeof(magic) )
-	{
-		if (magic[0] == 'B' &&
-				magic[1] == 'M')
+	rt_uint8_t buffer[18];
+	rt_bool_t is_bmp = RT_FALSE;
+
+    do
+    {
+        if (!file )
+        {
+            break;
+        }
+
+        /* Prepare to decode */
+        if (rtgui_filerw_seek(file, 0, RTGUI_FILE_SEEK_SET) < 0)
+        {
+            break;
+        }
+        if (rtgui_filerw_read(file, (void *)buffer, 18, 1) != 18)
+        {
+            break;
+        }
+        /* Read file type */
+		if (buffer[0] != 'B' || buffer[1] != 'M')
 		{
-			is_bmp = RT_TRUE;
+			break;
 		}
-	}
-
-	rtgui_filerw_seek(file, start, RTGUI_FILE_SEEK_SET);
 
-	return(is_bmp);
+        /* Read BMP header size */
+        if (*(rt_uint32_t *)&buffer[14] == 12)
+        {   /* Bitmap Header Version 2.x */
+            if (rtgui_filerw_read(file, (void *)buffer, 8, 1) != 8)
+            {
+                break;
+            }
+            /* Read image size */
+//            *width = (rt_uint32_t)*(rt_uint16_t *)&buffer[0];
+//            *height = (rt_uint32_t)*(rt_uint16_t *)&buffer[2];
+            is_bmp = RT_TRUE;
+        }
+        else
+        {   /* Bitmap Header Version bigger than 2.x */
+            if (rtgui_filerw_read(file, (void *)buffer, 8, 1) != 8)
+            {
+                break;
+            }
+            /* Read image size */
+//            *width = *(rt_uint32_t *)&buffer[0];
+//            *height = *(rt_uint32_t *)&buffer[4];
+            is_bmp = RT_TRUE;
+        }
+    } while(0);
+
+	return is_bmp;
 }
 
-static struct rtgui_image_palette* rtgui_image_bmp_load_palette(struct rtgui_image_bmp_header* header, struct rtgui_filerw* src)
+static struct rtgui_image_palette* rtgui_image_bmp_load_palette(
+    struct rtgui_filerw* file,
+    rt_uint32_t colorsUsed,
+    rt_bool_t alpha)
 {
 	/* Load the palette, if any */
-	rt_size_t i;
-	struct rtgui_image_palette* palette;
-
-	if (header->biClrUsed == 0)
-		header->biClrUsed = 1 << header->biBitCount;
-
-	palette = rtgui_image_palette_create(header->biClrUsed);
-	if (palette == RT_NULL) return RT_NULL;
-
-	if ( header->biSize == 12 )
-	{
-		rt_uint8_t r, g, b;
-		for ( i = 0; i < (int)header->biClrUsed; ++i )
-		{
-			rtgui_filerw_read(src, &b, 1, 1);
-			rtgui_filerw_read(src, &g, 1, 1);
-			rtgui_filerw_read(src, &r, 1, 1);
-			palette->colors[i] = RTGUI_RGB(r, g, b);
-		}
-	}
-	else
-	{
-		rt_uint8_t r, g, b, a;
-		for ( i = 0; i < (int)header->biClrUsed; ++i )
-		{
-			rtgui_filerw_read(src, &b, 1, 1);
-			rtgui_filerw_read(src, &g, 1, 1);
-			rtgui_filerw_read(src, &r, 1, 1);
-			rtgui_filerw_read(src, &a, 1, 1);
-			palette->colors[i] = RTGUI_ARGB(a, r, g, b);
-		}
-	}
+	rt_uint32_t i;
+	struct rtgui_image_palette *palette;
+
+    palette = rtgui_image_palette_create(colorsUsed);
+    if (palette == RT_NULL)
+    {
+        return RT_NULL;
+    }
+
+    if (alpha)
+    {
+    	rt_uint8_t temp[4];
+    	for (i = 0; i < colorsUsed; i++)
+    	{
+            if (rtgui_filerw_read(file, (void *)&temp, 1, 4) != 4)
+            {
+                rtgui_free(palette);
+                return RT_NULL;
+            }
+    		palette->colors[i] = RTGUI_ARGB(temp[3], temp[2], temp[1], temp[0]);
+    	}
+    }
+    else
+    {
+    	rt_uint8_t temp[3];
+    	for (i = 0; i < colorsUsed; i++)
+    	{
+            if (rtgui_filerw_read(file, (void *)&temp, 1, 3) != 3)
+            {
+                rtgui_free(palette);
+                return RT_NULL;
+            }
+    		palette->colors[i] = RTGUI_RGB(temp[2], temp[1], temp[0]);
+    	}
+    }
 
 	return palette;
 }
 
-static rt_bool_t rtgui_image_bmp_load(struct rtgui_image* image, struct rtgui_filerw* src, rt_bool_t load)
+static rt_bool_t rtgui_image_bmp_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load)
+//static rt_bool_t rtgui_image_bmp_load(struct rtgui_image* image,
+//    struct rtgui_filerw* file, rt_uint8_t scale, rt_bool_t load)
 {
-	rt_uint32_t Rmask;
-	rt_uint32_t Gmask;
-	rt_uint32_t Bmask;
-	int ExpandBMP, bmpPitch;
+    rt_uint8_t scale = 2;
+    rt_uint8_t *wrkBuffer;
 	struct rtgui_image_bmp* bmp;
-	struct rtgui_image_bmp_header* header;
-	struct rtgui_image_palette* palette;
-
-	bmp = RT_NULL;
-	header = RT_NULL;
-	palette = RT_NULL;
-	header = (struct rtgui_image_bmp_header*) rtgui_malloc(sizeof(struct rtgui_image_bmp_header));
-	if (header == RT_NULL) return RT_FALSE;
-
-	if ( rtgui_filerw_read(src, header->magic, 1, sizeof(header->magic)) ==
-		sizeof(sizeof(header->magic)) )
-	{
-		if (header->magic[0] != 'B' ||
-			header->magic[1] != 'M')
-		{
-			goto __exit;
-		}
-	}
-
-	header->bfSize		= rtgui_filerw_read32(src);
-	header->bfReserved1	= rtgui_filerw_read16(src);
-	header->bfReserved2	= rtgui_filerw_read16(src);
-	header->bfOffBits	= rtgui_filerw_read32(src);
-
-	/* Read the Win32 BITMAPINFOHEADER */
-	header->biSize		= rtgui_filerw_read32(src);
-	if ( header->biSize == 12 )
-	{
-		header->biWidth		= (rt_uint32_t)rtgui_filerw_read16(src);
-		header->biHeight	= (rt_uint32_t)rtgui_filerw_read16(src);
-		header->biPlanes	= rtgui_filerw_read16(src);
-		header->biBitCount	= rtgui_filerw_read16(src);
-		header->biCompression	= BI_RGB;
-		header->biSizeImage	= 0;
-		header->biXPelsPerMeter	= 0;
-		header->biYPelsPerMeter	= 0;
-		header->biClrUsed	= 0;
-
-		header->biClrImportant	= 0;
-
-	}
-	else
-	{
-		header->biWidth		= rtgui_filerw_read32(src);
-		header->biHeight	= rtgui_filerw_read32(src);
-		header->biPlanes	= rtgui_filerw_read16(src);
-		header->biBitCount	= rtgui_filerw_read16(src);
-		header->biCompression	= rtgui_filerw_read32(src);
-		header->biSizeImage	= rtgui_filerw_read32(src);
-		header->biXPelsPerMeter	= rtgui_filerw_read32(src);
-		header->biYPelsPerMeter	= rtgui_filerw_read32(src);
-		header->biClrUsed	= rtgui_filerw_read32(src);
-		header->biClrImportant	= rtgui_filerw_read32(src);
-
-	}
-
-	/* allocate palette and expand 1 and 4 bit bitmaps to 8 bits per pixel */
-	switch (header->biBitCount)
-	{
-	case 1:
-		ExpandBMP = header->biBitCount;
-		palette = rtgui_image_bmp_load_palette(header, src);
-		header->biBitCount = 8;
-		break;
-
-	case 4:
-		ExpandBMP = header->biBitCount;
-		palette = rtgui_image_bmp_load_palette(header, src);
-		header->biBitCount = 8;
-		break;
-
-	case 8:
-		palette = rtgui_image_bmp_load_palette(header, src);
-		ExpandBMP = 0;
-		break;
-
-	default:
-		ExpandBMP = 0;
-		break;
-	}
-
-	/* We don't support any BMP compression right now */
-	Rmask = Gmask = Bmask = 0;
-	switch (header->biCompression)
-	{
-	case BI_RGB:
-		/* If there are no masks, use the defaults */
-		if ( header->bfOffBits == (14 + header->biSize) )
+    rt_uint32_t bmpHeaderSize;
+    rt_uint32_t colorsUsed;
+
+    if (scale > BMP_MAX_SCALING_FACTOR)
+    {
+        return RT_FALSE;
+    }
+
+    do
+    {
+        wrkBuffer = (rt_uint8_t *)rt_malloc(BMP_WORKING_BUFFER_SIZE);
+        if (wrkBuffer == RT_NULL)
+        {
+            rt_kprintf("BMP err: no mem\n");
+            break;
+        }
+
+        bmp = (struct rtgui_image_bmp*)rtgui_malloc(sizeof(struct rtgui_image_bmp));
+        if (bmp == RT_NULL)
+        {
+            break;
+        }
+
+        /* Prepare to decode */
+        if (rtgui_filerw_seek(file, 0, RTGUI_FILE_SEEK_SET) < 0)
+        {
+            break;
+        }
+        if (rtgui_filerw_read(file, (void *)wrkBuffer, 18, 1) != 18)
+        {
+            break;
+        }
+        /* Read file type */
+		if (wrkBuffer[0] != 'B' || wrkBuffer[1] != 'M')
 		{
-			/* Default values for the BMP format */
-			switch (header->biBitCount)
-			{
-			case 15:
-			case 16:
-				Rmask = 0x7C00;
-				Gmask = 0x03E0;
-				Bmask = 0x001F;
-				break;
-
-			case 24:
-			case 32:
-				Rmask = 0x00FF0000;
-				Gmask = 0x0000FF00;
-				Bmask = 0x000000FF;
-				break;
-
-			default:
-				break;
-			}
 			break;
 		}
-		/* Fall through -- read the RGB masks */
-
-	case BI_BITFIELDS:
-		switch (header->biBitCount)
-		{
-		case 15:
-		case 16:
-		case 32:
-			Rmask = rtgui_filerw_read32(src);
-			Gmask = rtgui_filerw_read32(src);
-			Bmask = rtgui_filerw_read32(src);
-			break;
-
-		default:
-			break;
-		}
-		break;
-
-	default:
-		rt_kprintf("Compressed BMP files not supported\n");
-		goto __exit;
-	}
-
-	bmp = (struct rtgui_image_bmp*) rtgui_malloc(sizeof(struct rtgui_image_bmp));
-	if (bmp == RT_NULL)
-		goto __exit;
-
-	/* set image information */
-	image->w = header->biWidth;
-	image->h = header->biHeight;
-	image->engine = &rtgui_image_bmp_engine;
-	image->data = bmp;
-	bmp->filerw = src;
-	bmp->byte_per_pixel = header->biBitCount/8;
-	bmp->pitch = image->w * bmp->byte_per_pixel;
-	bmp->pixel_offset = header->bfOffBits;
-	bmp->Rmask = Rmask; bmp->Gmask = Gmask; bmp->Bmask = Bmask;
-	bmp->ExpandBMP = ExpandBMP;
-	if (palette != RT_NULL) image->palette = palette;
-
-	/* get padding */
-	switch (ExpandBMP)
-	{
-	case 1:
-		bmpPitch = (header->biWidth + 7) >> 3;
-		bmp->pad  = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0);
-		break;
-
-	case 4:
-		bmpPitch = (header->biWidth + 1) >> 1;
-		bmp->pad  = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0);
-		break;
-
-	default:
-		bmp->pad  = ((bmp->pitch%4) ? (4-(bmp->pitch%4)) : 0);
-		break;
-	}
-
-	if (load == RT_TRUE)
-	{
-		rt_uint8_t *bits;
-		rt_uint32_t i;
-
-		/* load all pixels */
-		bmp->pixels = rtgui_malloc(image->h * bmp->pitch);
-		if (bmp->pixels == RT_NULL)
-			goto __exit;
-
-		/* Read the pixels.  Note that the bmp image is upside down */
-		if ( rtgui_filerw_seek(src, bmp->pixel_offset, RTGUI_FILE_SEEK_SET) < 0)
-			goto __exit;
-
-		bits = bmp->pixels + image->h * bmp->pitch;
-		while ( bits > bmp->pixels )
-		{
-			bits -= bmp->pitch;
-			switch (ExpandBMP)
-			{
-			case 1:
-			case 4:
-				{
-					rt_uint8_t pixel = 0;
-					int   shift = (8 - ExpandBMP);
-					for ( i=0; i < image->w; ++i )
-					{
-						if ( i % (8/ExpandBMP) == 0 )
-						{
-							if ( !rtgui_filerw_read(src, &pixel, 1, 1) )
-								goto __exit;
-
-						}
-						*(bits+i) = (pixel>>shift);
-						pixel <<= ExpandBMP;
-					}
-				}
-				break;
-
-			default:
-				if ( rtgui_filerw_read(src, bits, 1, bmp->pitch) != bmp->pitch ) goto __exit;
-				break;
-			}
-
-			/* Skip padding bytes  */
-			if ( bmp->pad )
-			{
-				rt_uint8_t padbyte;
-				for ( i=0; i < bmp->pad; ++i )
-				{
-					rtgui_filerw_read(src, &padbyte, 1, 1);
-				}
-			}
-		}
-
-		rtgui_filerw_close(bmp->filerw);
-		bmp->line_pixels = RT_NULL;
-		bmp->filerw = RT_NULL;
-		bmp->pixel_offset = 0;
-	}
-	else
-	{
-		bmp->pixels = RT_NULL;
-		bmp->line_pixels = rtgui_malloc(bmp->pitch);
-	}
-
-	return RT_TRUE;
-
-__exit:
-	rtgui_free(header);
-	if (palette != RT_NULL)
-	{
-		rtgui_free(palette);
-		image->palette = RT_NULL;
-	}
-
-	if (bmp != RT_NULL)
-		rtgui_free(bmp->pixels);
+//        rt_kprintf("BMP: format ok\n");
+        /* Read pixel array offset */
+        bmp->pixel_offset = *(rt_uint32_t *)&wrkBuffer[10];
+//        rt_kprintf("BMP: bmp->pixel_offset %d\n", bmp->pixel_offset);
+        /* Read BMP header size */
+        bmpHeaderSize = *(rt_uint32_t *)&wrkBuffer[14];
+//        rt_kprintf("BMP: bmpHeaderSize %d\n", bmpHeaderSize);
+        colorsUsed = 0;
+        if (bmpHeaderSize == 12)
+        {   /* Bitmap Header Version 2.x */
+            if (rtgui_filerw_read(file, (void *)wrkBuffer, 8, 1) != 8)
+            {
+                break;
+            }
+            /* Read image size */
+            bmp->w = (rt_uint32_t)*(rt_uint16_t *)&wrkBuffer[0];
+            bmp->h = (rt_uint32_t)*(rt_uint16_t *)&wrkBuffer[2];
+            /* Read bits per pixel */
+            bmp->bit_per_pixel = (rt_uint8_t)*(rt_uint16_t *)&wrkBuffer[6];
+        }
+        else
+        {   /* Bitmap Header Version bigger than 2.x */
+            rt_uint32_t compression;
+
+            if (rtgui_filerw_read(file, (void *)wrkBuffer, 36, 1) != 36)
+            {
+                break;
+            }
+            /* Read image size */
+            bmp->w = *(rt_uint32_t *)&wrkBuffer[0];
+            bmp->h = *(rt_uint32_t *)&wrkBuffer[4];
+            /* Read bits per pixel */
+            bmp->bit_per_pixel = (rt_uint8_t)*(rt_uint16_t *)&wrkBuffer[10];
+            if (bmp->bit_per_pixel > 32)
+            {
+                rt_kprintf("BMP err: unsupported format\n");
+                break;
+            }
+            /* Read compression method */
+            compression = *(rt_uint32_t *)&wrkBuffer[12];
+            if (compression != BI_RGB && compression != BI_BITFIELDS)
+            {
+                rt_kprintf("BMP err: unsupported format\n");
+                break;
+            }
+            /* Read number of colors */
+            colorsUsed = *(rt_uint32_t *)&wrkBuffer[28];
+        }
+        if (!colorsUsed)
+        {
+            colorsUsed = 1 << bmp->bit_per_pixel;
+        }
+
+        /* Load palette */
+        if (bmp->bit_per_pixel <= 8)
+        {
+            if (rtgui_filerw_seek(file, 14 + bmpHeaderSize, RTGUI_FILE_SEEK_SET) < 0)
+            {
+                break;
+            }
+
+            image->palette = rtgui_image_bmp_load_palette(file, colorsUsed,
+                bmpHeaderSize > 12 ? RT_TRUE : RT_FALSE);
+            if (image->palette == RT_NULL)
+            {
+                break;
+            }
+        }
+
+        /* Set image information */
+        bmp->is_loaded = RT_FALSE;
+        bmp->scale = scale;
+        if (bmp->bit_per_pixel == 1)
+        {
+        	bmp->pitch = (bmp->w + 7) >> 3;
+        }
+        else if (bmp->bit_per_pixel == 4)
+        {
+        	bmp->pitch = (bmp->w + 1) >> 1;
+        }
+        else
+        {
+            bmp->pitch = bmp->w * (bmp->bit_per_pixel >> 3);
+        }
+        bmp->pad = ((bmp->pitch % 4) ? (4 - (bmp->pitch % 4)) : 0);
+        bmp->pixels = RT_NULL;
+        bmp->filerw = file;
+
+        image->w = bmp->w >> bmp->scale;
+        image->h = bmp->h >> bmp->scale;
+        image->engine = &rtgui_image_bmp_engine;
+        image->data = bmp;
+
+        /* Start to decode */
+        if (load == RT_TRUE)
+        {
+            rt_bool_t error = RT_FALSE;
+            rt_uint8_t *dst;
+            rt_uint32_t imageWidth;
+            rt_uint16_t readLength, readIndex, loadIndex;
+            rt_uint8_t skipLength;
+            rt_uint16_t y;
+            rt_uint8_t bytePerPixel;
+            rt_int8_t scale1, scale2;
+
+            bytePerPixel = bmp->bit_per_pixel / 8;
+            if (!bytePerPixel)
+            {
+                bytePerPixel = 1;
+            }
+            imageWidth = image->w * bytePerPixel;       /* Scaled width in byte */
+            bmp->pixels = rtgui_malloc(image->h * imageWidth);
+            if (bmp->pixels == RT_NULL)
+            {
+                rt_kprintf("BMP err: no mem to load (%d)\n", image->h * imageWidth);
+                break;
+            }
+
+            /* Read the pixels.  Note that the bmp image is upside down */
+            if (rtgui_filerw_seek(file, bmp->pixel_offset, RTGUI_FILE_SEEK_SET) < 0)
+            {
+                break;
+            }
+
+            if (bmp->bit_per_pixel == 1)
+            {
+                if (bmp->scale > 3)
+                {
+                    scale1 = bmp->scale - 3;
+                    scale2 = 3;
+                }
+                else
+                {
+                    scale1 = 0;
+                    scale2 = bmp->scale;
+                }
+            }
+            else if (bmp->bit_per_pixel == 4)
+            {
+                if (bmp->scale > 1)
+                {
+                    scale1 = bmp->scale - 1;
+                    scale2 = 1;
+                }
+                else
+                {
+                    scale1 = 0;
+                    scale2 = bmp->scale;
+                }
+            }
+
+            /* Process whole image */
+            y = 0;
+            while (y < image->h)
+            {
+                dst = bmp->pixels + (image->h - y - 1) * imageWidth;
+                readIndex = 0;
+                skipLength= 0;
+
+                /* Process a line */
+                while (readIndex < bmp->pitch)
+                {
+                    /* Put progress indicator */
+                    rt_kprintf("\r%lu%%", y * 100UL / image->h);
+
+                    /* Read data to buffer */
+                    readLength = (BMP_WORKING_BUFFER_SIZE > (bmp->pitch - readIndex)) ? \
+                        (bmp->pitch - readIndex) : BMP_WORKING_BUFFER_SIZE;
+                    if (rtgui_filerw_read(file, (void *)wrkBuffer, 1, readLength) != readLength)
+                    {
+                        rt_kprintf("BMP err: read failed\n");
+                        error = RT_TRUE;
+                        break;
+                    }
+                    readIndex += readLength;
+
+                    /* Process read buffer */
+                    if (bmp->bit_per_pixel == 1)
+                    {
+                        rt_uint8_t j;
+
+                        for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << scale1)
+                        {
+                            for (j = 0; j < 8; j += 1 << scale2)
+                            {
+                                *(dst++) = (wrkBuffer[loadIndex] & (1 << (7 - j))) >> (7 - j);
+                            }
+                        }
+                        if (scale1 && (readLength % (1 << scale1)))
+                        {
+                            skipLength = (1 << scale1) - readLength % (1 << scale1);
+                        }
+                    }
+                    else if (bmp->bit_per_pixel == 4)
+                    {
+                        rt_uint8_t j;
+
+                        for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << scale1)
+                        {
+                            for (j = 0; j < 8; j += 1 << (2 + scale2))
+                            {
+                                *(dst++) = (wrkBuffer[loadIndex] & (0x0F << (4 - j))) >> (4 - j);
+                            }
+                        }
+                        if (scale1 && (readLength % (1 << scale1)))
+                        {
+                            skipLength = (1 << scale1) - readLength % (1 << scale1);
+                        }
+                    }
+                    else
+                    {
+                        if (bmp->scale == 0)
+                        {
+                            rt_memcpy((void *)dst, (void *)wrkBuffer, readLength);
+                            dst += readLength;
+                        }
+                        else
+                        {
+                            for (loadIndex = skipLength; loadIndex < readLength; loadIndex += bytePerPixel << bmp->scale)
+                            {
+                                rt_memcpy((void *)dst, (void *)&wrkBuffer[loadIndex], bytePerPixel);
+                                dst += bytePerPixel;
+                            }
+                            if (readLength % (1 << bmp->scale))
+                            {
+                                skipLength = (1 << bmp->scale) - readLength % (1 << bmp->scale);
+                            }
+                        }
+                    }
+                }
+                if (error)
+                {
+                    break;
+                }
+                y++;
+
+                /* Skip padding bytes  */
+                if (bmp->pad)
+                {
+                    if ( rtgui_filerw_seek(file, bmp->pad, RTGUI_FILE_SEEK_CUR) < 0)
+                    {
+                        error = RT_TRUE;
+                        break;
+                    }
+                }
+
+                /* Height scale down */
+                if (bmp->scale)
+                {
+                    if (rtgui_filerw_seek(file, (bmp->pitch + bmp->pad) * ((1 << bmp->scale) - 1),
+                        RTGUI_FILE_SEEK_CUR) < 0)
+                    {
+                        error = RT_TRUE;
+                        break;
+                    }
+                }
+            }
+            if (error)
+            {
+                break;
+            }
+            /* Close file */
+            rtgui_filerw_close(bmp->filerw);
+            bmp->filerw = RT_NULL;
+            bmp->is_loaded = RT_TRUE;
+//            rt_kprintf("BMP: load to RAM\n");
+        }
+
+		/* Release memory */
+        rt_free(wrkBuffer);
+    	return RT_TRUE;
+    } while(0);
+
+    /* Release memory */
+    rt_free(wrkBuffer);
+	rtgui_free(image->palette);
+	rtgui_free(bmp->pixels);
 	rtgui_free(bmp);
 	return RT_FALSE;
 }
@@ -421,220 +494,324 @@ static void rtgui_image_bmp_unload(struct rtgui_image* image)
 
 	if (image != RT_NULL)
 	{
-		bmp = (struct rtgui_image_bmp*) image->data;
+		bmp = (struct rtgui_image_bmp*)image->data;
 
-		if (bmp->pixels != RT_NULL) rtgui_free(bmp->pixels);
-		if (bmp->line_pixels != RT_NULL) rtgui_free(bmp->line_pixels);
+		/* Release memory */
+		rtgui_free(bmp->pixels);
 		if (bmp->filerw != RT_NULL)
 		{
+            /* Close file */
 			rtgui_filerw_close(bmp->filerw);
 			bmp->filerw = RT_NULL;
 		}
-
-		/* release data */
 		rtgui_free(bmp);
 	}
 }
 
 static void rtgui_image_bmp_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* dst_rect)
 {
-	int y;
-	rt_uint16_t w, h;
+    rt_uint16_t w, h;
 	struct rtgui_image_bmp* bmp;
-
-	RT_ASSERT(image != RT_NULL || dc != RT_NULL || dst_rect != RT_NULL);
-
-	/* this dc is not visible */
-	if (rtgui_dc_get_visible(dc) != RT_TRUE) return;
-
-	bmp = (struct rtgui_image_bmp*) image->data;
-	RT_ASSERT(bmp != RT_NULL);
-
-	/* the minimum rect */
-	if (image->w < rtgui_rect_width(*dst_rect)) w = image->w;
-	else w = rtgui_rect_width(*dst_rect);
-	if (image->h < rtgui_rect_height(*dst_rect)) h = image->h;
-	else h = rtgui_rect_height(*dst_rect);
-
-	if (bmp->pixels != RT_NULL)
-	{
-		rt_uint8_t* ptr;
-
-		/* get pixel pointer */
-		ptr = bmp->pixels;
-		if (bmp->byte_per_pixel == hw_driver->bits_per_pixel/8)
-		{
-			for (y = 0; y < h; y ++)
-			{
-				dc->engine->blit_line(dc, 
-					dst_rect->x1, dst_rect->x1 + w,
-					dst_rect->y1 + y, 
-					ptr);
-				ptr += bmp->pitch;
-			}
-		}
-		else
-		{
-			rt_size_t pitch;
-			rt_uint8_t *line_ptr;
-
-			if (image->palette == RT_NULL)
-			{
-				rtgui_blit_line_func blit_line;
-				line_ptr = (rt_uint8_t*) rtgui_malloc((hw_driver->bits_per_pixel/8) * w);
-				blit_line = rtgui_blit_line_get(hw_driver->bits_per_pixel/8 , bmp->byte_per_pixel);
-				pitch = w * bmp->byte_per_pixel;
-				if (line_ptr != RT_NULL)
-				{
-					for (y = 0; y < h; y ++)
-					{
-						blit_line(line_ptr, ptr, pitch);
-						dc->engine->blit_line(dc,
-							dst_rect->x1, dst_rect->x1 + w,
-							dst_rect->y1 + y, 
-							line_ptr);
-						ptr += bmp->pitch;
-					}
-				}
-				rtgui_free(line_ptr);
-			}
-			else
-			{
-				int x;
-				rtgui_color_t color;
-
-				/* use palette */
-				for (y = 0; y < h; y ++)
-				{
-					ptr = bmp->pixels + (y * bmp->pitch);
-					for (x = 0; x < w; x ++)
-					{
-						color = image->palette->colors[*ptr]; ptr ++;
-						rtgui_dc_draw_color_point(dc, dst_rect->x1 + x, dst_rect->y1 + y, color);
-					}
-				}
-			}
-		}
-	}
-	else
-	{
-		int offset;
-		rt_uint8_t *bits;
-
-		/* calculate offset */
-		switch (bmp->ExpandBMP)
-		{
-		case 1:
-			offset = (image->h - h) * (image->w/8) * bmp->byte_per_pixel;
-			break;
-
-		case 4:
-			offset = (image->h - h) * (image->w/2) * bmp->byte_per_pixel;
-			break;
-
-		default:
-			offset = (image->h - h) * image->w * bmp->byte_per_pixel;
-			break;
-		}
-		/* seek to the begin of pixel data */
-		rtgui_filerw_seek(bmp->filerw, bmp->pixel_offset + offset, RTGUI_FILE_SEEK_SET);
-
-		if (bmp->ExpandBMP == 1 || bmp->ExpandBMP == 4)
-		{
-			int x;
-			rtgui_color_t color;
-			/* 1, 4 bit per pixels */
-
-			/* draw each line */
-			for (y = h - 1; y >= 0; y --)
-			{
-				/* read pixel data */
-				rt_uint8_t pixel = 0;
-				int   shift = (8 - bmp->ExpandBMP);
-				int i;
-
-				bits = bmp->line_pixels;
-				for ( i=0; i < image->w; ++i )
-				{
-					if ( i % (8/bmp->ExpandBMP) == 0 )
-					{
-						if ( !rtgui_filerw_read(bmp->filerw, &pixel, 1, 1) )
-							return;
-					}
-					*(bits+i) = (pixel>>shift);
-					pixel <<= bmp->ExpandBMP;
-				}
-
-				/* Skip padding bytes  */
-				if (bmp->pad)
-				{
-					int i;
-					rt_uint8_t padbyte;
-					for ( i=0; i < bmp->pad; ++i )
-						rtgui_filerw_read(bmp->filerw, &padbyte, 1, 1);
-				}
-
-				/* use palette */
-				bits = bmp->line_pixels;
-				for (x = 0; x < w; x ++)
-				{
-					color = image->palette->colors[*bits]; bits ++;
-					rtgui_dc_draw_color_point(dc, dst_rect->x1 + x, dst_rect->y1 + y, color);
-				}
-			}
-		}
-		else
-		{
-			rt_uint8_t *line_ptr = (rt_uint8_t*) rtgui_malloc((hw_driver->bits_per_pixel/8) * w);
-			if (line_ptr == RT_NULL) return;
-
-			/* draw each line */
-			for (y = h - 1; y >= 0; y --)
-			{
-				/* read line pixels */
-				rtgui_filerw_read(bmp->filerw, bmp->line_pixels, 1, bmp->pitch);
-
-				/* Skip padding bytes  */
-				if (bmp->pad)
-				{
-					int i;
-					rt_uint8_t padbyte;
-					for ( i=0; i < bmp->pad; ++i )
-						rtgui_filerw_read(bmp->filerw, &padbyte, 1, 1);
-				}
-
-				if (image->palette == RT_NULL)
-				{
-					int pitch;
-					rtgui_blit_line_func blit_line;
-					blit_line = rtgui_blit_line_get(hw_driver->bits_per_pixel/8 , bmp->byte_per_pixel);
-					pitch = w * bmp->byte_per_pixel;
-					if (line_ptr != RT_NULL)
-					{
-						blit_line(line_ptr, bmp->line_pixels, pitch);
-						dc->engine->blit_line(dc,
-							dst_rect->x1, dst_rect->x1 + w,
-							dst_rect->y1 + y, 
-							line_ptr);
-					}
-				}
-				else 
-				{
-					int x;
-					rtgui_color_t color;
-
-					/* use palette */
-					bits = bmp->line_pixels;
-					for (x = 0; x < w; x ++)
-					{
-						color = image->palette->colors[*bits]; bits ++;
-						rtgui_dc_draw_color_point(dc, dst_rect->x1 + x, dst_rect->y1 + y, color);
-					}
-				}
-			}
-			if (line_ptr != RT_NULL) rtgui_free(line_ptr);
-		}
-	}
+    rt_uint8_t bytePerPixel;
+    rt_uint32_t imageWidth;
+    rt_bool_t error;
+
+	bmp = (struct rtgui_image_bmp*)image->data;
+    RT_ASSERT(image != RT_NULL || dc != RT_NULL || dst_rect != RT_NULL || bmp != RT_NULL);
+
+    bytePerPixel = bmp->bit_per_pixel / 8;
+    if (!bytePerPixel)
+    {
+        bytePerPixel = 1;
+    }
+    imageWidth = image->w * bytePerPixel;       /* Scaled width in byte */
+    error = RT_FALSE;
+
+    do
+    {
+        /* this dc is not visible */
+        if (rtgui_dc_get_visible(dc) != RT_TRUE)
+        {
+            break;
+        }
+
+        /* the minimum rect */
+        if (image->w < rtgui_rect_width(*dst_rect))
+        {
+            w = image->w;
+        }
+        else
+        {
+            w = rtgui_rect_width(*dst_rect);
+        }
+        if (image->h < rtgui_rect_height(*dst_rect))
+        {
+            h = image->h;
+        }
+        else
+        {
+            h = rtgui_rect_height(*dst_rect);
+        }
+
+        if (!bmp->is_loaded)
+        {
+            rt_uint8_t *wrkBuffer;
+            rt_uint16_t readLength, readIndex, loadIndex;
+            rt_uint8_t skipLength;
+            rt_uint16_t x, y;
+            rt_int8_t scale1, scale2;
+
+            wrkBuffer = (rt_uint8_t *)rt_malloc(BMP_WORKING_BUFFER_SIZE);
+            if (wrkBuffer == RT_NULL)
+            {
+                rt_kprintf("BMP err: no mem (%d)\n", BMP_WORKING_BUFFER_SIZE);
+                break;
+            }
+
+            /* Read the pixels.  Note that the bmp image is upside down */
+            if (rtgui_filerw_seek(bmp->filerw, bmp->pixel_offset, RTGUI_FILE_SEEK_SET) < 0)
+            {
+                break;
+            }
+
+            if (bmp->bit_per_pixel == 1)
+            {
+                if (bmp->scale > 3)
+                {
+                    scale1 = bmp->scale - 3;
+                    scale2 = 3;
+                }
+                else
+                {
+                    scale1 = 0;
+                    scale2 = bmp->scale;
+                }
+            }
+            else if (bmp->bit_per_pixel == 4)
+            {
+                if (bmp->scale > 1)
+                {
+                    scale1 = bmp->scale - 1;
+                    scale2 = 1;
+                }
+                else
+                {
+                    scale1 = 0;
+                    scale2 = bmp->scale;
+                }
+            }
+
+            /* Process whole image */
+            y = 0;
+            while (y < image->h)
+            {
+                x = 0;
+                readIndex = 0;
+                skipLength= 0;
+
+                /* Process a line */
+                while (readIndex < bmp->pitch)
+                {
+                    /* Put progress indicator */
+                    rt_kprintf("\r%lu%%", y * 100UL / image->h);
+
+                    /* Read data to buffer */
+                    readLength = (BMP_WORKING_BUFFER_SIZE > (bmp->pitch - readIndex)) ? \
+                        (bmp->pitch - readIndex) : BMP_WORKING_BUFFER_SIZE;
+                    if (rtgui_filerw_read(bmp->filerw, (void *)wrkBuffer, 1, readLength) != readLength)
+                    {
+                        rt_kprintf("BMP err: read failed\n");
+                        error = RT_TRUE;
+                        break;
+                    }
+                    readIndex += readLength;
+
+                    /* Process read buffer */
+                    if (bmp->bit_per_pixel == 1)
+                    {
+                        rt_uint8_t j;
+                        rtgui_color_t color;
+
+                        for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << scale1)
+                        {
+                            for (j = 0; j < 8; j += 1 << scale2)
+                            {
+                                color = image->palette->colors[(wrkBuffer[loadIndex] & (1 << (7 - j))) >> (7 - j)];
+                                rtgui_dc_draw_color_point(dc,
+                                    dst_rect->x1 + x++,
+                                    dst_rect->y1 + image->h - y,
+                                    color);
+                            }
+                            if (scale1 && (readLength % (1 << scale1)))
+                            {
+                                skipLength = (1 << scale1) - readLength % (1 << scale1);
+                            }
+                        }
+                    }
+                    else if (bmp->bit_per_pixel == 4)
+                    {
+                        rt_uint8_t j;
+                        rtgui_color_t color;
+
+                        for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << scale1)
+                        {
+                            for (j = 0; j < 8; j += 1 << (2 + scale2))
+                            {
+                                color = image->palette->colors[(wrkBuffer[loadIndex] & (0x0F << (4 - j))) >> (4 - j)];
+                                rtgui_dc_draw_color_point(dc,
+                                    dst_rect->x1 + x++,
+                                    dst_rect->y1 + image->h - y,
+                                    color);
+                            }
+                        }
+                        if (scale1 && (readLength % (1 << scale1)))
+                        {
+                            skipLength = (1 << scale1) - readLength % (1 << scale1);
+                        }
+                    }
+                    else if (bmp->bit_per_pixel == 8)
+                    {
+                        rtgui_color_t color;
+
+                        for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << bmp->scale)
+                        {
+                            color = image->palette->colors[wrkBuffer[loadIndex]];
+                            rtgui_dc_draw_color_point(dc,
+                                dst_rect->x1 + x++,
+                                dst_rect->y1 + image->h - y,
+                                color);
+                        }
+                        if (readLength % (1 << bmp->scale))
+                        {
+                            skipLength = (1 << bmp->scale) - readLength % (1 << bmp->scale);
+                        }
+                    }
+                    else
+                    {
+                        rtgui_blit_line_func blit_line;
+                        rt_uint8_t hw_bytePerPixel = hw_driver->bits_per_pixel / 8;
+                        rt_uint8_t temp[4] = {0};
+
+                        if (!hw_bytePerPixel)
+                        {
+                            hw_bytePerPixel = 1;
+                        }
+
+                        if (hw_driver->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565)
+                        {
+                            blit_line = rtgui_blit_line_get_inv(hw_bytePerPixel, bytePerPixel);
+                        }
+                        else
+                        {
+                            blit_line = rtgui_blit_line_get(hw_bytePerPixel, bytePerPixel);
+                        }
+
+                        for (loadIndex = skipLength; loadIndex < readLength; loadIndex += bytePerPixel << bmp->scale)
+                        {
+                            blit_line(temp, &wrkBuffer[loadIndex], bytePerPixel);
+                            dc->engine->blit_line(dc,
+                                dst_rect->x1 + x, dst_rect->x1 + x,
+                                dst_rect->y1 + image->h - y,
+                                temp);
+                            x++;
+                        }
+                        if (readLength % (1 << bmp->scale))
+                        {
+                            skipLength = (1 << bmp->scale) - readLength % (1 << bmp->scale);
+                        }
+                    }
+                }
+                if (error)
+                {
+                    break;
+                }
+                y++;
+
+                /* Skip padding bytes  */
+                if (bmp->pad)
+                {
+                    if ( rtgui_filerw_seek(bmp->filerw, bmp->pad, RTGUI_FILE_SEEK_CUR) < 0)
+                    {
+                        error = RT_TRUE;
+                        break;
+                    }
+                }
+
+                /* Height scale down */
+                if (bmp->scale)
+                {
+                    if (rtgui_filerw_seek(bmp->filerw, (bmp->pitch + bmp->pad) * ((1 << bmp->scale) - 1),
+                        RTGUI_FILE_SEEK_CUR) < 0)
+                    {
+                        error = RT_TRUE;
+                        break;
+                    }
+                }
+            }
+            if (error)
+            {
+                break;
+            }
+            /* Release memory */
+            rt_free(wrkBuffer);
+//            rt_kprintf("BMP: load to display\n");
+        }
+        else
+        {
+            rt_uint16_t x, y;
+            rt_uint8_t* ptr;
+
+            for (y = 0; y < h; y ++)
+            {
+                ptr = bmp->pixels + (y * imageWidth);
+                if (bmp->bit_per_pixel <= 8)
+                {
+                    rtgui_color_t color;
+
+                    /* Using palette */
+                    for (x = 0; x < w; x ++)
+                    {
+                        color = image->palette->colors[*(ptr++)];
+                        rtgui_dc_draw_color_point(dc,
+                            dst_rect->x1 + x,
+                            dst_rect->y1 + y,
+                            color);
+                    }
+                }
+                else
+                {
+                    rtgui_blit_line_func blit_line;
+                    rt_uint8_t hw_bytePerPixel = hw_driver->bits_per_pixel / 8;
+                    rt_uint8_t temp[4] = {0};
+
+                    if (!hw_bytePerPixel)
+                    {
+                        hw_bytePerPixel = 1;
+                    }
+
+                    if (hw_driver->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565)
+                    {
+                        blit_line = rtgui_blit_line_get_inv(hw_bytePerPixel, bytePerPixel);
+                    }
+                    else
+                    {
+                        blit_line = rtgui_blit_line_get(hw_bytePerPixel, bytePerPixel);
+                    }
+
+                    for (x = 0; x < w; x ++)
+                    {
+                        blit_line(temp, ptr, bytePerPixel);
+                        ptr += bytePerPixel;
+                        dc->engine->blit_line(dc,
+                            dst_rect->x1 + x, dst_rect->x1 + x,
+                            dst_rect->y1 + y,
+                            temp);
+                    }
+                }
+            }
+        }
+//        rt_kprintf("BMP: blit ok\n");
+    } while(0);
 }
 
 void rtgui_image_bmp_init()

+ 479 - 0
components/rtgui/common/image_jpg.c

@@ -1,3 +1,8 @@
+/*
+ * Change Logs:
+ * Date           Author       Notes
+ * 2012-01-24     onelife      add TJpgDec (Tiny JPEG Decompressor) support
+ */
 #include <rtthread.h>
 #include <rtgui/rtgui.h>
 
@@ -494,3 +499,477 @@ static rt_bool_t rtgui_image_jpeg_check(struct rtgui_filerw* file)
 }
 
 #endif
+
+#if defined(RTGUI_IMAGE_TJPGD)
+/***************************************************************************//**
+ * @file    image_jpg.c
+ * @brief   JPEG decoder using TJpgDec module (elm-chan.org)
+ *  COPYRIGHT (C) 2012, RT-Thread Development Team
+ * @author  onelife
+ * @version 1.0
+ *******************************************************************************
+ * @section License
+ * 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
+ *******************************************************************************
+ * @section Change Logs
+ * Date         Author      Notes
+ * 2012-01-24   onelife     Initial creation for limited memory devices
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @addtogroup TJpgDec
+ * @{
+ ******************************************************************************/
+
+/* Includes ------------------------------------------------------------------*/
+#include "tjpgd.h"
+
+#include <rtgui/rtgui_system.h>
+#include <rtgui/filerw.h>
+#include <rtgui/blit.h>
+#include <rtgui/image_jpeg.h>
+
+#ifdef RTGUI_USING_DFS_FILERW
+#include <dfs_posix.h>
+#endif
+
+/* Private typedef -----------------------------------------------------------*/
+struct rtgui_image_jpeg
+{
+    struct rtgui_filerw* filerw;
+    struct rtgui_dc *dc;
+    rt_uint16_t dst_x, dst_y;
+    rt_uint16_t dst_w, dst_h;
+    rt_bool_t is_loaded;
+    rt_bool_t to_buffer;
+    rt_uint8_t scale;
+    rt_uint8_t byte_per_pixel;
+    JDEC tjpgd;                     /* jpeg structure */
+    void *pool;
+    rt_uint8_t *pixels;
+};
+
+/* Private define ------------------------------------------------------------*/
+#define TJPGD_WORKING_BUFFER_SIZE   (3100)
+#define TJPGD_MAX_MCU_WIDTH_ON_DISP (2 * 8 * 4)     /* Y component: 2x2; Display: 4-byte per pixel */
+#define TJPGD_MAX_SCALING_FACTOR    (3)
+#define hw_driver                   (rtgui_graphic_driver_get_default())
+
+/* Private macro -------------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* static rt_bool_t rtgui_image_jpeg_check(struct rtgui_filerw* file,
+    rt_uint16_t *width, rt_uint16_t *height);
+static rt_bool_t rtgui_image_jpeg_load(struct rtgui_image* image,
+    struct rtgui_filerw* file, rt_uint8_t scale, rt_bool_t load); */
+static rt_bool_t rtgui_image_jpeg_check(struct rtgui_filerw* file);
+static rt_bool_t rtgui_image_jpeg_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load);
+static void rtgui_image_jpeg_unload(struct rtgui_image* image);
+static void rtgui_image_jpeg_blit(struct rtgui_image* image,
+    struct rtgui_dc* dc, struct rtgui_rect* dst_rect);
+
+/* Private variables ---------------------------------------------------------*/
+struct rtgui_image_engine rtgui_image_jpeg_engine =
+{
+    "jpeg",
+    {RT_NULL},
+    rtgui_image_jpeg_check,
+    rtgui_image_jpeg_load,
+    rtgui_image_jpeg_unload,
+    rtgui_image_jpeg_blit
+};
+
+struct rtgui_image_engine rtgui_image_jpg_engine =
+{
+    "jpg",
+    {RT_NULL},
+    rtgui_image_jpeg_check,
+    rtgui_image_jpeg_load,
+    rtgui_image_jpeg_unload,
+    rtgui_image_jpeg_blit
+};
+
+/* Private functions ---------------------------------------------------------*/
+void rtgui_image_jpeg_init()
+{
+    /* register jpeg on image system */
+    rtgui_image_register_engine(&rtgui_image_jpeg_engine);
+    /* register jpg on image system */
+    rtgui_image_register_engine(&rtgui_image_jpg_engine);
+}
+
+static UINT tjpgd_in_func(JDEC *jdec, BYTE *buff, UINT ndata)
+{
+    struct rtgui_filerw *file = *(struct rtgui_filerw **)jdec->device;
+
+    if (buff == RT_NULL)
+    {
+        return rtgui_filerw_seek(file, ndata, RTGUI_FILE_SEEK_CUR);
+    }
+
+    return rtgui_filerw_read(file, (void *)buff, 1, ndata);
+}
+
+static UINT tjpgd_out_func(JDEC *jdec, void *bitmap, JRECT *rect)
+{
+    struct rtgui_image_jpeg *jpeg = (struct rtgui_image_jpeg *)jdec->device;
+    rt_uint16_t w, h, y;
+    rt_uint16_t rectWidth;               /* Width of source rectangular (bytes) */
+    rt_uint8_t *src, *dst;
+
+    /* Put progress indicator */
+    if (rect->left == 0)
+    {
+        rt_kprintf("\r%lu%%", (rect->top << jpeg->scale) * 100UL / jdec->height);
+    }
+
+    /* Copy the decompressed RGB rectanglar to the frame buffer */
+    rectWidth = (rect->right - rect->left + 1) * jpeg->byte_per_pixel;
+    src = (rt_uint8_t *)bitmap;
+
+    if (jpeg->to_buffer)
+    {
+        rt_uint16_t imageWidth;          /* Width of image (bytes) */
+
+        imageWidth = (jdec->width >> jdec->scale) * jpeg->byte_per_pixel;
+        dst = jpeg->pixels + rect->top * imageWidth + rect->left * jpeg->byte_per_pixel;
+                                        /* Left-top of destination rectangular */
+        for (h = rect->top; h <= rect->bottom; h++)
+        {
+            rt_memcpy(dst, src, rectWidth);
+            src += rectWidth;
+            dst += imageWidth;           /* Next line */
+        }
+    }
+    else
+    {
+        rtgui_blit_line_func blit_line = RT_NULL;
+
+        w = rect->right < jpeg->dst_w ? rect->right : jpeg->dst_w;
+        w = w - rect->left + 1;
+        h = rect->bottom < jpeg->dst_h ? rect->bottom : jpeg->dst_h;
+        h = h - rect->top + 1;
+        if (jpeg->byte_per_pixel == hw_driver->bits_per_pixel / 8)
+        {
+            if (hw_driver->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565)
+            {
+                blit_line = rtgui_blit_line_get_inv(hw_driver->bits_per_pixel / 8, jpeg->byte_per_pixel);
+            }
+        }
+        else
+        {
+            blit_line = rtgui_blit_line_get(hw_driver->bits_per_pixel / 8, jpeg->byte_per_pixel);
+        }
+
+        if (blit_line)
+        {
+            rt_uint8_t line_buf[TJPGD_MAX_MCU_WIDTH_ON_DISP];
+
+            for (y = 0; y < h; y++)
+            {
+                blit_line(line_buf, src, w * jpeg->byte_per_pixel);
+                jpeg->dc->engine->blit_line(jpeg->dc,
+                    jpeg->dst_x + rect->left, jpeg->dst_x + rect->left + w - 1,
+                    jpeg->dst_y + rect->top + y,
+                    line_buf);
+                src += rectWidth;
+            }
+        }
+        else
+        {
+            for (y = 0; y < h; y++)
+            {
+                jpeg->dc->engine->blit_line(jpeg->dc,
+                    jpeg->dst_x + rect->left, jpeg->dst_x + rect->left + w - 1,
+                    jpeg->dst_y + rect->top + y,
+                    src);
+                src += rectWidth;
+            }
+        }
+    }
+    return 1;                           /* Continue to decompress */
+}
+
+static rt_bool_t rtgui_image_jpeg_check(struct rtgui_filerw* file)
+//static rt_bool_t rtgui_image_jpeg_check(struct rtgui_filerw* file,
+//    rt_uint32_t *width, rt_uint32_t *height)
+{
+	rt_bool_t is_JPG;
+    JDEC tjpgd;
+    void *pool;
+
+    is_JPG = RT_FALSE;
+    do
+    {
+        if (!file )
+        {
+            break;
+        }
+
+        pool = rt_malloc(TJPGD_WORKING_BUFFER_SIZE);
+        if (pool == RT_NULL)
+        {
+            rt_kprintf("TJPGD err: no mem\n");
+            break;
+        }
+
+        if (rtgui_filerw_seek(file, 0, SEEK_SET) == -1)
+        {
+            break;
+        }
+
+        if (jd_prepare(&tjpgd, tjpgd_in_func, pool,
+            TJPGD_WORKING_BUFFER_SIZE, (void *)&file) == JDR_OK)
+        {
+//            *width = (rt_uint32_t)tjpgd.width;
+//            *height = (rt_uint32_t)tjpgd.height;
+            is_JPG = RT_TRUE;
+        }
+
+        rt_kprintf("TJPGD: check OK\n");
+    } while(0);
+
+    rt_free(pool);
+
+    return is_JPG;
+}
+
+static rt_bool_t rtgui_image_jpeg_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load)
+//static rt_bool_t rtgui_image_jpeg_load(struct rtgui_image* image,
+//    struct rtgui_filerw* file, rt_uint8_t scale, rt_bool_t load)
+{
+    rt_uint8_t scale = 2;
+    rt_bool_t res = RT_FALSE;
+    struct rtgui_image_jpeg *jpeg;
+    JRESULT ret;
+
+    if (scale > TJPGD_MAX_SCALING_FACTOR)
+    {
+        return RT_FALSE;
+    }
+
+    do
+    {
+        jpeg = (struct rtgui_image_jpeg *)rt_malloc(sizeof(struct rtgui_image_jpeg));
+        if (jpeg == RT_NULL)
+        {
+            break;
+        }
+        jpeg->filerw = file;
+        jpeg->is_loaded = RT_FALSE;
+        jpeg->to_buffer = load;
+        jpeg->scale = scale;
+#if (JD_FORMAT == 0)
+        jpeg->byte_per_pixel = 3;
+#elif (JD_FORMAT == 1)
+        jpeg->byte_per_pixel = 2;
+#endif
+        jpeg->pool = RT_NULL;
+        jpeg->pixels = RT_NULL;
+
+        jpeg->pool = rt_malloc(TJPGD_WORKING_BUFFER_SIZE);
+        if (jpeg->pool == RT_NULL)
+        {
+            rt_kprintf("TJPGD err: no mem (%d)\n", TJPGD_WORKING_BUFFER_SIZE);
+            break;
+        }
+
+        if (rtgui_filerw_seek(jpeg->filerw, 0, SEEK_SET) == -1)
+        {
+            break;
+        }
+
+        ret = jd_prepare(&jpeg->tjpgd, tjpgd_in_func, jpeg->pool,
+            TJPGD_WORKING_BUFFER_SIZE, (void *)jpeg);
+        if (ret != JDR_OK)
+        {
+            if (ret == JDR_FMT3)
+            {
+                rt_kprintf("TJPGD: not supported format\n");
+            }
+            break;
+        }
+        rt_kprintf("TJPGD: prepare OK\n");
+
+        image->w = (rt_uint16_t)jpeg->tjpgd.width >> jpeg->scale;
+        image->h = (rt_uint16_t)jpeg->tjpgd.height >> jpeg->scale;
+
+        /* set image private data and engine */
+        image->data = jpeg;
+        image->engine = &rtgui_image_jpeg_engine;
+
+        if (jpeg->to_buffer == RT_TRUE)
+        {
+            jpeg->pixels = (rt_uint8_t *)rtgui_malloc(
+                jpeg->byte_per_pixel * image->w * image->h);
+            if (jpeg->pixels == RT_NULL)
+            {
+                rt_kprintf("TJPGD err: no mem to load (%d)\n",
+                    jpeg->byte_per_pixel * image->w * image->h);
+                break;
+            }
+
+            ret = jd_decomp(&jpeg->tjpgd, tjpgd_out_func, jpeg->scale);
+            if (ret != JDR_OK)
+            {
+                break;
+            }
+
+            rtgui_filerw_close(jpeg->filerw);
+            jpeg->is_loaded = RT_TRUE;
+
+            rt_kprintf("TJPGD: load to RAM\n");
+        }
+        res = RT_TRUE;
+    } while(0);
+
+    if (!res || jpeg->is_loaded)
+    {
+        rt_free(jpeg->pool);
+    }
+    if (!res)
+    {
+        rtgui_free(jpeg->pixels);
+        rt_free(jpeg);
+    }
+
+    /* create jpeg image successful */
+    return res;
+}
+
+
+static void rtgui_image_jpeg_unload(struct rtgui_image* image)
+{
+    if (image != RT_NULL)
+    {
+        struct rtgui_image_jpeg* jpeg;
+
+        jpeg = (struct rtgui_image_jpeg*) image->data;
+        RT_ASSERT(jpeg != RT_NULL);
+
+        if (jpeg->to_buffer == RT_TRUE)
+        {
+            if (jpeg->is_loaded == RT_TRUE)
+            {
+                rtgui_free(jpeg->pixels);
+            }
+            if (jpeg->is_loaded != RT_TRUE)
+            {
+                rtgui_filerw_close(jpeg->filerw);
+            }
+        }
+        else
+        {
+            rt_free(jpeg->pool);
+            rtgui_filerw_close(jpeg->filerw);
+        }
+        rt_free(jpeg);
+    }
+    rt_kprintf("TJPGD: unload\n");
+}
+
+static void rtgui_image_jpeg_blit(struct rtgui_image* image,
+    struct rtgui_dc* dc, struct rtgui_rect* dst_rect)
+{
+    rt_uint16_t w, h, y;
+    struct rtgui_image_jpeg *jpeg;
+
+    jpeg = (struct rtgui_image_jpeg *) image->data;
+    RT_ASSERT(image != RT_NULL || dc != RT_NULL || dst_rect != RT_NULL || jpeg != RT_NULL);
+
+    do
+    {
+        /* this dc is not visible */
+        if (rtgui_dc_get_visible(dc) != RT_TRUE)
+        {
+            break;
+        }
+        jpeg->dc= dc;
+
+        /* the minimum rect */
+        if (image->w < rtgui_rect_width(*dst_rect))
+        {
+            w = image->w;
+        }
+        else
+        {
+            w = rtgui_rect_width(*dst_rect);
+        }
+        if (image->h < rtgui_rect_height(*dst_rect))
+        {
+            h = image->h;
+        }
+        else
+        {
+            h = rtgui_rect_height(*dst_rect);
+        }
+
+        if (!jpeg->is_loaded)
+        {
+            JRESULT ret;
+
+            jpeg->dst_x = dst_rect->x1;
+            jpeg->dst_y = dst_rect->y1;
+            jpeg->dst_w = w;
+            jpeg->dst_h = h;
+            ret = jd_decomp(&jpeg->tjpgd, tjpgd_out_func, jpeg->scale);
+            if (ret != JDR_OK)
+            {
+                break;
+            }
+            rt_kprintf("TJPGD: load to display\n");
+        }
+        else
+        {
+            rt_uint8_t* src = jpeg->pixels;
+            rt_uint16_t imageWidth = image->w * jpeg->byte_per_pixel;
+            rtgui_blit_line_func blit_line = RT_NULL;
+
+            if (jpeg->byte_per_pixel == hw_driver->bits_per_pixel / 8)
+            {
+                if (hw_driver->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565)
+                {
+                    blit_line = rtgui_blit_line_get_inv(hw_driver->bits_per_pixel / 8, jpeg->byte_per_pixel);
+                }
+            }
+            else
+            {
+                blit_line = rtgui_blit_line_get(hw_driver->bits_per_pixel / 8, jpeg->byte_per_pixel);
+            }
+
+            if (blit_line)
+            {
+                rt_uint16_t x;
+                rt_uint8_t temp[4];
+
+                for (y = 0; y < h; y++)
+                {
+                    for (x = 0; x < w; x++)
+                    {
+                        blit_line(temp, src, jpeg->byte_per_pixel);
+                        src += jpeg->byte_per_pixel;
+                        dc->engine->blit_line(dc,
+                            dst_rect->x1 + x, dst_rect->x1 + x,
+                            dst_rect->y1 + y,
+                            temp);
+                    }
+                }
+            }
+            else
+            {
+                for (y = 0; y < h; y++)
+                {
+                    dc->engine->blit_line(dc,
+                        dst_rect->x1, dst_rect->x1 + w - 1,
+                        dst_rect->y1 + y,
+                        src);
+                    src += imageWidth;
+                }
+            }
+        }
+    } while(0);
+}
+#endif /* defined(RTGUI_IMAGE_TJPGD) */
+/***************************************************************************//**
+ * @}
+ ******************************************************************************/

+ 49 - 7
components/rtgui/common/image_png.c

@@ -242,9 +242,16 @@ static void rtgui_image_png_unload(struct rtgui_image* image)
 
 static void rtgui_image_png_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect)
 {
+	struct rtgui_graphic_driver* hwdev = rtgui_graphic_get_device();
 	rt_uint16_t x, y, w, h;
 	rtgui_color_t* ptr;
 	struct rtgui_image_png* png;
+	int fg_maxsample;
+	int ialpha;
+	float alpha;
+	rtgui_color_t color;
+	rtgui_color_t c, bgcolor;
+	int fc[3], bc[3];
 
 	RT_ASSERT(image != RT_NULL && dc != RT_NULL && rect != RT_NULL);
 	RT_ASSERT(image->data != RT_NULL);
@@ -255,21 +262,56 @@ static void rtgui_image_png_blit(struct rtgui_image* image, struct rtgui_dc* dc,
     else w = rtgui_rect_width(*rect);
     if (image->h < rtgui_rect_height(*rect)) h = image->h;
     else h = rtgui_rect_height(*rect);
+	
+	fg_maxsample = (1 << png->info_ptr->bit_depth) - 1;
 
     if (png->pixels != RT_NULL)
     {
         ptr = (rtgui_color_t*)png->pixels;
-        /* draw each point within dc */
+        bgcolor = rtgui_color_from_565(RTGUI_DC_BC(dc));
+		bc[0] = RTGUI_RGB_R(bgcolor);
+		bc[1] = RTGUI_RGB_G(bgcolor);
+		bc[2] = RTGUI_RGB_B(bgcolor);
+		/* draw each point within dc */
         for (y = 0; y < h; y ++)
         {
             for (x = 0; x < w; x++)
             {
-                /* not alpha */
-                if ((*ptr >> 24) != 255)
-                {
-                    rtgui_dc_draw_color_point(dc, x + rect->x1, y + rect->y1, *ptr);
-                }
-
+                c = *ptr;
+				ialpha = RTGUI_RGB_A(c);
+				if(ialpha == 0)
+				{
+					/*
+					 * Foreground image is transparent hear.
+					 * If the background image is already in the frame
+					 * buffer, there is nothing to do.
+					 */
+				}
+				else if (ialpha == fg_maxsample)
+				{
+					/*
+					 * Copy foreground pixel to frame buffer.
+					 */
+					rtgui_dc_draw_color_point(dc, x + rect->x1, y + rect->y1, c);
+				}
+				else
+				{	/* output = alpha * foreground + (1-alpha) * background	*/
+					/*
+					 * Compositing is necessary.
+					 * Get floating-point alpha and its complement.
+					 * Note: alpha is always linear: gamma does not
+					 * affect it.
+					 */
+					fc[0] = RTGUI_RGB_R(c);
+					fc[1] = RTGUI_RGB_G(c);
+					fc[2] = RTGUI_RGB_B(c);
+					
+					alpha = (float) ialpha / fg_maxsample;
+					color = RTGUI_RGB( (rt_uint8_t)(fc[0]*alpha + bc[0]*(1-alpha)), 
+									   (rt_uint8_t)(fc[1]*alpha + bc[1]*(1-alpha)),
+									   (rt_uint8_t)(fc[2]*alpha + bc[2]*(1-alpha)));
+					rtgui_dc_draw_color_point(dc, x + rect->x1, y + rect->y1, color);
+				}
                 /* move to next color buffer */
                 ptr ++;
             }

+ 51 - 4
components/rtgui/common/pixel_driver.c

@@ -1,9 +1,23 @@
+/*
+ * Change Logs:
+ * Date           Author       Notes
+ * 2012-01-24     onelife      add mono color support
+ * 2012-01-24     onelife      fix a bug in _pixel_draw_raw_hline
+ */
 #include <rtgui/rtgui_system.h>
 #include <rtgui/driver.h>
 
 #define gfx_device		(rtgui_graphic_get_device()->device)
 #define gfx_device_ops 	rt_graphix_ops(gfx_device)
 
+static void _pixel_mono_set_pixel(rtgui_color_t *c, int x, int y)
+{
+	rt_uint8_t pixel;
+
+	pixel = rtgui_color_to_mono(*c);
+	gfx_device_ops->set_pixel((char*)&pixel, x, y);
+}
+
 static void _pixel_rgb565p_set_pixel(rtgui_color_t *c, int x, int y)
 {
 	rt_uint16_t pixel;
@@ -28,6 +42,14 @@ static void _pixel_rgb888_set_pixel(rtgui_color_t *c, int x, int y)
 	gfx_device_ops->set_pixel((char*)&pixel, x, y);
 }
 
+static void _pixel_mono_get_pixel(rtgui_color_t *c, int x, int y)
+{
+	rt_uint8_t pixel;
+
+	gfx_device_ops->get_pixel((char*)&pixel, x, y);
+	*c = rtgui_color_from_mono(pixel);
+}
+
 static void _pixel_rgb565p_get_pixel(rtgui_color_t *c, int x, int y)
 {
 	rt_uint16_t pixel;
@@ -52,6 +74,14 @@ static void _pixel_rgb888_get_pixel(rtgui_color_t *c, int x, int y)
 	*c = rtgui_color_from_888(pixel);
 }
 
+static void _pixel_mono_draw_hline(rtgui_color_t *c, int x1, int x2, int y)
+{
+	rt_uint8_t pixel;
+
+	pixel = rtgui_color_to_mono(*c);
+	gfx_device_ops->draw_hline((char*)&pixel, x1, x2, y);
+}
+
 static void _pixel_rgb565p_draw_hline(rtgui_color_t *c, int x1, int x2, int y)
 {
 	rt_uint16_t pixel;
@@ -76,6 +106,14 @@ static void _pixel_rgb888_draw_hline(rtgui_color_t *c, int x1, int x2, int y)
 	gfx_device_ops->draw_hline((char*)&pixel, x1, x2, y);
 }
 
+static void _pixel_mono_draw_vline(rtgui_color_t *c, int x, int y1, int y2)
+{
+	rt_uint8_t pixel;
+
+	pixel = rtgui_color_to_mono(*c);
+	gfx_device_ops->draw_vline((char*)&pixel, x, y1, y2);
+}
+
 static void _pixel_rgb565p_draw_vline(rtgui_color_t *c, int x, int y1, int y2)
 {
 	rt_uint16_t pixel;
@@ -102,13 +140,19 @@ static void _pixel_rgb888_draw_vline(rtgui_color_t *c, int x, int y1, int y2)
 
 static void _pixel_draw_raw_hline(rt_uint8_t *pixels, int x1, int x2, int y)
 {
-	if (x2 > x1)
-		gfx_device_ops->blit_line((char*)pixels, x1, y, (x2 - x1));
-	else
-		gfx_device_ops->blit_line((char*)pixels, x2, y, (x1 - x2));	
+	gfx_device_ops->blit_line((char*)pixels, x1, x2, y);
 }
 
 /* pixel device */
+const struct rtgui_graphic_driver_ops _pixel_mono_ops =
+{
+	_pixel_mono_set_pixel,
+	_pixel_mono_get_pixel,
+	_pixel_mono_draw_hline,
+	_pixel_mono_draw_vline,
+	_pixel_draw_raw_hline,
+};
+
 const struct rtgui_graphic_driver_ops _pixel_rgb565p_ops = 
 {
 	_pixel_rgb565p_set_pixel,
@@ -140,6 +184,9 @@ const struct rtgui_graphic_driver_ops *rtgui_pixel_device_get_ops(int pixel_form
 {
 	switch (pixel_format)
 	{
+    case RTGRAPHIC_PIXEL_FORMAT_MONO:
+        return &_pixel_mono_ops;
+		
 	case RTGRAPHIC_PIXEL_FORMAT_RGB565:
 		return &_pixel_rgb565_ops;
 		

+ 380 - 0
components/rtgui/common/rtgui_app.c

@@ -0,0 +1,380 @@
+/*
+ * File      : rtgui_application.c
+ * This file is part of RTGUI in RT-Thread RTOS
+ * COPYRIGHT (C) 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-01-13     Grissiom     first version(just a prototype of application API)
+ * 2012-07-07     Bernard      move the send/recv message to the rtgui_system.c
+ */
+
+#include <rtgui/rtgui_system.h>
+#include <rtgui/rtgui_app.h>
+#include <rtgui/widgets/window.h>
+
+static void _rtgui_app_constructor(struct rtgui_app *app)
+{
+	/* set event handler */
+	rtgui_object_set_event_handler(RTGUI_OBJECT(app),
+			                       rtgui_app_event_handler);
+
+	app->name           = RT_NULL;
+	/* set EXITED so we can destroy an application that just created */
+	app->state_flag     = RTGUI_APP_FLAG_EXITED;
+	app->ref_count      = 0;
+	app->exit_code      = 0;
+	app->tid            = RT_NULL;
+	app->server         = RT_NULL;
+	app->mq             = RT_NULL;
+	app->modal_object   = RT_NULL;
+	app->main_object    = RT_NULL;
+	app->on_idle        = RT_NULL;
+}
+
+static void _rtgui_app_destructor(struct rtgui_app *app)
+{
+	RT_ASSERT(app != RT_NULL);
+
+	rt_free(app->name);
+	app->name = RT_NULL;
+}
+
+DEFINE_CLASS_TYPE(application, "application",
+	RTGUI_OBJECT_TYPE,
+	_rtgui_app_constructor,
+	_rtgui_app_destructor,
+	sizeof(struct rtgui_app));
+
+struct rtgui_app* rtgui_app_create(
+        rt_thread_t tid,
+        const char *title)
+{
+	rt_thread_t srv_tid;
+	struct rtgui_app *app;
+	struct rtgui_event_application event;
+
+	RT_ASSERT(tid != RT_NULL);
+	RT_ASSERT(title != RT_NULL);
+
+	/* create application */
+	app = RTGUI_APP(rtgui_object_create(RTGUI_APP_TYPE));
+	if (app == RT_NULL)
+		return RT_NULL;
+
+	/* one thread only can create one rtgui application */
+	RT_ASSERT(tid->user_data == 0);
+	app->tid = tid;
+	/* set user thread */
+	tid->user_data = (rt_uint32_t)app;
+
+	app->mq = rt_mq_create("rtgui", sizeof(union rtgui_event_generic), 32, RT_IPC_FLAG_FIFO);
+	if (app->mq == RT_NULL)
+	{
+		rt_kprintf("create msgq failed.\n");
+		goto __mq_err;
+	}
+
+	/* set application title */
+	app->name = (unsigned char*)rt_strdup((char*)title);
+	if (app->name == RT_NULL)
+		goto __err;
+
+	/* send a message to notify rtgui server */
+	srv_tid = rtgui_get_server();
+	if (srv_tid == RT_NULL)
+	{
+		rt_kprintf("gui server is not running.\n");
+		goto __err;
+	}
+
+	/* create the rtgui server application */
+	if (srv_tid == rt_thread_self())
+		return app;
+
+	RTGUI_EVENT_APP_CREATE_INIT(&event);
+	event.app = app;
+
+	/* notify rtgui server to one application has been created */
+	if (rtgui_send_sync(srv_tid, RTGUI_EVENT(&event), sizeof(event)) == RT_EOK)
+	{
+		return app;
+	}
+
+__err:
+__mq_err:
+	rtgui_object_destroy(RTGUI_OBJECT(app));
+	tid->user_data = 0;
+	return RT_NULL;
+}
+
+#define _rtgui_application_check(app)			\
+	do {										\
+		RT_ASSERT(app != RT_NULL);				\
+		RT_ASSERT(app->tid != RT_NULL);			\
+		RT_ASSERT(app->tid->user_data != 0);	\
+		RT_ASSERT(app->mq != RT_NULL);			\
+	} while (0)
+
+void rtgui_app_destroy(struct rtgui_app *app)
+{
+	rt_thread_t srv_tid;
+    _rtgui_application_check(app);
+
+	if (!(app->state_flag & RTGUI_APP_FLAG_EXITED))
+	{
+		rt_kprintf("cannot destroy a running application: %s.\n",
+				   app->name);
+		return;
+	}
+
+	/* send a message to notify rtgui server */
+	srv_tid = rtgui_get_server();
+	if (srv_tid != rt_thread_self()) /* must not the server thread */
+	{
+		struct rtgui_event_application event;
+		RTGUI_EVENT_APP_DESTROY_INIT(&event);
+		event.app = app;
+
+		if (rtgui_send_sync(srv_tid, RTGUI_EVENT(&event), sizeof(event)) != RT_EOK)
+		{
+			rt_kprintf("destroy an application in server failed\n");
+			return ;
+		}
+	}
+
+	app->tid->user_data = 0;
+	rt_mq_delete(app->mq);
+	rtgui_object_destroy(RTGUI_OBJECT(app));
+}
+
+struct rtgui_app* rtgui_app_self(void)
+{
+	struct rtgui_app *app;
+	rt_thread_t self;
+
+	/* get current thread */
+	self = rt_thread_self();
+	app = (struct rtgui_app*)(self->user_data);
+
+	return app;
+}
+
+void rtgui_app_set_onidle(rtgui_idle_func_t onidle)
+{
+	struct rtgui_app *app;
+
+	app = rtgui_app_self();
+	if (app != RT_NULL)
+		app->on_idle = onidle;
+}
+
+rtgui_idle_func_t rtgui_app_get_onidle(void)
+{
+	struct rtgui_app *app;
+
+	app = rtgui_app_self();
+	if (app != RT_NULL)
+		return app->on_idle;
+	else
+		return RT_NULL;
+}
+
+rt_inline rt_bool_t _rtgui_application_dest_handle(
+		struct rtgui_app *app,
+		struct rtgui_event *event)
+{
+	struct rtgui_event_win* wevent = (struct rtgui_event_win*)event;
+
+	struct rtgui_object* dest_object = RTGUI_OBJECT(wevent->wid);
+
+	if (dest_object != RT_NULL)
+	{
+		if (dest_object->event_handler != RT_NULL)
+			return dest_object->event_handler(RTGUI_OBJECT(dest_object), event);
+		else
+			return RT_FALSE;
+	}
+	else
+	{
+		rt_kprintf("RTGUI ERROR:server sent a event(%d) without wid\n", event->type);
+		return RT_FALSE;
+	}
+}
+
+rt_bool_t rtgui_app_event_handler(struct rtgui_object* object, rtgui_event_t* event)
+{
+	struct rtgui_app* app;
+
+	RT_ASSERT(object != RT_NULL);
+	RT_ASSERT(event != RT_NULL);
+
+	app = RTGUI_APP(object);
+
+	switch (event->type)
+	{
+	case RTGUI_EVENT_PAINT:
+	case RTGUI_EVENT_CLIP_INFO:
+	case RTGUI_EVENT_WIN_ACTIVATE:
+	case RTGUI_EVENT_WIN_DEACTIVATE:
+	case RTGUI_EVENT_WIN_CLOSE:
+	case RTGUI_EVENT_WIN_MOVE:
+	case RTGUI_EVENT_KBD:
+		_rtgui_application_dest_handle(app, event);
+		break;
+
+	case RTGUI_EVENT_APP_ACTIVATE:
+		if (app->main_object != RT_NULL)
+		{
+			rtgui_win_activate(RTGUI_WIN(app->main_object));
+			if (app->modal_object != RT_NULL)
+				rtgui_win_activate(RTGUI_WIN(app->modal_object));
+		}
+		else if (app->modal_object != RT_NULL)
+		{
+			rtgui_win_activate(RTGUI_WIN(app->modal_object));
+		}
+		break;
+
+	case RTGUI_EVENT_MOUSE_BUTTON:
+	case RTGUI_EVENT_MOUSE_MOTION:
+		{
+			struct rtgui_event_win* wevent = (struct rtgui_event_win*)event;
+			struct rtgui_object* dest_object = RTGUI_OBJECT(wevent->wid);
+
+			// FIXME: let application determine the dest_wiget but not in sever
+			// so we can combine this handler with above one
+			if (app->modal_object != RT_NULL &&
+				dest_object != app->modal_object)
+			{
+//				rt_kprintf("discard event %s that is not sent to modal object\n",
+//						   event_string[event->type]);
+			}
+			else
+			{
+				_rtgui_application_dest_handle(app, event);
+			}
+		}
+		break;
+
+	case RTGUI_EVENT_TIMER:
+		{
+			struct rtgui_timer* timer;
+			struct rtgui_event_timer* etimer = (struct rtgui_event_timer*) event;
+
+			timer = etimer->timer;
+			if (timer->timeout != RT_NULL)
+			{
+				/* call timeout function */
+				timer->timeout(timer, timer->user_data);
+			}
+		}
+		break;
+
+        case RTGUI_EVENT_COMMAND:
+        {
+            struct rtgui_event_command *ecmd = (struct rtgui_event_command*)event;
+
+            if (ecmd->wid != RT_NULL)
+                    return _rtgui_application_dest_handle(app, event);
+        }
+
+	default:
+		return rtgui_object_event_handler(object, event);
+	}
+
+	return RT_TRUE;
+}
+
+rt_inline void _rtgui_application_event_loop(struct rtgui_app *app)
+{
+	rt_err_t result;
+	rt_uint16_t current_ref;
+	struct rtgui_event *event;
+
+	_rtgui_application_check(app);
+
+	/* point to event buffer */
+	event = (struct rtgui_event*)app->event_buffer;
+
+	current_ref = ++app->ref_count;
+
+	while (current_ref <= app->ref_count)
+	{
+		RT_ASSERT(current_ref == app->ref_count);
+
+		if (app->on_idle != RT_NULL)
+		{
+			result = rtgui_recv_nosuspend(event, sizeof(union rtgui_event_generic));
+			if (result == RT_EOK)
+				RTGUI_OBJECT(app)->event_handler(RTGUI_OBJECT(app), event);
+			else if (result == -RT_ETIMEOUT)
+				app->on_idle(RTGUI_OBJECT(app), RT_NULL);
+		}
+		else
+		{
+			result = rtgui_recv(event, sizeof(union rtgui_event_generic));
+			if (result == RT_EOK)
+				RTGUI_OBJECT(app)->event_handler(RTGUI_OBJECT(app), event);
+		}
+	}
+}
+
+rt_base_t rtgui_app_run(struct rtgui_app *app)
+{
+	_rtgui_application_check(app);
+
+	app->state_flag &= ~RTGUI_APP_FLAG_EXITED;
+
+	_rtgui_application_event_loop(app);
+
+	if (app->ref_count == 0)
+		app->state_flag |= RTGUI_APP_FLAG_EXITED;
+
+	return app->exit_code;
+}
+
+void rtgui_app_exit(struct rtgui_app* app, rt_uint16_t code)
+{
+	--app->ref_count;
+	app->exit_code = code;
+}
+
+/**
+ * set this application as window manager
+ */
+rt_err_t rtgui_app_set_as_wm(void)
+{
+	rt_thread_t srv_tid;
+	struct rtgui_event_set_wm event;
+	struct rtgui_app* app;
+
+	srv_tid = rtgui_get_server();
+	app = rtgui_app_self();
+	if (app != RT_NULL && srv_tid != RT_NULL)
+	{
+		/* notify rtgui server, this is a window manager */
+		RTGUI_EVENT_SET_WM_INIT(&event);
+		event.app = app;
+
+		rtgui_send_sync(srv_tid, RTGUI_EVENT(&event), sizeof(event));
+		return RT_EOK;
+	}
+
+	return RT_ERROR;
+}
+
+void rtgui_app_set_main_win(struct rtgui_win* win)
+{
+	struct rtgui_app *app;
+
+	app = rtgui_app_self();
+	if (app != RT_NULL)
+	{
+		app->main_object = RTGUI_OBJECT(win);
+	}
+}

+ 416 - 3
components/rtgui/common/rtgui_system.c

@@ -16,7 +16,7 @@
 #include <rtgui/image.h>
 #include <rtgui/font.h>
 #include <rtgui/event.h>
-#include <rtgui/rtgui_application.h>
+#include <rtgui/rtgui_app.h>
 #include <rtgui/rtgui_server.h>
 #include <rtgui/rtgui_system.h>
 #include <rtgui/widgets/window.h>
@@ -26,7 +26,7 @@
 #define RTGUI_MEM_TRACE
 #endif
 
-void rtgui_system_server_init(void)
+void rtgui_system_server_init()
 {
 	/* init image */
 	rtgui_system_image_init();
@@ -59,7 +59,7 @@ static void rtgui_time_out(void* parameter)
 
 	event.timer = timer;
 
-	rtgui_application_send(timer->tid, &(event.parent), sizeof(rtgui_event_timer_t));
+	rtgui_send(timer->tid, &(event.parent), sizeof(rtgui_event_timer_t));
 }
 
 rtgui_timer_t* rtgui_timer_create(rt_int32_t time, rt_int32_t flag, rtgui_timeout_func timeout, void* parameter)
@@ -285,3 +285,416 @@ void rtgui_free(void* ptr)
 	rt_free(ptr);
 }
 
+#if defined(RTGUI_MEM_TRACE) && defined(RT_USING_FINSH)
+#include <finsh.h>
+void list_mem(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);
+#endif
+
+/************************************************************************/
+/* RTGUI Event Dump                                                     */
+/************************************************************************/
+
+#ifdef _WIN32
+#define RTGUI_EVENT_DEBUG
+#endif
+
+#ifdef RTGUI_EVENT_DEBUG
+const char *event_string[] =
+{
+	/* application event */
+	"APP_CREATE", 			/* create an application */
+	"APP_DESTROY", 			/* destroy an application */
+	"APP_ACTIVATE",			/* activate an application */
+
+	/* window event */
+	"WIN_CREATE",			/* create a window 	*/
+	"WIN_DESTROY",			/* destroy a window 	*/
+	"WIN_SHOW",				/* show a window 		*/
+	"WIN_HIDE",				/* hide a window 		*/
+	"WIN_ACTIVATE", 		/* activate a window 	*/
+	"WIN_DEACTIVATE",		/* deactivate a window 	*/
+	"WIN_CLOSE",			/* close a window 		*/
+	"WIN_MOVE",				/* move a window 		*/
+	"WIN_RESIZE", 			/* resize a window 		*/
+	"WIN_MODAL_ENTER", 			/* a window modals		*/
+
+	"SET_WM", 				/* set window manager	*/
+
+	"UPDATE_BEGIN",			/* begin of update rect */
+	"UPDATE_END",			/* end of update rect	*/
+	"MONITOR_ADD",			/* add a monitor rect 	*/
+	"MONITOR_REMOVE", 		/* remove a monitor rect*/
+	"SHOW",				    /* the widget is going to be shown */
+	"HIDE",				    /* the widget is going to be hidden */
+	"PAINT",				/* paint on screen 		*/
+	"TIMER",				/* timer 				*/
+
+	/* clip rect information */
+	"CLIP_INFO",			/* clip rect info		*/
+
+	/* mouse and keyboard event */
+	"MOUSE_MOTION",			/* mouse motion */
+	"MOUSE_BUTTON",			/* mouse button info 	*/
+	"KBD",					/* keyboard info		*/
+
+	/* user command event */
+	"COMMAND",				/* user command 		*/
+
+	/* request's status event */
+	"STATUS",				/* request result 		*/
+	"SCROLLED",           	/* scroll bar scrolled  */
+	"RESIZE",				/* widget resize 		*/
+};
+
+#define DBG_MSG(x)	rt_kprintf x
+
+static void rtgui_event_dump(rt_thread_t tid, rtgui_event_t* event)
+{
+	char* sender = "(unknown)";
+
+	if ((event->type == RTGUI_EVENT_TIMER) ||
+		(event->type == RTGUI_EVENT_UPDATE_BEGIN) ||
+		(event->type == RTGUI_EVENT_MOUSE_MOTION) ||
+		(event->type == RTGUI_EVENT_UPDATE_END))
+	{
+		/* don't dump timer event */
+		return ;
+	}
+
+	if (event->sender != RT_NULL)
+		sender = event->sender->name;
+
+	rt_kprintf("%s -- %s --> %s ", sender, event_string[event->type], tid->name);
+	switch (event->type)
+	{
+	case RTGUI_EVENT_APP_CREATE:
+	case RTGUI_EVENT_APP_DESTROY:
+	case RTGUI_EVENT_APP_ACTIVATE:
+		{
+			struct rtgui_event_application *eapp = (struct rtgui_event_application *)event;
+
+			rt_kprintf("app: %s", eapp->app->name);
+		}
+		break;
+		
+	case RTGUI_EVENT_PAINT:
+		{
+			struct rtgui_event_paint *paint = (struct rtgui_event_paint *)event;
+
+			if(paint->wid != RT_NULL)
+				rt_kprintf("win: %s", paint->wid->title);
+		}
+		break;
+
+	case RTGUI_EVENT_KBD:
+		{
+			struct rtgui_event_kbd *ekbd = (struct rtgui_event_kbd*) event;
+			if (ekbd->wid != RT_NULL)
+				rt_kprintf("win: %s", ekbd->wid->title);
+			if (RTGUI_KBD_IS_UP(ekbd)) rt_kprintf(", up");
+			else rt_kprintf(", down");
+		}
+		break;
+
+	case RTGUI_EVENT_CLIP_INFO:
+		{
+			struct rtgui_event_clip_info *info = (struct rtgui_event_clip_info *)event;
+
+			if(info->wid != RT_NULL)
+				rt_kprintf("win: %s", info->wid->title);
+		}
+		break;
+
+	case RTGUI_EVENT_WIN_CREATE:
+		{
+			struct rtgui_event_win_create *create = (struct rtgui_event_win_create*)event;
+
+			rt_kprintf(" win: %s at (x1:%d, y1:%d, x2:%d, y2:%d), addr: %p",
+#ifdef RTGUI_USING_SMALL_SIZE
+				create->wid->title,
+				RTGUI_WIDGET(create->wid)->extent.x1,
+				RTGUI_WIDGET(create->wid)->extent.y1,
+				RTGUI_WIDGET(create->wid)->extent.x2,
+				RTGUI_WIDGET(create->wid)->extent.y2,
+#else
+				create->title,
+				create->extent.x1,
+				create->extent.y1,
+				create->extent.x2,
+				create->extent.y2,
+#endif
+				create->wid
+                );
+		}
+		break;
+
+	case RTGUI_EVENT_UPDATE_END:
+		{
+			struct rtgui_event_update_end* update_end = (struct rtgui_event_update_end*)event;
+			rt_kprintf("(x:%d, y1:%d, x2:%d, y2:%d)", update_end->rect.x1,
+				update_end->rect.y1,
+				update_end->rect.x2,
+				update_end->rect.y2);
+		}
+		break;
+
+	case RTGUI_EVENT_WIN_ACTIVATE:
+	case RTGUI_EVENT_WIN_DEACTIVATE:
+	case RTGUI_EVENT_WIN_SHOW:
+	case RTGUI_EVENT_WIN_MODAL_ENTER:
+		{
+			struct rtgui_event_win *win = (struct rtgui_event_win *)event;
+
+			if(win->wid != RT_NULL)
+				rt_kprintf("win: %s", win->wid->title);
+		}
+		break;
+
+	case RTGUI_EVENT_WIN_MOVE:
+		{
+			struct rtgui_event_win_move *win = (struct rtgui_event_win_move *)event;
+
+			if(win->wid != RT_NULL)
+			{
+				rt_kprintf("win: %s", win->wid->title);
+				rt_kprintf(" to (x:%d, y:%d)", win->x, win->y);
+			}
+		}
+		break;
+
+	case RTGUI_EVENT_WIN_RESIZE:
+		{
+			struct rtgui_event_win_resize* win = (struct rtgui_event_win_resize *)event;
+
+			if (win->wid != RT_NULL)
+			{
+				rt_kprintf("win: %s, rect(x1:%d, y1:%d, x2:%d, y2:%d)", win->wid->title,
+					RTGUI_WIDGET(win->wid)->extent.x1,
+					RTGUI_WIDGET(win->wid)->extent.y1,
+					RTGUI_WIDGET(win->wid)->extent.x2,
+					RTGUI_WIDGET(win->wid)->extent.y2);
+			}
+		}
+		break;
+
+	case RTGUI_EVENT_MOUSE_BUTTON:
+	case RTGUI_EVENT_MOUSE_MOTION:
+		{
+			struct rtgui_event_mouse *mouse = (struct rtgui_event_mouse*)event;
+
+			if (mouse->button & RTGUI_MOUSE_BUTTON_LEFT) rt_kprintf("left ");
+			else rt_kprintf("right ");
+
+			if (mouse->button & RTGUI_MOUSE_BUTTON_DOWN) rt_kprintf("down ");
+			else rt_kprintf("up ");
+
+			if (mouse->wid != RT_NULL)
+				rt_kprintf("win: %s at (%d, %d)", mouse->wid->title,
+				mouse->x, mouse->y);
+			else
+				rt_kprintf("(%d, %d)", mouse->x, mouse->y);
+		}
+		break;
+
+	case RTGUI_EVENT_MONITOR_ADD:
+		{
+			struct rtgui_event_monitor *monitor = (struct rtgui_event_monitor*)event;
+			if (monitor->wid != RT_NULL)
+			{
+				rt_kprintf("win: %s, the rect is:(%d, %d) - (%d, %d)", monitor->wid->title,
+					monitor->rect.x1, monitor->rect.y1,
+					monitor->rect.x2, monitor->rect.y2);
+			}
+		}
+		break;
+	}
+
+	rt_kprintf("\n");
+}
+#else
+#define DBG_MSG(x)
+#define rtgui_event_dump(tid, event)
+#endif
+
+/************************************************************************/
+/* RTGUI IPC APIs                                                       */
+/************************************************************************/
+rt_err_t rtgui_send(rt_thread_t tid, rtgui_event_t* event, rt_size_t event_size)
+{
+	rt_err_t result;
+	struct rtgui_app *app;
+
+	RT_ASSERT(tid != RT_NULL);
+	RT_ASSERT(event != RT_NULL);
+	RT_ASSERT(event_size != 0);
+
+	rtgui_event_dump(tid, event);
+
+	/* find struct rtgui_application */
+	app = (struct rtgui_app*) (tid->user_data);
+	if (app == RT_NULL)
+		return -RT_ERROR;
+
+	result = rt_mq_send(app->mq, event, event_size);
+	if (result != RT_EOK)
+	{
+		if (event->type != RTGUI_EVENT_TIMER)
+			rt_kprintf("send event to %s failed\n", app->tid->name);
+	}
+
+	return result;
+}
+
+rt_err_t rtgui_send_urgent(rt_thread_t tid, rtgui_event_t* event, rt_size_t event_size)
+{
+	rt_err_t result;
+	struct rtgui_app *app;
+
+	RT_ASSERT(tid != RT_NULL);
+	RT_ASSERT(event != RT_NULL);
+	RT_ASSERT(event_size != 0);
+
+	rtgui_event_dump(tid, event);
+
+	/* find rtgui_application */
+	app = (struct rtgui_app*) (tid->user_data);
+	if (app == RT_NULL)
+		return -RT_ERROR;
+
+	result = rt_mq_urgent(app->mq, event, event_size);
+	if (result != RT_EOK)
+		rt_kprintf("send ergent event failed\n");
+
+	return result;
+}
+
+rt_err_t rtgui_send_sync(rt_thread_t tid, rtgui_event_t* event, rt_size_t event_size)
+{
+	rt_err_t r;
+	struct rtgui_app *app;
+	rt_int32_t ack_buffer, ack_status;
+	struct rt_mailbox ack_mb;
+
+	RT_ASSERT(tid != RT_NULL);
+	RT_ASSERT(event != RT_NULL);
+	RT_ASSERT(event_size != 0);
+
+	rtgui_event_dump(tid, event);
+
+	/* init ack mailbox */
+	r = rt_mb_init(&ack_mb, "ack", &ack_buffer, 1, 0);
+	if (r!= RT_EOK)
+		goto __return;
+
+	app = (struct rtgui_app*) (tid->user_data);
+	if (app == RT_NULL)
+	{
+		r = -RT_ERROR;
+		goto __return;
+	}
+
+	event->ack = &ack_mb;
+	r = rt_mq_send(app->mq, event, event_size);
+	if (r != RT_EOK)
+	{
+		rt_kprintf("send sync event failed\n");
+		goto __return;
+	}
+
+	r = rt_mb_recv(&ack_mb, (rt_uint32_t*)&ack_status, RT_WAITING_FOREVER);
+	if (r!= RT_EOK)
+		goto __return;
+
+	if (ack_status != RTGUI_STATUS_OK)
+		r = -RT_ERROR;
+	else
+		r = RT_EOK;
+
+__return:
+	/* fini ack mailbox */
+	rt_mb_detach(&ack_mb);
+	return r;
+}
+
+rt_err_t rtgui_ack(rtgui_event_t* event, rt_int32_t status)
+{
+	RT_ASSERT(event != RT_NULL);
+	RT_ASSERT(event->ack != RT_NULL);
+
+	rt_mb_send(event->ack, status);
+
+	return RT_EOK;
+}
+
+rt_err_t rtgui_recv(rtgui_event_t* event, rt_size_t event_size)
+{
+	struct rtgui_app* app;
+	rt_err_t r;
+
+	RT_ASSERT(event != RT_NULL);
+	RT_ASSERT(event_size != 0);
+
+	app = (struct rtgui_app*) (rt_thread_self()->user_data);
+	if (app == RT_NULL)
+		return -RT_ERROR;
+
+	r = rt_mq_recv(app->mq, event, event_size, RT_WAITING_FOREVER);
+
+	return r;
+}
+
+rt_err_t rtgui_recv_nosuspend(rtgui_event_t* event, rt_size_t event_size)
+{
+	struct rtgui_app *app;
+	rt_err_t r;
+
+	RT_ASSERT(event != RT_NULL);
+	RT_ASSERT(event != 0);
+
+	app = (struct rtgui_app*) (rt_thread_self()->user_data);
+	if (app == RT_NULL)
+		return -RT_ERROR;
+
+	r = rt_mq_recv(app->mq, event, event_size, 0);
+
+	return r;
+}
+
+rt_err_t rtgui_recv_filter(rt_uint32_t type, rtgui_event_t* event, rt_size_t event_size)
+{
+	struct rtgui_app *app;
+
+	RT_ASSERT(event != RT_NULL);
+	RT_ASSERT(event_size != 0);
+
+	app = (struct rtgui_app*) (rt_thread_self()->user_data);
+	if (app == RT_NULL)
+		return -RT_ERROR;
+
+	while (rt_mq_recv(app->mq, event, event_size, RT_WAITING_FOREVER) == RT_EOK)
+	{
+		if (event->type == type)
+		{
+			return RT_EOK;
+		}
+		else
+		{
+			if (RTGUI_OBJECT(app)->event_handler != RT_NULL)
+			{
+				RTGUI_OBJECT(app)->event_handler(RTGUI_OBJECT(app), event);
+			}
+		}
+	}
+
+	return -RT_ERROR;
+}
+
+rt_thread_t rtgui_get_server(void)
+{
+	return rt_thread_find("rtgui");
+}
+

+ 2 - 0
components/rtgui/doc/attention.txt

@@ -14,3 +14,5 @@ slider 处理上下键,上面的值小,下面的值大。
 
 6, view 不再提供 show 方法。如果想单独显示控件,请用 window 包含之。
 
+7, 若窗口在销毁(destroy)时没有关闭,则 RTGUI 会先关闭之。也会调用 on_close 函数
+但是此函数的返回值会被忽略。

+ 2 - 2
components/rtgui/doc/road_map.txt

@@ -46,9 +46,9 @@ mq 的模式。rtgui_application 记录当前依附的 panel,和 panel 的 ext
 10, 在 widget 中添加 on_show 和 on_hide 事件回调函数。(Done)
 
 11, 添加 EVENT_WIN_MODAL_ENTER 和 EVENT_WIN_MODAL_EXIT 事件,用来通知窗口管理器
-(topwin)一个窗口进入模态。窗口管理器根据这个进行相应的设置。
+(topwin)一个窗口进入模态。窗口管理器根据这个进行相应的设置。(Done)
 
-12, rtgui_filelist_view 不必继承自 container。
+12, rtgui_filelist_view 不必继承自 container。(Deprecated)
 
 13, 添加 desktop window 支持。(Done)
     概念与名词:

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

@@ -5,5 +5,6 @@
 
 typedef void (*rtgui_blit_line_func)(rt_uint8_t* dst, rt_uint8_t* src, int line);
 rtgui_blit_line_func rtgui_blit_line_get(int dst_bpp, int src_bpp);
+rtgui_blit_line_func rtgui_blit_line_get_inv(int dst_bpp, int src_bpp);
 
 #endif

+ 25 - 0
components/rtgui/include/rtgui/color.h

@@ -10,6 +10,7 @@
  * Change Logs:
  * Date           Author       Notes
  * 2009-10-16     Bernard      first version
+ * 2012-01-24     onelife      add mono color support
  */
 #ifndef __RTGUI_COLOR_H__
 #define __RTGUI_COLOR_H__
@@ -45,6 +46,30 @@ extern const rtgui_color_t light_grey;
  * BBBB BBBB GGGG GGGG RRRR RRRR
  */
 
+/* convert rtgui color to mono */
+rt_inline rt_uint8_t rtgui_color_to_mono(rtgui_color_t c)
+{
+	rt_uint8_t pixel;
+
+	pixel = (RTGUI_RGB_R(c) | RTGUI_RGB_G(c) | RTGUI_RGB_B(c)) ? 0x01 : 0x00;
+	return pixel;
+}
+
+rt_inline rtgui_color_t rtgui_color_from_mono(rt_uint8_t pixel)
+{
+	rtgui_color_t color;
+
+	if (pixel)
+	{
+    	color = white;
+	}
+    else
+    {
+        color = black;
+    }
+	return color;
+}
+
 /* convert rtgui color to BBBBBGGGGGGRRRRR */
 rt_inline rt_uint16_t rtgui_color_to_565(rtgui_color_t c)
 {

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

@@ -54,6 +54,7 @@ struct rtgui_graphic_driver* rtgui_graphic_driver_get_default(void);
 void rtgui_graphic_driver_get_rect(const struct rtgui_graphic_driver *driver, rtgui_rect_t *rect);
 void rtgui_graphic_driver_screen_update(const struct rtgui_graphic_driver* driver, rtgui_rect_t *rect);
 rt_uint8_t* rtgui_graphic_driver_get_framebuffer(const struct rtgui_graphic_driver* driver);
+rt_uint8_t* rtgui_graphic_driver_get_default_framebuffer(void);
 
 rt_err_t rtgui_graphic_set_device(rt_device_t device);
 

+ 47 - 0
components/rtgui/include/rtgui/event.h

@@ -21,6 +21,11 @@
  * rtgui_event_generic */
 enum _rtgui_event_type
 {
+	/* applications event */
+	RTGUI_EVENT_APP_CREATE,			   /* create an application */
+	RTGUI_EVENT_APP_DESTROY,		   /* destroy an application */
+	RTGUI_EVENT_APP_ACTIVATE, 		   /* activate an application */
+
 	/* window event */
 	RTGUI_EVENT_WIN_CREATE,            /* create a window       */
 	RTGUI_EVENT_WIN_DESTROY,           /* destroy a window      */
@@ -43,6 +48,8 @@ enum _rtgui_event_type
 	RTGUI_EVENT_UPDATE_END,            /* update a rect         */
 	RTGUI_EVENT_MONITOR_ADD,           /* add a monitor rect    */
 	RTGUI_EVENT_MONITOR_REMOVE,        /* remove a monitor rect */
+	RTGUI_EVENT_SHOW,                  /* the widget is going to be shown */
+	RTGUI_EVENT_HIDE,                  /* the widget is going to be hidden */
 	RTGUI_EVENT_PAINT,                 /* paint on screen       */
 	RTGUI_EVENT_TIMER,                 /* timer                 */
 
@@ -94,6 +101,24 @@ typedef struct rtgui_event rtgui_event_t;
 	(e)->ack = RT_NULL;					\
 } while (0)
 
+/*
+ * RTGUI Application Event
+ */
+struct rtgui_event_application
+{
+	struct rtgui_event parent;
+
+	struct rtgui_app* app;
+};
+
+/* gui application init */
+#define RTGUI_EVENT_APP_CREATE_INIT(e)      RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_APP_CREATE)
+#define RTGUI_EVENT_APP_DESTROY_INIT(e)      RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_APP_DESTROY)
+#define RTGUI_EVENT_APP_ACTIVATE_INIT(e)      RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_APP_ACTIVATE)
+
+/*
+ * RTGUI Window Event
+ */
 #define _RTGUI_EVENT_WIN_ELEMENTS \
 	struct rtgui_event parent; \
 	struct rtgui_win *wid;
@@ -151,6 +176,16 @@ struct rtgui_event_win_resize
 #define RTGUI_EVENT_WIN_RESIZE_INIT(e)      RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_WIN_RESIZE)
 #define RTGUI_EVENT_WIN_MODAL_ENTER_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_WIN_MODAL_ENTER)
 
+/*
+ * RTGUI set window manager
+ */
+struct rtgui_event_set_wm
+{
+	struct rtgui_event parent;
+	struct rtgui_app *app;
+};
+#define RTGUI_EVENT_SET_WM_INIT(e)			RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_SET_WM);
+
 /*
  * RTGUI Other Event
  */
@@ -214,6 +249,12 @@ struct rtgui_event_clip_info
 #define RTGUI_EVENT_PAINT_INIT(e)			RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_PAINT)
 #define RTGUI_EVENT_TIMER_INIT(e)			RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_TIMER)
 
+#define rtgui_event_show rtgui_event
+#define rtgui_event_hide rtgui_event
+
+#define RTGUI_EVENT_SHOW_INIT(e)			RTGUI_EVENT_INIT((e), RTGUI_EVENT_SHOW)
+#define RTGUI_EVENT_HIDE_INIT(e)			RTGUI_EVENT_INIT((e), RTGUI_EVENT_HIDE)
+
 /*
  * RTGUI Mouse and Keyboard Event
  */
@@ -325,6 +366,12 @@ struct rtgui_event_resize
 union rtgui_event_generic
 {
 	struct rtgui_event base;
+
+	struct rtgui_event_application app_create;
+	struct rtgui_event_application app_destroy;
+	struct rtgui_event_application app_activate;
+
+	struct rtgui_event_set_wm set_wm;
 	struct rtgui_event_win win_base;
 	struct rtgui_event_win_create win_create;
 	struct rtgui_event_win_move win_move;

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

@@ -30,7 +30,7 @@ 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* widget, struct rtgui_event* event);
+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);
 
 struct rtgui_point

+ 88 - 0
components/rtgui/include/rtgui/rtgui_app.h

@@ -0,0 +1,88 @@
+/*
+ * File      : rtgui_application.h
+ * This file is part of RTGUI in RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2012-01-13     Grissiom     first version
+ */
+#ifndef __RTGUI_APPLICATION_H__
+#define __RTGUI_APPLICATION_H__
+
+#include <rtthread.h>
+#include <rtgui/rtgui.h>
+#include <rtgui/event.h>
+#include <rtgui/rtgui_system.h>
+
+DECLARE_CLASS_TYPE(application);
+
+/** Gets the type of a application */
+#define RTGUI_APP_TYPE       (RTGUI_TYPE(application))
+/** Casts the object to an rtgui_workbench */
+#define RTGUI_APP(obj)       (RTGUI_OBJECT_CAST((obj), RTGUI_APP_TYPE, struct rtgui_app))
+/** Checks if the object is an rtgui_workbench */
+#define RTGUI_IS_APP(obj)    (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_APP_TYPE))
+
+enum rtgui_app_flag
+{
+	RTGUI_APP_FLAG_EXITED  = 0x04,
+	RTGUI_APP_FLAG_SHOWN   = 0x08
+};
+
+typedef void (*rtgui_idle_func_t)(struct rtgui_object* obj, struct rtgui_event *event);
+
+struct rtgui_app
+{
+	struct rtgui_object parent;
+
+	/* application name */
+	unsigned char *name;
+	struct rtgui_image* icon;
+
+	enum rtgui_app_flag state_flag;
+
+	rt_uint16_t ref_count;
+	rt_uint16_t exit_code;
+
+	/* the thread id */
+	rt_thread_t tid;
+	/* the RTGUI server id */
+    rt_thread_t server;
+
+	/* the message queue of thread */
+	rt_mq_t mq;
+	/* event buffer */
+	rt_uint8_t event_buffer[sizeof(union rtgui_event_generic)];
+
+	/* if not RT_NULL, the application is in modal state by modal_object. If is
+	 * RT_NULL, nothing modal windows. */
+	struct rtgui_object *modal_object;
+	struct rtgui_object *main_object;
+
+	/* on idle event handler */
+	rtgui_idle_func_t on_idle;
+};
+
+/**
+ * create an application named @myname on thread @param tid
+ */
+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_base_t rtgui_app_run(struct rtgui_app *app);
+void rtgui_app_exit(struct rtgui_app *app, rt_uint16_t code);
+
+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);
+
+rt_err_t rtgui_app_set_as_wm(void);
+void rtgui_app_set_main_win(struct rtgui_win* win);
+
+#endif /* end of include guard: RTGUI_APPLICATION_H */

+ 0 - 99
components/rtgui/include/rtgui/rtgui_application.h

@@ -1,99 +0,0 @@
-/*
- * File      : rtgui_application.h
- * This file is part of RTGUI in RT-Thread RTOS
- * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date           Author       Notes
- * 2012-01-13     Grissiom     first version
- */
-#ifndef __RTGUI_APPLICATION_H__
-#define __RTGUI_APPLICATION_H__
-
-#include <rtthread.h>
-#include <rtgui/rtgui.h>
-#include <rtgui/event.h>
-#include <rtgui/rtgui_system.h>
-
-DECLARE_CLASS_TYPE(application);
-
-/** Gets the type of a application */
-#define RTGUI_APPLICATION_TYPE       (RTGUI_TYPE(application))
-/** Casts the object to an rtgui_workbench */
-#define RTGUI_APPLICATION(obj)       (RTGUI_OBJECT_CAST((obj), RTGUI_APPLICATION_TYPE, struct rtgui_application))
-/** Checks if the object is an rtgui_workbench */
-#define RTGUI_IS_APPLICATION(obj)    (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_APPLICATION_TYPE))
-
-enum rtgui_application_flag
-{
-	RTGUI_APPLICATION_FLAG_EXITED  = 0x04,
-	RTGUI_APPLICATION_FLAG_SHOWN   = 0x08
-};
-
-typedef void (*rtgui_idle_func)(struct rtgui_object* obj, struct rtgui_event *event);
-
-struct rtgui_application
-{
-	struct rtgui_object parent;
-
-	/* application name */
-	unsigned char *name;
-
-	enum rtgui_application_flag state_flag;
-
-	rt_uint16_t ref_count;
-	rt_uint16_t exit_code;
-
-	/* the thread id */
-	rt_thread_t tid;
-    rt_thread_t server;
-
-	/* the message queue of thread */
-	rt_mq_t mq;
-	/* event buffer */
-	rt_uint8_t event_buffer[sizeof(union rtgui_event_generic)];
-
-	/* if not RT_NULL, the application is modaled by modal_object. If is
-	 * RT_NULL, nothing modals. */
-	struct rtgui_object *modal_object;
-
-	/* on idle event handler */
-	rtgui_idle_func on_idle;
-};
-
-/**
- * create an application named @myname on thread @param tid
- */
-struct rtgui_application* rtgui_application_create(
-        rt_thread_t tid,
-        const char *myname);
-void rtgui_application_destroy(struct rtgui_application *app);
-rt_err_t rtgui_application_show(struct rtgui_application *app);
-rt_err_t rtgui_application_hide(struct rtgui_application *app);
-
-rt_base_t rtgui_application_run(struct rtgui_application *app);
-void rtgui_application_exit(struct rtgui_application *app, rt_uint16_t code);
-
-void rtgui_application_set_onidle(rtgui_idle_func onidle);
-rtgui_idle_func rtgui_application_get_onidle(void);
-struct rtgui_application* rtgui_application_self(void);
-
-rt_thread_t rtgui_application_get_server(void);
-
-void rtgui_application_set_root_object(struct rtgui_object* object);
-struct rtgui_object* rtgui_application_get_root_object(void);
-
-struct rtgui_event;
-rt_err_t rtgui_application_send(rt_thread_t tid, struct rtgui_event* event, rt_size_t event_size);
-rt_err_t rtgui_application_send_urgent(rt_thread_t tid, struct rtgui_event* event, rt_size_t event_size);
-rt_err_t rtgui_application_send_sync(rt_thread_t tid, struct rtgui_event* event, rt_size_t event_size);
-rt_err_t rtgui_application_ack(struct rtgui_event* event, rt_int32_t status);
-rt_err_t rtgui_application_recv(struct rtgui_event* event, rt_size_t event_size);
-rt_err_t rtgui_application_recv_nosuspend(struct rtgui_event* event, rt_size_t event_size);
-rt_err_t rtgui_application_recv_filter(rt_uint32_t type, struct rtgui_event* event, rt_size_t event_size);
-
-#endif /* end of include guard: RTGUI_APPLICATION_H */

+ 2 - 1
components/rtgui/include/rtgui/rtgui_config.h

@@ -77,5 +77,6 @@
 //#define RTGUI_USING_DESKTOP_WINDOW
 
 #define  RTGUI_EVENT_DEBUG
-#undef RTGUI_USING_SMALL_SIZE
+// #undef RTGUI_USING_SMALL_SIZE
+
 #endif

+ 1 - 4
components/rtgui/include/rtgui/rtgui_object.h

@@ -31,7 +31,7 @@ extern "C" {
 /** Casts the function pointer to an rtgui_constructor */
 #define RTGUI_DESTRUCTOR(destructor)                  ((rtgui_destructor_t)(destructor))
 
-/* pre-definetion */
+/* pre-definition */
 struct rtgui_object;
 typedef struct rtgui_object rtgui_object_t;
 typedef void (*rtgui_constructor_t)(rtgui_object_t *object);
@@ -125,9 +125,6 @@ rt_bool_t rtgui_object_event_handler(struct rtgui_object *object, struct rtgui_e
 	/* supress compiler warning */ \
 	widget = widget;
 
-void       rtgui_object_name_set(rtgui_object_t *object, const char *name);
-const char *rtgui_object_name_get(rtgui_object_t *object);
-
 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);
 

+ 5 - 3
components/rtgui/include/rtgui/rtgui_server.h

@@ -20,7 +20,7 @@
 /* RTGUI server definitions */
 
 /* top window definitions in server */
-enum
+enum rtgui_topwin_flag
 {
 	WINTITLE_NO         =  0x01,
 	WINTITLE_BORDER     =  0x02,
@@ -34,7 +34,9 @@ enum
 	/* window is modaled by other window */
 	WINTITLE_MODALED    =  0x80,
 	/* window is modaling other window */
-	WINTITLE_MODALING   = 0x100
+	WINTITLE_MODALING   = 0x100,
+	WINTITLE_ONTOP      = 0x200,
+	WINTITLE_ONBTM      = 0x400,
 };
 
 #define WINTITLE_HEIGHT         20
@@ -45,7 +47,7 @@ enum
 struct rtgui_topwin
 {
 	/* the window flag */
-	rt_uint32_t flag;
+	enum rtgui_topwin_flag flag;
 	/* event mask */
 	rt_uint32_t mask;
 

+ 11 - 0
components/rtgui/include/rtgui/rtgui_system.h

@@ -53,5 +53,16 @@ void* rtgui_realloc(void* ptr, rt_size_t size);
 #define rtgui_enter_critical	rt_enter_critical
 #define rtgui_exit_critical		rt_exit_critical
 
+rt_thread_t rtgui_get_server(void);
+
+struct rtgui_event;
+rt_err_t rtgui_send(rt_thread_t tid, struct rtgui_event* event, rt_size_t event_size);
+rt_err_t rtgui_send_urgent(rt_thread_t tid, struct rtgui_event* event, rt_size_t event_size);
+rt_err_t rtgui_send_sync(rt_thread_t tid, struct rtgui_event* event, rt_size_t event_size);
+rt_err_t rtgui_ack(struct rtgui_event* event, rt_int32_t status);
+rt_err_t rtgui_recv(struct rtgui_event* event, rt_size_t event_size);
+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
 

+ 0 - 44
components/rtgui/include/rtgui/widgets/about_view.h

@@ -1,44 +0,0 @@
-/*
- * File      : list_view.h
- * This file is part of RTGUI in RT-Thread RTOS
- * COPYRIGHT (C) 2010, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date           Author       Notes
- * 2010-01-06     Bernard      first version
- */
-
-#ifndef __RTGUI_ABOUT_VIEW_H__
-#define __RTGUI_ABOUT_VIEW_H__
-
-#include <rtgui/rtgui.h>
-#include <rtgui/image.h>
-#include <rtgui/rtgui_system.h>
-#include <rtgui/widgets/container.h>
-
-DECLARE_CLASS_TYPE(aboutview);
-/** Gets the type of a about view */
-#define RTGUI_ABOUT_VIEW_TYPE       (RTGUI_TYPE(aboutview))
-/** Casts the object to a about view */
-#define RTGUI_ABOUT_VIEW(obj)       (RTGUI_OBJECT_CAST((obj), RTGUI_ABOUT_VIEW_TYPE, rtgui_about_view_t))
-/** Checks if the object is a about view */
-#define RTGUI_IS_ABOUT_VIEW(obj)    (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_ABOUT_VIEW_TYPE))
-
-struct rtgui_about_view
-{
-	struct rtgui_container parent;
-
-	/* widget private data */
-	rtgui_image_t* logo;
-	const char* description;
-};
-typedef struct rtgui_about_view rtgui_about_view_t;
-
-rtgui_about_view_t* rtgui_about_view_create(rtgui_image_t *logo, const char* description);
-rt_bool_t rtgui_about_view_event_handler(struct rtgui_object* widget, struct rtgui_event* event);
-
-#endif

+ 5 - 8
components/rtgui/include/rtgui/widgets/box.h

@@ -33,26 +33,23 @@ DECLARE_CLASS_TYPE(box);
 
 struct rtgui_box
 {
-	struct rtgui_container parent;
+	struct rtgui_object parent;
 
 	rt_uint16_t orient;
 	rt_uint16_t border_size;
+
+	struct rtgui_container* container;
 };
 typedef struct rtgui_box rtgui_box_t;
 
-struct rtgui_box* rtgui_box_create(int orientation, rtgui_rect_t* rect);
+struct rtgui_box* rtgui_box_create(int orientation, int border_size);
 void rtgui_box_destroy(struct rtgui_box* box);
 
-rt_bool_t rtgui_box_event_handler(struct rtgui_object* object, rtgui_event_t* event);
-
-void rtgui_box_append(rtgui_box_t* box, rtgui_widget_t* widget);
 void rtgui_box_layout(rtgui_box_t* box);
 
-rt_uint32_t rtgui_box_get_width(rtgui_box_t* box);
-rt_uint32_t rtgui_box_get_height(rtgui_box_t* box);
-
 #ifdef __cplusplus
 }
 #endif
 
 #endif
+

+ 6 - 5
components/rtgui/include/rtgui/widgets/container.h

@@ -15,6 +15,7 @@
 #define __RTGUI_CONTAINER_H__
 
 #include <rtgui/widgets/widget.h>
+#include <rtgui/widgets/box.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -35,6 +36,9 @@ struct rtgui_container
 {
 	struct rtgui_widget parent;
 
+	/* layout box */
+	struct rtgui_box* layout_box;
+
 	rtgui_list_t children;
 };
 typedef struct rtgui_container rtgui_container_t;
@@ -44,12 +48,9 @@ void rtgui_container_destroy(rtgui_container_t* container);
 
 rt_bool_t rtgui_container_event_handler(struct rtgui_object* widget, struct rtgui_event* event);
 
-#ifndef RTGUI_USING_SMALL_SIZE
-struct rtgui_box;
+/* set layout box */
 void rtgui_container_set_box(struct rtgui_container* container, struct rtgui_box* box);
-#endif
-
-void rtgui_container_hide(rtgui_container_t* container);
+void rtgui_container_layout(struct rtgui_container* container);
 
 void rtgui_container_add_child(rtgui_container_t *container, rtgui_widget_t* child);
 void rtgui_container_remove_child(rtgui_container_t *container, rtgui_widget_t* child);

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

@@ -49,7 +49,7 @@ rtgui_filelist_view_t* rtgui_filelist_view_create(const char* directory,
 												  const rtgui_rect_t* rect);
 void rtgui_filelist_view_destroy(rtgui_filelist_view_t* view);
 
-rt_bool_t rtgui_filelist_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);
+rt_bool_t rtgui_filelist_view_event_handler(struct rtgui_object* object, struct rtgui_event* event);
 void rtgui_filelist_view_set_directory(rtgui_filelist_view_t* view, const char* directory);
 
 void rtgui_filelist_view_get_fullpath(rtgui_filelist_view_t* view, char* path, rt_size_t len);

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

@@ -29,7 +29,7 @@ struct rtgui_menu_item
 	rt_uint16_t submenu_count;
 
 	/* menu action */
-	rt_bool_t (*on_menuaction)(rtgui_widget_t* widget, rtgui_event_t* event);
+	rt_bool_t (*on_menuaction)(struct rtgui_object* object, struct rtgui_event* event);
 };
 typedef struct rtgui_menu_item rtgui_menu_item_t;
 

+ 45 - 0
components/rtgui/include/rtgui/widgets/panel.h

@@ -0,0 +1,45 @@
+/*
+ * File      : panel.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
+ * 2009-10-16     Bernard      first version
+ */
+#ifndef __RTGUI_PANEL_H__
+#define __RTGUI_PANEL_H__
+
+#include <rtgui/rtgui.h>
+#include <rtgui/widgets/container.h>
+
+DECLARE_CLASS_TYPE(panel);
+
+/** Gets the type of a 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 */
+#define RTGUI_IS_PANEL(obj)    (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_PANEL_TYPE))
+
+/*
+ * the panel widget
+ */
+struct rtgui_panel
+{
+	struct rtgui_container parent;
+
+	int border_style;
+};
+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_bool_t rtgui_panel_event_handler(struct rtgui_object* object, struct rtgui_event* event);
+
+#endif

+ 32 - 21
components/rtgui/include/rtgui/widgets/textbox.h

@@ -14,32 +14,34 @@
 #ifndef __RTGUI_TEXTBOX_H__
 #define __RTGUI_TEXTBOX_H__
 
-#include <rtgui/rtgui.h>
+#include <rtgui/rtgui_system.h>
 #include <rtgui/widgets/widget.h>
+#include <rtgui/widgets/container.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 DECLARE_CLASS_TYPE(textbox);
+
 /** Gets the type of a textbox */
 #define RTGUI_TEXTBOX_TYPE       (RTGUI_TYPE(textbox))
-/** Casts the object to a rtgui_textbox */
+/** Casts the object to a rtgui_textbox_t */
 #define RTGUI_TEXTBOX(obj)       (RTGUI_OBJECT_CAST((obj), RTGUI_TEXTBOX_TYPE, rtgui_textbox_t))
-/** Checks if the object is a rtgui_textbox */
+/** Checks if the object is a rtgui_textbox_t */
 #define RTGUI_IS_TEXTBOX(obj)    (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_TEXTBOX_TYPE))
 
 #define RTGUI_TEXTBOX_DEFAULT_WIDTH		80
-#define RTGUI_TEXTBOX_DEFAULT_HEIGHT	20
+#define RTGUI_TEXTBOX_DEFAULT_HEIGHT		20
 
-#define RTGUI_TEXTBOX_SINGLE			0x00
-#define RTGUI_TEXTBOX_MULTI				0x01
-#define RTGUI_TEXTBOX_MASK				0x02
-#define RTGUI_TEXTBOX_CARET_SHOW		0x10
-#define RTGUI_TEXTBOX_CARET_HIDE		0x00
-
-struct rtgui_textbox_line
-{
-	char* line_text;
+#define RTGUI_TEXTBOX_SINGLE        0x00
+#define RTGUI_TEXTBOX_MULTI			0x01 /* multiline */
+#define RTGUI_TEXTBOX_MASK			0x02 /* ciphertext */
+#define RTGUI_TEXTBOX_DIGIT         0x04 /* digit */
+#define RTGUI_TEXTBOX_CARET_SHOW	0x10
+#define RTGUI_TEXTBOX_CARET_STAT	0x20 /* unused */
 
-	struct rtgui_textbox_line *prev, *next;
-};
+#define RTGUI_TEXTBOX_LINE_MAX		128  /* text line cache */
 
 struct rtgui_textbox
 {
@@ -47,22 +49,24 @@ struct rtgui_textbox
 	struct rtgui_widget parent;
 
 	/* text box flag */
-	rt_uint8_t flag;
+	rt_uint32_t flag;
 
 	/* current line and position */
 	rt_uint16_t line, line_begin, position, line_length;
-
+	rt_uint16_t dis_length;	/*may be display length.*/
 	char* text;
 	rt_size_t font_width;
 
-	struct rtgui_timer* caret_timer;
+	rtgui_timer_t *caret_timer;
+	rtgui_color_t *caret;
+	rtgui_rect_t  caret_rect;
 
-	/* widget private data */
-	rt_bool_t (*on_enter) 	(struct rtgui_widget* widget, struct rtgui_event* event);
+	/* textbox private data */
+	rt_bool_t (*on_enter) (struct rtgui_textbox *box, rtgui_event_t* event);
 };
 typedef struct rtgui_textbox rtgui_textbox_t;
 
-struct rtgui_textbox* rtgui_textbox_create(const char* text, rt_uint8_t flag);
+struct rtgui_textbox* rtgui_textbox_create(const char* text, rt_uint32_t flag);
 void rtgui_textbox_destroy(struct rtgui_textbox* box);
 
 rt_bool_t rtgui_textbox_event_handler(struct rtgui_object* object, struct rtgui_event* event);
@@ -72,4 +76,11 @@ const char* rtgui_textbox_get_value(struct rtgui_textbox* box);
 
 void rtgui_textbox_set_line_length(struct rtgui_textbox* box, rt_size_t length);
 
+void rtgui_textbox_get_edit_rect(struct rtgui_textbox *box,rtgui_rect_t *rect);
+
+void rtgui_textbox_ondraw(rtgui_textbox_t* box);
+#ifdef __cplusplus
+}
+#endif
+
 #endif

+ 13 - 14
components/rtgui/include/rtgui/widgets/widget.h

@@ -26,16 +26,16 @@ extern "C" {
 #endif
 
 #define RTGUI_WIDGET_FLAG_DEFAULT		0x0000
-#define RTGUI_WIDGET_FLAG_HIDE			0x0001
+#define RTGUI_WIDGET_FLAG_SHOWN			0x0001
 #define RTGUI_WIDGET_FLAG_DISABLE		0x0002
 #define RTGUI_WIDGET_FLAG_FOCUS			0x0004
 #define RTGUI_WIDGET_FLAG_TRANSPARENT	0x0008
 #define RTGUI_WIDGET_FLAG_FOCUSABLE		0x0010
 #define RTGUI_WIDGET_FLAG_DC_VISIBLE	0x0100
 
-#define RTGUI_WIDGET_UNHIDE(w)			(w)->flag &= ~RTGUI_WIDGET_FLAG_HIDE
-#define RTGUI_WIDGET_HIDE(w)			(w)->flag |= RTGUI_WIDGET_FLAG_HIDE
-#define RTGUI_WIDGET_IS_HIDE(w)			((w)->flag & RTGUI_WIDGET_FLAG_HIDE)
+#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
@@ -52,12 +52,13 @@ extern "C" {
 #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))
 
-/* get rtgui widget object */
-#define RTGUI_WIDGET_FOREGROUND(w) 		((w)->gc.foreground)
-#define RTGUI_WIDGET_BACKGROUND(w)		((w)->gc.background)
-#define RTGUI_WIDGET_TEXTALIGN(w)		((w)->gc.textalign)
-#define RTGUI_WIDGET_FONT(w)			((w)->gc.font)
-#define RTGUI_WIDGET_FLAG(w)			((w)->flag)
+/* rtgui widget attribute */
+#define RTGUI_WIDGET_FOREGROUND(w) 		(RTGUI_WIDGET(w)->gc.foreground)
+#define RTGUI_WIDGET_BACKGROUND(w)		(RTGUI_WIDGET(w)->gc.background)
+#define RTGUI_WIDGET_TEXTALIGN(w)		(RTGUI_WIDGET(w)->gc.textalign)
+#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)
 
 DECLARE_CLASS_TYPE(widget);
 
@@ -96,14 +97,10 @@ struct rtgui_widget
 	/* the widget extent */
 	rtgui_rect_t extent;
 
-#ifndef RTGUI_USING_SMALL_SIZE
 	/* minimal width and height of widget */
 	rt_int16_t mini_width, mini_height;
-	rt_int16_t margin, margin_style;
-
 	/* widget align */
 	rt_int32_t align;
-#endif
 
 	/* the rect clip */
 	rtgui_region_t clip;
@@ -189,7 +186,9 @@ void rtgui_widget_update_clip(rtgui_widget_t* widget);
 struct rtgui_win* rtgui_widget_get_toplevel(rtgui_widget_t* widget);
 
 void rtgui_widget_show(rtgui_widget_t* widget);
+rt_bool_t rtgui_widget_onshow(struct rtgui_object *object, struct rtgui_event *event);
 void rtgui_widget_hide(rtgui_widget_t* widget);
+rt_bool_t rtgui_widget_onhide(struct rtgui_object *object, struct rtgui_event *event);
 void rtgui_widget_update(rtgui_widget_t* widget);
 
 /* get parent color */

+ 4 - 12
components/rtgui/include/rtgui/widgets/window.h

@@ -37,16 +37,8 @@ DECLARE_CLASS_TYPE(win);
 #define RTGUI_WIN_STYLE_MINIBOX		        0x010	/* window has the mini button	*/
 
 #define RTGUI_WIN_STYLE_DESTROY_ON_CLOSE	0x020   /* window is destroyed when closed */
-#ifdef RTGUI_USING_DESKTOP_WINDOW
-/* A desktop window is a full screen window which will beneath all other windows.
- * There will be only one desktop window in a system. And this window should be
- * created _before_ any other windows.
- */
-#define RTGUI_WIN_STYLE_DESKTOP		        0x8000
-#define RTGUI_WIN_STYLE_DESKTOP_DEFAULT     RTGUI_WIN_STYLE_DESKTOP |\
-                                            RTGUI_WIN_STYLE_NO_BORDER |\
-                                            RTGUI_WIN_STYLE_NO_TITLE
-#endif
+#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_DEFAULT		(RTGUI_WIN_STYLE_CLOSEBOX | RTGUI_WIN_STYLE_MINIBOX)
 
@@ -84,7 +76,7 @@ struct rtgui_win
 	/* the widget that will grab the focus in current window */
 	struct rtgui_widget *focused_widget;
 
-	/* top window style */
+	/* window style */
 	rt_uint16_t style;
 
 	/* window state flag */
@@ -133,7 +125,7 @@ rt_bool_t rtgui_win_close(struct rtgui_win* win);
 rt_base_t rtgui_win_show(struct rtgui_win *win, rt_bool_t is_modal);
 void rtgui_win_hiden(rtgui_win_t* win);
 void rtgui_win_end_modal(rtgui_win_t* win, rtgui_modal_code_t modal_code);
-
+rt_err_t rtgui_win_activate(struct rtgui_win *win);
 rt_bool_t rtgui_win_is_activated(struct rtgui_win* win);
 
 void rtgui_win_move(struct rtgui_win* win, int x, int y);

+ 4 - 0
components/rtgui/server/driver.c

@@ -88,3 +88,7 @@ rt_uint8_t* rtgui_graphic_driver_get_framebuffer(const struct rtgui_graphic_driv
 	return (rt_uint8_t*)driver->framebuffer;
 }
 
+rt_uint8_t* rtgui_graphic_driver_get_default_framebuffer(void)
+{
+	return rtgui_graphic_driver_get_framebuffer(&_driver);
+}

+ 14 - 16
components/rtgui/server/mouse.c

@@ -52,9 +52,6 @@ struct rtgui_cursor
 	rt_uint8_t		*win_top, *win_bottom;
 	rt_bool_t		win_rect_show, win_rect_has_saved;
 #endif
-
-	/* screen framebuffer */
-	rt_uint8_t*		framebuffer;
 };
 
 struct rtgui_cursor* _rtgui_cursor;
@@ -140,7 +137,6 @@ void rtgui_mouse_init()
 
 	/* init cursor */
 	_rtgui_cursor->bpp = gd->bits_per_pixel/8;
-	_rtgui_cursor->framebuffer = rtgui_graphic_driver_get_framebuffer(gd);
 	_rtgui_cursor->screen_pitch = _rtgui_cursor->bpp * gd->width;
 
 #ifdef RTGUI_USING_MOUSE_CURSOR
@@ -300,7 +296,7 @@ static void rtgui_cursor_restore()
 	rt_base_t idx, height, cursor_pitch;
 	rt_uint8_t *cursor_ptr, *fb_ptr;
 
-	fb_ptr = _rtgui_cursor->framebuffer + _rtgui_cursor->cy * _rtgui_cursor->screen_pitch
+	fb_ptr = rtgui_graphic_driver_get_default_framebuffer() + _rtgui_cursor->cy * _rtgui_cursor->screen_pitch
 		+ _rtgui_cursor->cx * _rtgui_cursor->bpp;
 	cursor_ptr = _rtgui_cursor->cursor_saved;
 
@@ -327,7 +323,7 @@ static void rtgui_cursor_save()
 	rt_base_t idx, height, cursor_pitch;
 	rt_uint8_t *cursor_ptr, *fb_ptr;
 
-	fb_ptr = _rtgui_cursor->framebuffer + _rtgui_cursor->cy * _rtgui_cursor->screen_pitch +
+	fb_ptr = _driver_get_default_framebuffer() + _rtgui_cursor->cy * _rtgui_cursor->screen_pitch +
 		_rtgui_cursor->cx * _rtgui_cursor->bpp;
 	cursor_ptr = _rtgui_cursor->cursor_saved;
 
@@ -488,10 +484,11 @@ static void rtgui_winrect_show()
 
 static void rtgui_winrect_restore()
 {
-	rt_uint8_t *winrect_ptr, *fb_ptr;
+	rt_uint8_t *winrect_ptr, *fb_ptr, *driver_fb;
 	int winrect_pitch, idx;
 	rtgui_rect_t screen_rect, win_rect;
 
+	driver_fb = rtgui_graphic_driver_get_default_framebuffer();
 	win_rect = _rtgui_cursor->win_rect;
 
 	rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(),
@@ -499,7 +496,7 @@ static void rtgui_winrect_restore()
 	rtgui_rect_intersect(&screen_rect, &win_rect);
 
 	/* restore winrect left */
-	fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch +
+	fb_ptr = driver_fb + win_rect.y1 * _rtgui_cursor->screen_pitch +
 		win_rect.x1 * _rtgui_cursor->bpp;
 	winrect_ptr = _rtgui_cursor->win_left;
 	winrect_pitch = WIN_MOVE_BORDER * _rtgui_cursor->bpp;
@@ -507,7 +504,7 @@ static void rtgui_winrect_restore()
 		(win_rect.y2 - win_rect.y1), winrect_pitch);
 
 	/* restore winrect right */
-	fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch +
+	fb_ptr = driver_fb + win_rect.y1 * _rtgui_cursor->screen_pitch +
 		(win_rect.x2 - WIN_MOVE_BORDER) * _rtgui_cursor->bpp;
 	winrect_ptr = _rtgui_cursor->win_right;
 	winrect_pitch = WIN_MOVE_BORDER * _rtgui_cursor->bpp;
@@ -515,7 +512,7 @@ static void rtgui_winrect_restore()
 		(win_rect.y2 - win_rect.y1), winrect_pitch);
 
 	/* restore winrect top */
-	fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch +
+	fb_ptr = driver_fb + win_rect.y1 * _rtgui_cursor->screen_pitch +
 		(win_rect.x1 + WIN_MOVE_BORDER)* _rtgui_cursor->bpp;
 	winrect_ptr = _rtgui_cursor->win_top;
 	winrect_pitch = (win_rect.x2 - win_rect.x1 - 2 * WIN_MOVE_BORDER) * _rtgui_cursor->bpp;
@@ -523,7 +520,7 @@ static void rtgui_winrect_restore()
 		WIN_MOVE_BORDER, winrect_pitch);
 
 	/* restore winrect bottom */
-	fb_ptr = _rtgui_cursor->framebuffer + (win_rect.y2 - WIN_MOVE_BORDER) * _rtgui_cursor->screen_pitch +
+	fb_ptr = driver_fb + (win_rect.y2 - WIN_MOVE_BORDER) * _rtgui_cursor->screen_pitch +
 		(win_rect.x1 + WIN_MOVE_BORDER) * _rtgui_cursor->bpp;
 	winrect_ptr = _rtgui_cursor->win_bottom;
 	display_direct_memcpy(winrect_ptr, fb_ptr, winrect_pitch, _rtgui_cursor->screen_pitch,
@@ -532,10 +529,11 @@ static void rtgui_winrect_restore()
 
 static void rtgui_winrect_save()
 {
-	rt_uint8_t *winrect_ptr, *fb_ptr;
+	rt_uint8_t *winrect_ptr, *fb_ptr, *driver_fb;
 	int winrect_pitch, idx;
 	rtgui_rect_t screen_rect, win_rect;
 
+	driver_fb = rtgui_graphic_driver_get_default_framebuffer();
 	win_rect = _rtgui_cursor->win_rect;
 
 	rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(),
@@ -546,7 +544,7 @@ static void rtgui_winrect_save()
 	_rtgui_cursor->win_rect_has_saved = RT_TRUE;
 
 	/* save winrect left */
-	fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch +
+	fb_ptr = driver_fb + win_rect.y1 * _rtgui_cursor->screen_pitch +
 		win_rect.x1 * _rtgui_cursor->bpp;
 	winrect_ptr = _rtgui_cursor->win_left;
 	winrect_pitch = WIN_MOVE_BORDER * _rtgui_cursor->bpp;
@@ -554,7 +552,7 @@ static void rtgui_winrect_save()
 		(win_rect.y2 - win_rect.y1), winrect_pitch);
 
 	/* save winrect right */
-	fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch +
+	fb_ptr = driver_fb + win_rect.y1 * _rtgui_cursor->screen_pitch +
 		(win_rect.x2 - WIN_MOVE_BORDER) * _rtgui_cursor->bpp;
 	winrect_ptr = _rtgui_cursor->win_right;
 	winrect_pitch = WIN_MOVE_BORDER * _rtgui_cursor->bpp;
@@ -562,7 +560,7 @@ static void rtgui_winrect_save()
 		(win_rect.y2 - win_rect.y1), winrect_pitch);
 
 	/* save winrect top */
-	fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch +
+	fb_ptr = driver_fb + win_rect.y1 * _rtgui_cursor->screen_pitch +
 		(win_rect.x1 + WIN_MOVE_BORDER)* _rtgui_cursor->bpp;
 	winrect_ptr = _rtgui_cursor->win_top;
 	winrect_pitch = (win_rect.x2 - win_rect.x1 - 2 * WIN_MOVE_BORDER) * _rtgui_cursor->bpp;
@@ -570,7 +568,7 @@ static void rtgui_winrect_save()
 		WIN_MOVE_BORDER, winrect_pitch);
 
 	/* save winrect bottom */
-	fb_ptr = _rtgui_cursor->framebuffer + (win_rect.y2 - WIN_MOVE_BORDER) * _rtgui_cursor->screen_pitch +
+	fb_ptr = driver_fb + (win_rect.y2 - WIN_MOVE_BORDER) * _rtgui_cursor->screen_pitch +
 		(win_rect.x1 + WIN_MOVE_BORDER) * _rtgui_cursor->bpp;
 	winrect_ptr = _rtgui_cursor->win_bottom;
 	display_direct_memcpy(fb_ptr, winrect_ptr, _rtgui_cursor->screen_pitch, winrect_pitch,

+ 0 - 677
components/rtgui/server/rtgui_application.c

@@ -1,677 +0,0 @@
-/*
- * File      : rtgui_application.c
- * This file is part of RTGUI in RT-Thread RTOS
- * COPYRIGHT (C) 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-01-13     Grissiom     first version(just a prototype of application API)
- */
-
-#include <rtgui/rtgui_system.h>
-#include <rtgui/rtgui_application.h>
-#include <rtgui/widgets/window.h>
-
-#ifdef _WIN32
-#define RTGUI_EVENT_DEBUG
-#endif
-
-#ifdef RTGUI_EVENT_DEBUG
-const char *event_string[] =
-{
-	/* window event */
-	"WIN_CREATE",			/* create a window 	*/
-	"WIN_DESTROY",			/* destroy a window 	*/
-	"WIN_SHOW",				/* show a window 		*/
-	"WIN_HIDE",				/* hide a window 		*/
-	"WIN_ACTIVATE", 		/* activate a window 	*/
-	"WIN_DEACTIVATE",		/* deactivate a window 	*/
-	"WIN_CLOSE",			/* close a window 		*/
-	"WIN_MOVE",				/* move a window 		*/
-	"WIN_RESIZE", 			/* resize a window 		*/
-	"WIN_MODAL_ENTER", 			/* a window modals		*/
-
-	"SET_WM", 				/* set window manager	*/
-
-	"UPDATE_BEGIN",			/* begin of update rect */
-	"UPDATE_END",			/* end of update rect	*/
-	"MONITOR_ADD",			/* add a monitor rect 	*/
-	"MONITOR_REMOVE", 		/* remove a monitor rect*/
-	"PAINT",				/* paint on screen 		*/
-	"TIMER",				/* timer 				*/
-
-	/* clip rect information */
-	"CLIP_INFO",			/* clip rect info		*/
-
-	/* mouse and keyboard event */
-	"MOUSE_MOTION",			/* mouse motion */
-	"MOUSE_BUTTON",			/* mouse button info 	*/
-	"KBD",					/* keyboard info		*/
-
-	/* user command event */
-	"COMMAND",				/* user command 		*/
-
-	/* request's status event */
-	"STATUS",				/* request result 		*/
-	"SCROLLED",           	/* scroll bar scrolled  */
-	"RESIZE",				/* widget resize 		*/
-};
-
-#define DBG_MSG(x)	rt_kprintf x
-
-static void rtgui_event_dump(rt_thread_t tid, rtgui_event_t* event)
-{
-	char* sender = "(unknown)";
-
-	if ((event->type == RTGUI_EVENT_TIMER) ||
-		(event->type == RTGUI_EVENT_UPDATE_BEGIN) ||
-		(event->type == RTGUI_EVENT_MOUSE_MOTION) ||
-		(event->type == RTGUI_EVENT_UPDATE_END))
-	{
-		/* don't dump timer event */
-		return ;
-	}
-
-	if (event->sender != RT_NULL)
-		sender = event->sender->name;
-
-	rt_kprintf("%s -- %s --> %s ", sender, event_string[event->type], tid->name);
-	switch (event->type)
-	{
-	case RTGUI_EVENT_PAINT:
-		{
-			struct rtgui_event_paint *paint = (struct rtgui_event_paint *)event;
-
-			if(paint->wid != RT_NULL)
-				rt_kprintf("win: %s", paint->wid->title);
-		}
-		break;
-
-	case RTGUI_EVENT_KBD:
-		{
-			struct rtgui_event_kbd *ekbd = (struct rtgui_event_kbd*) event;
-			if (ekbd->wid != RT_NULL)
-				rt_kprintf("win: %s", ekbd->wid->title);
-			if (RTGUI_KBD_IS_UP(ekbd)) rt_kprintf(", up");
-			else rt_kprintf(", down");
-		}
-		break;
-
-	case RTGUI_EVENT_CLIP_INFO:
-		{
-			struct rtgui_event_clip_info *info = (struct rtgui_event_clip_info *)event;
-
-			if(info->wid != RT_NULL)
-				rt_kprintf("win: %s", info->wid->title);
-		}
-		break;
-
-	case RTGUI_EVENT_WIN_CREATE:
-		{
-			struct rtgui_event_win_create *create = (struct rtgui_event_win_create*)event;
-
-			rt_kprintf(" win: %s at (x1:%d, y1:%d, x2:%d, y2:%d), addr: %p",
-#ifdef RTGUI_USING_SMALL_SIZE
-				create->wid->title,
-				RTGUI_WIDGET(create->wid)->extent.x1,
-				RTGUI_WIDGET(create->wid)->extent.y1,
-				RTGUI_WIDGET(create->wid)->extent.x2,
-				RTGUI_WIDGET(create->wid)->extent.y2,
-#else
-				create->title,
-				create->extent.x1,
-				create->extent.y1,
-				create->extent.x2,
-				create->extent.y2,
-#endif
-				create->wid
-                );
-		}
-		break;
-
-	case RTGUI_EVENT_UPDATE_END:
-		{
-			struct rtgui_event_update_end* update_end = (struct rtgui_event_update_end*)event;
-			rt_kprintf("(x:%d, y1:%d, x2:%d, y2:%d)", update_end->rect.x1,
-				update_end->rect.y1,
-				update_end->rect.x2,
-				update_end->rect.y2);
-		}
-		break;
-
-	case RTGUI_EVENT_WIN_ACTIVATE:
-	case RTGUI_EVENT_WIN_DEACTIVATE:
-	case RTGUI_EVENT_WIN_SHOW:
-	case RTGUI_EVENT_WIN_MODAL_ENTER:
-	case RTGUI_EVENT_WIN_HIDE:
-		{
-			struct rtgui_event_win *win = (struct rtgui_event_win *)event;
-
-			if(win->wid != RT_NULL)
-				rt_kprintf("win: %s", win->wid->title);
-		}
-		break;
-
-	case RTGUI_EVENT_WIN_MOVE:
-		{
-			struct rtgui_event_win_move *win = (struct rtgui_event_win_move *)event;
-
-			if(win->wid != RT_NULL)
-			{
-				rt_kprintf("win: %s", win->wid->title);
-				rt_kprintf(" to (x:%d, y:%d)", win->x, win->y);
-			}
-		}
-		break;
-
-	case RTGUI_EVENT_WIN_RESIZE:
-		{
-			struct rtgui_event_win_resize* win = (struct rtgui_event_win_resize *)event;
-
-			if (win->wid != RT_NULL)
-			{
-				rt_kprintf("win: %s, rect(x1:%d, y1:%d, x2:%d, y2:%d)", win->wid->title,
-					RTGUI_WIDGET(win->wid)->extent.x1,
-					RTGUI_WIDGET(win->wid)->extent.y1,
-					RTGUI_WIDGET(win->wid)->extent.x2,
-					RTGUI_WIDGET(win->wid)->extent.y2);
-			}
-		}
-		break;
-
-	case RTGUI_EVENT_MOUSE_BUTTON:
-	case RTGUI_EVENT_MOUSE_MOTION:
-		{
-			struct rtgui_event_mouse *mouse = (struct rtgui_event_mouse*)event;
-
-			if (mouse->button & RTGUI_MOUSE_BUTTON_LEFT) rt_kprintf("left ");
-			else rt_kprintf("right ");
-
-			if (mouse->button & RTGUI_MOUSE_BUTTON_DOWN) rt_kprintf("down ");
-			else rt_kprintf("up ");
-
-			if (mouse->wid != RT_NULL)
-				rt_kprintf("win: %s at (%d, %d)", mouse->wid->title,
-				mouse->x, mouse->y);
-			else
-				rt_kprintf("(%d, %d)", mouse->x, mouse->y);
-		}
-		break;
-
-	case RTGUI_EVENT_MONITOR_ADD:
-		{
-			struct rtgui_event_monitor *monitor = (struct rtgui_event_monitor*)event;
-			if (monitor->wid != RT_NULL)
-			{
-				rt_kprintf("win: %s, the rect is:(%d, %d) - (%d, %d)", monitor->wid->title,
-					monitor->rect.x1, monitor->rect.y1,
-					monitor->rect.x2, monitor->rect.y2);
-			}
-		}
-		break;
-
-	default:
-		break;
-	}
-
-	rt_kprintf("\n");
-}
-#else
-#define DBG_MSG(x)
-#define rtgui_event_dump(tid, event)
-#endif
-
-rt_bool_t rtgui_application_event_handler(struct rtgui_object* obj, rtgui_event_t* event);
-
-static void _rtgui_application_constructor(struct rtgui_application *app)
-{
-	/* set event handler */
-	rtgui_object_set_event_handler(RTGUI_OBJECT(app),
-			                       rtgui_application_event_handler);
-
-	app->name           = RT_NULL;
-	/* set EXITED so we can destroy an application that just created */
-	app->state_flag     = RTGUI_APPLICATION_FLAG_EXITED;
-	app->ref_count      = 0;
-	app->exit_code      = 0;
-	app->tid            = RT_NULL;
-	app->server         = RT_NULL;
-	app->mq             = RT_NULL;
-	app->modal_object   = RT_NULL;
-	app->on_idle        = RT_NULL;
-}
-
-static void _rtgui_application_destructor(struct rtgui_application *app)
-{
-	RT_ASSERT(app != RT_NULL);
-
-	rt_free(app->name);
-	app->name = RT_NULL;
-}
-
-DEFINE_CLASS_TYPE(application, "application",
-	RTGUI_OBJECT_TYPE,
-	_rtgui_application_constructor,
-	_rtgui_application_destructor,
-	sizeof(struct rtgui_application));
-
-struct rtgui_application* rtgui_application_create(
-        rt_thread_t tid,
-        const char *myname)
-{
-	struct rtgui_application *app;
-
-	RT_ASSERT(tid != RT_NULL);
-	RT_ASSERT(myname != RT_NULL);
-
-	/* create application */
-	app = RTGUI_APPLICATION(rtgui_object_create(RTGUI_APPLICATION_TYPE));
-	if (app == RT_NULL)
-		return RT_NULL;
-
-	DBG_MSG(("register a rtgui application(%s) on thread %s\n", myname, tid->name));
-
-	app->tid     = tid;
-	/* set user thread */
-	tid->user_data = (rt_uint32_t)app;
-
-	app->mq = rt_mq_create("rtgui", sizeof(union rtgui_event_generic), 32, RT_IPC_FLAG_FIFO);
-	if (app->mq == RT_NULL)
-	{
-		rt_kprintf("mq err\n");
-		goto __mq_err;
-	}
-
-	/* set application title */
-	app->name = (unsigned char*)rt_strdup((char*)myname);
-	if (app->name != RT_NULL)
-		return app;
-
-__mq_err:
-	rtgui_object_destroy(RTGUI_OBJECT(app));
-	tid->user_data = 0;
-	return RT_NULL;
-}
-
-#define _rtgui_application_check(app) \
-do { \
-    RT_ASSERT(app != RT_NULL); \
-    RT_ASSERT(app->tid != RT_NULL); \
-    RT_ASSERT(app->tid->user_data != 0); \
-    RT_ASSERT(app->mq != RT_NULL); \
-} while (0)
-
-void rtgui_application_destroy(struct rtgui_application *app)
-{
-    _rtgui_application_check(app);
-
-	if (!(app->state_flag & RTGUI_APPLICATION_FLAG_EXITED))
-	{
-		rt_kprintf("cannot destroy a running application: %s.\n",
-				   app->name);
-		return;
-	}
-
-	app->tid->user_data = 0;
-	rt_mq_delete(app->mq);
-	rtgui_object_destroy(RTGUI_OBJECT(app));
-}
-
-struct rtgui_application* rtgui_application_self(void)
-{
-	struct rtgui_application *app;
-	rt_thread_t self;
-
-	/* get current thread */
-	self = rt_thread_self();
-	app = (struct rtgui_application*)(self->user_data);
-
-	return app;
-}
-
-void rtgui_application_set_onidle(rtgui_idle_func onidle)
-{
-	struct rtgui_application *app;
-
-	app = rtgui_application_self();
-	if (app != RT_NULL)
-		app->on_idle = onidle;
-}
-
-rtgui_idle_func rtgui_application_get_onidle(void)
-{
-	struct rtgui_application *app;
-
-	app = rtgui_application_self();
-	if (app != RT_NULL)
-		return app->on_idle;
-	else
-		return RT_NULL;
-}
-
-extern rt_thread_t rt_thread_find(char* name);
-rt_thread_t rtgui_application_get_server(void)
-{
-	return rt_thread_find("rtgui");
-}
-
-rt_err_t rtgui_application_send(rt_thread_t tid, rtgui_event_t* event, rt_size_t event_size)
-{
-	rt_err_t result;
-	struct rtgui_application *app;
-
-	RT_ASSERT(tid != RT_NULL);
-	RT_ASSERT(event != RT_NULL);
-	RT_ASSERT(event_size != 0);
-
-	rtgui_event_dump(tid, event);
-
-	/* find struct rtgui_application */
-	app = (struct rtgui_application*) (tid->user_data);
-	if (app == RT_NULL)
-		return -RT_ERROR;
-
-	result = rt_mq_send(app->mq, event, event_size);
-	if (result != RT_EOK)
-	{
-		if (event->type != RTGUI_EVENT_TIMER)
-			rt_kprintf("send event to %s failed\n", app->tid->name);
-	}
-
-	return result;
-}
-
-rt_err_t rtgui_application_send_urgent(rt_thread_t tid, rtgui_event_t* event, rt_size_t event_size)
-{
-	rt_err_t result;
-	struct rtgui_application *app;
-
-	RT_ASSERT(tid != RT_NULL);
-	RT_ASSERT(event != RT_NULL);
-	RT_ASSERT(event_size != 0);
-
-	rtgui_event_dump(tid, event);
-
-	/* find rtgui_application */
-	app = (struct rtgui_application*) (tid->user_data);
-	if (app == RT_NULL)
-		return -RT_ERROR;
-
-	result = rt_mq_urgent(app->mq, event, event_size);
-	if (result != RT_EOK)
-		rt_kprintf("send ergent event failed\n");
-
-	return result;
-}
-
-rt_err_t rtgui_application_send_sync(rt_thread_t tid, rtgui_event_t* event, rt_size_t event_size)
-{
-	rt_err_t r;
-	struct rtgui_application *app;
-	rt_int32_t ack_buffer, ack_status;
-	struct rt_mailbox ack_mb;
-
-	RT_ASSERT(tid != RT_NULL);
-	RT_ASSERT(event != RT_NULL);
-	RT_ASSERT(event_size != 0);
-
-	rtgui_event_dump(tid, event);
-
-	/* init ack mailbox */
-	r = rt_mb_init(&ack_mb, "ack", &ack_buffer, 1, 0);
-	if (r!= RT_EOK)
-		goto __return;
-
-	app = (struct rtgui_application*) (tid->user_data);
-	if (app == RT_NULL)
-	{
-		r = -RT_ERROR;
-		goto __return;
-	}
-
-	event->ack = &ack_mb;
-	r = rt_mq_send(app->mq, event, event_size);
-	if (r != RT_EOK)
-	{
-		rt_kprintf("send sync event failed\n");
-		goto __return;
-	}
-
-	r = rt_mb_recv(&ack_mb, (rt_uint32_t*)&ack_status, RT_WAITING_FOREVER);
-	if (r!= RT_EOK)
-		goto __return;
-
-	if (ack_status != RTGUI_STATUS_OK)
-		r = -RT_ERROR;
-	else
-		r = RT_EOK;
-
-__return:
-	/* fini ack mailbox */
-	rt_mb_detach(&ack_mb);
-	return r;
-}
-
-rt_err_t rtgui_application_ack(rtgui_event_t* event, rt_int32_t status)
-{
-	RT_ASSERT(event != RT_NULL);
-	RT_ASSERT(event->ack != RT_NULL);
-
-	rt_mb_send(event->ack, status);
-
-	return RT_EOK;
-}
-
-rt_err_t rtgui_application_recv(rtgui_event_t* event, rt_size_t event_size)
-{
-	struct rtgui_application* app;
-	rt_err_t r;
-
-	RT_ASSERT(event != RT_NULL);
-	RT_ASSERT(event_size != 0);
-
-	app = (struct rtgui_application*) (rt_thread_self()->user_data);
-	if (app == RT_NULL)
-		return -RT_ERROR;
-
-	r = rt_mq_recv(app->mq, event, event_size, RT_WAITING_FOREVER);
-
-	return r;
-}
-
-rt_err_t rtgui_application_recv_nosuspend(rtgui_event_t* event, rt_size_t event_size)
-{
-	struct rtgui_application *app;
-	rt_err_t r;
-
-	RT_ASSERT(event != RT_NULL);
-	RT_ASSERT(event != 0);
-
-	app = (struct rtgui_application*) (rt_thread_self()->user_data);
-	if (app == RT_NULL)
-		return -RT_ERROR;
-
-	r = rt_mq_recv(app->mq, event, event_size, 0);
-
-	return r;
-}
-
-rt_err_t rtgui_application_recv_filter(rt_uint32_t type, rtgui_event_t* event, rt_size_t event_size)
-{
-	struct rtgui_application *app;
-
-	RT_ASSERT(event != RT_NULL);
-	RT_ASSERT(event_size != 0);
-
-	app = (struct rtgui_application*) (rt_thread_self()->user_data);
-	if (app == RT_NULL)
-		return -RT_ERROR;
-
-	while (rt_mq_recv(app->mq, event, event_size, RT_WAITING_FOREVER) == RT_EOK)
-	{
-		if (event->type == type)
-		{
-			return RT_EOK;
-		}
-		else
-		{
-			if (RTGUI_OBJECT(app)->event_handler != RT_NULL)
-			{
-				RTGUI_OBJECT(app)->event_handler(RTGUI_OBJECT(app), event);
-			}
-		}
-	}
-
-	return -RT_ERROR;
-}
-
-rt_inline rt_bool_t _rtgui_application_dest_handle(
-		struct rtgui_application *app,
-		struct rtgui_event *event)
-{
-	struct rtgui_event_win* wevent = (struct rtgui_event_win*)event;
-
-	struct rtgui_object* dest_object = RTGUI_OBJECT(wevent->wid);
-
-	if (dest_object != RT_NULL)
-	{
-		if (dest_object->event_handler != RT_NULL)
-			return dest_object->event_handler(RTGUI_OBJECT(dest_object), event);
-		else
-			return RT_FALSE;
-	}
-	else
-	{
-		rt_kprintf("RTGUI ERROR:server sent a event(%d) without wid\n", event->type);
-		return RT_FALSE;
-	}
-}
-
-rt_bool_t rtgui_application_event_handler(struct rtgui_object* object, rtgui_event_t* event)
-{
-	struct rtgui_application* app;
-
-	RT_ASSERT(object != RT_NULL);
-	RT_ASSERT(event != RT_NULL);
-
-	app = RTGUI_APPLICATION(object);
-
-	switch (event->type)
-	{
-	case RTGUI_EVENT_PAINT:
-	case RTGUI_EVENT_CLIP_INFO:
-	case RTGUI_EVENT_WIN_ACTIVATE:
-	case RTGUI_EVENT_WIN_DEACTIVATE:
-	case RTGUI_EVENT_WIN_CLOSE:
-	case RTGUI_EVENT_WIN_MOVE:
-	case RTGUI_EVENT_KBD:
-		_rtgui_application_dest_handle(app, event);
-		break;
-
-	case RTGUI_EVENT_MOUSE_BUTTON:
-	case RTGUI_EVENT_MOUSE_MOTION:
-		{
-			struct rtgui_event_win* wevent = (struct rtgui_event_win*)event;
-			struct rtgui_object* dest_object = RTGUI_OBJECT(wevent->wid);
-
-			// FIXME: let application determine the dest_wiget but not in sever
-			// so we can combine this handler with above one
-			if (app->modal_object != RT_NULL &&
-				dest_object != app->modal_object)
-			{
-//				rt_kprintf("discard event %s that is not sent to modal object\n",
-//						   event_string[event->type]);
-			}
-			else
-			{
-				_rtgui_application_dest_handle(app, event);
-			}
-		}
-		break;
-
-	case RTGUI_EVENT_TIMER:
-		{
-			struct rtgui_timer* timer;
-			struct rtgui_event_timer* etimer = (struct rtgui_event_timer*) event;
-
-			timer = etimer->timer;
-			if (timer->timeout != RT_NULL)
-			{
-				/* call timeout function */
-				timer->timeout(timer, timer->user_data);
-			}
-		}
-		break;
-
-	case RTGUI_EVENT_COMMAND:
-		{
-			struct rtgui_event_command *ecmd = (struct rtgui_event_command *)event;
-
-			if (ecmd->wid != RT_NULL)
-				return _rtgui_application_dest_handle(app, event);
-		}
-
-	default:
-		return rtgui_object_event_handler(object, event);
-	}
-
-	return RT_TRUE;
-}
-
-rt_inline void _rtgui_application_event_loop(struct rtgui_application *app)
-{
-	rt_err_t result;
-	rt_uint16_t current_ref;
-	struct rtgui_event *event;
-
-	_rtgui_application_check(app);
-
-	/* point to event buffer */
-	event = (struct rtgui_event*)app->event_buffer;
-
-	current_ref = ++app->ref_count;
-
-	while (current_ref <= app->ref_count)
-	{
-		RT_ASSERT(current_ref == app->ref_count);
-
-		if (app->on_idle != RT_NULL)
-		{
-			result = rtgui_application_recv_nosuspend(event, sizeof(union rtgui_event_generic));
-			if (result == RT_EOK)
-				RTGUI_OBJECT(app)->event_handler(RTGUI_OBJECT(app), event);
-			else if (result == -RT_ETIMEOUT)
-				app->on_idle(RTGUI_OBJECT(app), RT_NULL);
-		}
-		else
-		{
-			result = rtgui_application_recv(event, sizeof(union rtgui_event_generic));
-			if (result == RT_EOK)
-				RTGUI_OBJECT(app)->event_handler(RTGUI_OBJECT(app), event);
-		}
-	}
-}
-
-rt_base_t rtgui_application_run(struct rtgui_application *app)
-{
-	_rtgui_application_check(app);
-
-	app->state_flag &= ~RTGUI_APPLICATION_FLAG_EXITED;
-
-	_rtgui_application_event_loop(app);
-
-	if (app->ref_count == 0)
-		app->state_flag |= RTGUI_APPLICATION_FLAG_EXITED;
-
-	return app->exit_code;
-}
-
-void rtgui_application_exit(struct rtgui_application* app, rt_uint16_t code)
-{
-	--app->ref_count;
-	app->exit_code = code;
-}

+ 91 - 53
components/rtgui/server/server.c

@@ -16,14 +16,16 @@
 #include <rtgui/event.h>
 #include <rtgui/rtgui_system.h>
 #include <rtgui/rtgui_object.h>
-#include <rtgui/rtgui_application.h>
+#include <rtgui/rtgui_app.h>
 #include <rtgui/driver.h>
 
 #include "mouse.h"
 #include "topwin.h"
 
 static struct rt_thread *rtgui_server_tid;
-static struct rtgui_application *rtgui_server_application;
+
+static struct rtgui_app *rtgui_server_application = RT_NULL;
+static struct rtgui_app *rtgui_wm_application = RT_NULL;
 
 void rtgui_server_handle_update(struct rtgui_event_update_end* event)
 {
@@ -85,7 +87,7 @@ void rtgui_server_handle_mouse_btn(struct rtgui_event_mouse* event)
 			}
 
 			/* send to client thread */
-			rtgui_application_send(topwin->tid, &(ewin.parent), sizeof(ewin));
+			rtgui_send(topwin->tid, &(ewin.parent), sizeof(ewin));
 
 			return;
 		}
@@ -101,7 +103,7 @@ void rtgui_server_handle_mouse_btn(struct rtgui_event_mouse* event)
 		if (rtgui_topwin_get_focus() != wnd)
 		{
 			/* raise this window */
-			rtgui_topwin_activate_win(wnd);
+			rtgui_topwin_activate_topwin(wnd);
 		}
 
 		if (wnd->title != RT_NULL &&
@@ -112,7 +114,7 @@ void rtgui_server_handle_mouse_btn(struct rtgui_event_mouse* event)
 		else
 		{
 			/* send mouse event to thread */
-			rtgui_application_send(wnd->tid, (struct rtgui_event*)event, sizeof(struct rtgui_event_mouse));
+			rtgui_send(wnd->tid, (struct rtgui_event*)event, sizeof(struct rtgui_event_mouse));
 		}
 		return ;
 	}
@@ -144,7 +146,7 @@ void rtgui_server_handle_mouse_motion(struct rtgui_event_mouse* event)
 	{
 		event->wid = last_monitor_topwin->wid;
 		/* send mouse motion event */
-		rtgui_application_send(last_monitor_topwin->tid, &(event->parent), sizeof(struct rtgui_event_mouse));
+		rtgui_send(last_monitor_topwin->tid, &(event->parent), sizeof(struct rtgui_event_mouse));
 	}
 
 	if (last_monitor_topwin != win)
@@ -155,7 +157,7 @@ void rtgui_server_handle_mouse_motion(struct rtgui_event_mouse* event)
 			event->wid = last_monitor_topwin->wid;
 
 			/* send mouse motion event */
-			rtgui_application_send(last_monitor_topwin->tid, &(event->parent), sizeof(struct rtgui_event_mouse));
+			rtgui_send(last_monitor_topwin->tid, &(event->parent), sizeof(struct rtgui_event_mouse));
 		}
 	}
 
@@ -181,7 +183,7 @@ void rtgui_server_handle_kbd(struct rtgui_event_kbd* event)
 		event->wid = wnd->wid;
 
 		/* send keyboard event to thread */
-		rtgui_application_send(wnd->tid, (struct rtgui_event*)event, sizeof(struct rtgui_event_kbd));
+		rtgui_send(wnd->tid, (struct rtgui_event*)event, sizeof(struct rtgui_event_kbd));
 
 		return;
 	}
@@ -200,58 +202,113 @@ static rt_bool_t rtgui_server_event_handler(struct rtgui_object *object,
     /* dispatch event */
     switch (event->type)
     {
+    case RTGUI_EVENT_APP_CREATE:
+	case RTGUI_EVENT_APP_DESTROY:
+		if (rtgui_wm_application != RT_NULL)
+		{
+			/* forward event to wm application */
+			rtgui_send(rtgui_wm_application->tid, event, sizeof(struct rtgui_event_application));
+		}
+		else
+		{
+			/* always ack with OK */
+			rtgui_ack(event, RTGUI_STATUS_OK);
+		}
+		break;
+
+		/* mouse and keyboard event */
+    case RTGUI_EVENT_MOUSE_MOTION:
+        /* handle mouse motion event */
+        rtgui_server_handle_mouse_motion((struct rtgui_event_mouse*)event);
+        break;
+
+    case RTGUI_EVENT_MOUSE_BUTTON:
+        /* handle mouse button */
+        rtgui_server_handle_mouse_btn((struct rtgui_event_mouse*)event);
+        break;
+
+    case RTGUI_EVENT_KBD:
+        /* handle keyboard event */
+        rtgui_server_handle_kbd((struct rtgui_event_kbd*)event);
+        break;
+
 		/* window event */
     case RTGUI_EVENT_WIN_CREATE:
         if (rtgui_topwin_add((struct rtgui_event_win_create*)event) == RT_EOK)
-			rtgui_application_ack(event, RTGUI_STATUS_OK);
+			rtgui_ack(event, RTGUI_STATUS_OK);
 		else
-			rtgui_application_ack(event, RTGUI_STATUS_ERROR);
-        break;
-
-    case RTGUI_EVENT_WIN_DESTROY:
-		if (last_monitor_topwin != RT_NULL &&
-			last_monitor_topwin->wid == ((struct rtgui_event_win*)event)->wid)
-				last_monitor_topwin = RT_NULL;
-        if (rtgui_topwin_remove(((struct rtgui_event_win*)event)->wid) == RT_EOK)
-            rtgui_application_ack(event, RTGUI_STATUS_OK);
-        else
-            rtgui_application_ack(event, RTGUI_STATUS_ERROR);
+			rtgui_ack(event, RTGUI_STATUS_ERROR);
         break;
 
     case RTGUI_EVENT_WIN_SHOW:
         if (rtgui_topwin_show((struct rtgui_event_win*)event) == RT_EOK)
-            rtgui_application_ack(event, RTGUI_STATUS_OK);
+            rtgui_ack(event, RTGUI_STATUS_OK);
         else
-            rtgui_application_ack(event, RTGUI_STATUS_ERROR);
+            rtgui_ack(event, RTGUI_STATUS_ERROR);
         break;
 
     case RTGUI_EVENT_WIN_HIDE:
         if (rtgui_topwin_hide((struct rtgui_event_win*)event) == RT_EOK)
-            rtgui_application_ack(event, RTGUI_STATUS_OK);
+            rtgui_ack(event, RTGUI_STATUS_OK);
         else
-            rtgui_application_ack(event, RTGUI_STATUS_ERROR);
+            rtgui_ack(event, RTGUI_STATUS_ERROR);
         break;
 
     case RTGUI_EVENT_WIN_MOVE:
         if (rtgui_topwin_move((struct rtgui_event_win_move*)event) == RT_EOK)
-            rtgui_application_ack(event, RTGUI_STATUS_OK);
+            rtgui_ack(event, RTGUI_STATUS_OK);
         else
-            rtgui_application_ack(event, RTGUI_STATUS_ERROR);
+            rtgui_ack(event, RTGUI_STATUS_ERROR);
         break;
 
 	case RTGUI_EVENT_WIN_MODAL_ENTER:
 		if (rtgui_topwin_modal_enter((struct rtgui_event_win_modal_enter*)event) == RT_EOK)
-			rtgui_application_ack(event, RTGUI_STATUS_OK);
+			rtgui_ack(event, RTGUI_STATUS_OK);
 		else
-			rtgui_application_ack(event, RTGUI_STATUS_ERROR);
+			rtgui_ack(event, RTGUI_STATUS_ERROR);
 		break;
 
+	case RTGUI_EVENT_WIN_ACTIVATE:
+		if (rtgui_topwin_activate((struct rtgui_event_win_activate*)event) == RT_EOK)
+			rtgui_ack(event, RTGUI_STATUS_OK);
+		else
+			rtgui_ack(event, RTGUI_STATUS_ERROR);
+		break;
+
+    case RTGUI_EVENT_WIN_DESTROY:
+		if (last_monitor_topwin != RT_NULL &&
+			last_monitor_topwin->wid == ((struct rtgui_event_win*)event)->wid)
+				last_monitor_topwin = RT_NULL;
+        if (rtgui_topwin_remove(((struct rtgui_event_win*)event)->wid) == RT_EOK)
+            rtgui_ack(event, RTGUI_STATUS_OK);
+        else
+            rtgui_ack(event, RTGUI_STATUS_ERROR);
+        break;
+
     case RTGUI_EVENT_WIN_RESIZE:
         rtgui_topwin_resize(((struct rtgui_event_win_resize*)event)->wid,
                 &(((struct rtgui_event_win_resize*)event)->rect));
         break;
 
+	case RTGUI_EVENT_SET_WM:
+		if (rtgui_wm_application != RT_NULL)
+		{
+			rtgui_ack(event, RTGUI_STATUS_ERROR);
+		}
+		else
+		{
+			struct rtgui_event_set_wm *set_wm;
+
+			set_wm = (struct rtgui_event_set_wm*) event;
+			rtgui_wm_application = set_wm->app;
+			rtgui_ack(event, RTGUI_STATUS_OK);
+		}
+		break;
+
         /* other event */
+    case RTGUI_EVENT_COMMAND:
+        break;
+
     case RTGUI_EVENT_UPDATE_BEGIN:
 #ifdef RTGUI_USING_MOUSE_CURSOR
         /* hide cursor */
@@ -272,25 +329,6 @@ static rt_bool_t rtgui_server_event_handler(struct rtgui_object *object,
         /* handle mouse monitor */
         rtgui_server_handle_monitor_add((struct rtgui_event_monitor*)event);
         break;
-
-        /* mouse and keyboard event */
-    case RTGUI_EVENT_MOUSE_MOTION:
-        /* handle mouse motion event */
-        rtgui_server_handle_mouse_motion((struct rtgui_event_mouse*)event);
-        break;
-
-    case RTGUI_EVENT_MOUSE_BUTTON:
-        /* handle mouse button */
-        rtgui_server_handle_mouse_btn((struct rtgui_event_mouse*)event);
-        break;
-
-    case RTGUI_EVENT_KBD:
-        /* handle keyboard event */
-        rtgui_server_handle_kbd((struct rtgui_event_kbd*)event);
-        break;
-
-    case RTGUI_EVENT_COMMAND:
-        break;
     }
 
 	return RT_TRUE;
@@ -307,8 +345,8 @@ static void rtgui_server_entry(void* parameter)
 	SetThreadPriority(hCurrentThread, THREAD_PRIORITY_HIGHEST);
 #endif
 
-	/* register rtgui server thread */
-	rtgui_server_application = rtgui_application_create(rtgui_server_tid,
+	/* create rtgui server application */
+	rtgui_server_application = rtgui_app_create(rtgui_server_tid,
                                                         "rtgui");
     if (rtgui_server_application == RT_NULL)
         return;
@@ -321,16 +359,16 @@ static void rtgui_server_entry(void* parameter)
 	rtgui_mouse_show_cursor();
 #endif
 
-    rtgui_application_run(rtgui_server_application);
+    rtgui_app_run(rtgui_server_application);
 
-    rtgui_application_destroy(rtgui_server_application);
+    rtgui_app_destroy(rtgui_server_application);
     rtgui_server_application = RT_NULL;
 }
 
 void rtgui_server_post_event(struct rtgui_event* event, rt_size_t size)
 {
 	if (rtgui_server_tid != RT_NULL)
-		rtgui_application_send(rtgui_server_tid, event, size);
+		rtgui_send(rtgui_server_tid, event, size);
 	else
 		rt_kprintf("post when server is not running\n");
 }
@@ -338,7 +376,7 @@ void rtgui_server_post_event(struct rtgui_event* event, rt_size_t size)
 rt_err_t rtgui_server_post_event_sync(struct rtgui_event* event, rt_size_t size)
 {
 	if (rtgui_server_tid != RT_NULL)
-		return rtgui_application_send_sync(rtgui_server_tid, event, size);
+		return rtgui_send_sync(rtgui_server_tid, event, size);
 	else
 	{
 		rt_kprintf("post when server is not running\n");

+ 183 - 120
components/rtgui/server/topwin.c

@@ -19,41 +19,36 @@
 #include <rtgui/image.h>
 #include <rtgui/rtgui_theme.h>
 #include <rtgui/rtgui_system.h>
-#include <rtgui/rtgui_application.h>
+#include <rtgui/rtgui_app.h>
 #include <rtgui/widgets/window.h>
 
 /* This list is divided into two parts. The first part is the shown list, in
  * which all the windows have the WINTITLE_SHOWN flag set. Second part is the
- * hidden list, in which all the windows don't have WINTITLE_SHOWN flag.
+ * hidden items, in which all the windows don't have WINTITLE_SHOWN flag.
  *
  * The active window is the one that would receive kbd events. It should always
- * in the first tree. The order of this list is the order of the windows.
- * Thus, the first item is the top most window and the last item is the bottom
- * window. Top window can always clip the window beneath it when the two
+ * be in the first tree. The order of this list is the order of the windows.
+ * Top window can always clip the window beneath it when the two
  * overlapping. Child window can always clip it's parent. Slibing windows can
- * clip each other with the same rule as this list. Thus, each child list is
- * the same as _rtgui_topwin_list. This forms the hierarchy tree structure of
- * all windows.
+ * clip each other with the same rule as this list. Each child list is the same
+ * as _rtgui_topwin_list. This forms the hierarchy tree structure of all
+ * windows.
  *
- * The hidden list have no specific order.
+ * Thus, the left most leaf of the tree is the top most window and the right
+ * most root node is the bottom window.  The hidden part have no specific
+ * order.
  */
 static struct rtgui_dlist_node _rtgui_topwin_list;
 #define get_topwin_from_list(list_entry) \
 	(rtgui_dlist_entry((list_entry), struct rtgui_topwin, list))
 
-#ifdef RTGUI_USING_DESKTOP_WINDOW
-static struct rtgui_topwin *the_desktop_topwin;
-
-#define IS_ROOT_WIN(topwin) ((topwin)->parent == the_desktop_topwin)
-#else
 #define IS_ROOT_WIN(topwin) ((topwin)->parent == RT_NULL)
-#endif
 
 static struct rt_semaphore _rtgui_topwin_lock;
 
 static void rtgui_topwin_update_clip(void);
 static void rtgui_topwin_redraw(struct rtgui_rect* rect);
-static void _rtgui_topwin_activate_next(void);
+static void _rtgui_topwin_activate_next(enum rtgui_topwin_flag);
 
 void rtgui_topwin_init(void)
 {
@@ -113,11 +108,6 @@ rt_err_t rtgui_topwin_add(struct rtgui_event_win_create* event)
 	{
 		topwin->parent = RT_NULL;
 		rtgui_dlist_insert_before(&_rtgui_topwin_list, &topwin->list);
-#ifdef RTGUI_USING_DESKTOP_WINDOW
-		RT_ASSERT(the_desktop_topwin == RT_NULL);
-		RT_ASSERT(event->parent.user & RTGUI_WIN_STYLE_DESKTOP);
-		the_desktop_topwin = topwin;
-#endif
 	}
 	else
 	{
@@ -138,6 +128,8 @@ rt_err_t rtgui_topwin_add(struct rtgui_event_win_create* event)
 	if (event->parent.user & RTGUI_WIN_STYLE_CLOSEBOX) topwin->flag |= WINTITLE_CLOSEBOX;
 	if (!(event->parent.user & RTGUI_WIN_STYLE_NO_BORDER)) topwin->flag |= WINTITLE_BORDER;
 	if (event->parent.user & RTGUI_WIN_STYLE_NO_FOCUS) topwin->flag |= WINTITLE_NOFOCUS;
+	if (event->parent.user & RTGUI_WIN_STYLE_ONTOP) topwin->flag |= WINTITLE_ONTOP;
+	if (event->parent.user & RTGUI_WIN_STYLE_ONBTM) topwin->flag |= WINTITLE_ONBTM;
 
 	if(!(topwin->flag & WINTITLE_NO) || (topwin->flag & WINTITLE_BORDER))
 	{
@@ -195,12 +187,31 @@ static struct rtgui_topwin* _rtgui_topwin_get_topmost_child_shown(struct rtgui_t
 	return topwin;
 }
 
-static struct rtgui_topwin* _rtgui_topwin_get_topmost_window_shown(void)
+static rt_bool_t _rtgui_topwin_in_layer(struct rtgui_topwin *topwin, enum rtgui_topwin_flag flag)
 {
-	if (!(get_topwin_from_list(_rtgui_topwin_list.next)->flag & WINTITLE_SHOWN))
-		return RT_NULL;
-	else
-		return _rtgui_topwin_get_topmost_child_shown(get_topwin_from_list(_rtgui_topwin_list.next));
+	return (topwin->flag & (WINTITLE_ONTOP|WINTITLE_ONBTM))
+		    == (flag & (WINTITLE_ONTOP|WINTITLE_ONBTM));
+}
+
+/* find the topmost window shown in the layer set by flag. The flag has many
+ * other infomations but we only use the ONTOP/ONBTM */
+static struct rtgui_topwin* _rtgui_topwin_get_topmost_window_shown(enum rtgui_topwin_flag flag)
+{
+	struct rtgui_dlist_node *node;
+
+	rtgui_dlist_foreach(node, &_rtgui_topwin_list, next)
+	{
+		struct rtgui_topwin *topwin = get_topwin_from_list(node);
+
+		/* reach the hidden region no window shown in current layer */
+		if (!(topwin->flag & WINTITLE_SHOWN))
+			return RT_NULL;
+
+		if (_rtgui_topwin_in_layer(topwin, flag))
+			return _rtgui_topwin_get_topmost_child_shown(topwin);
+	}
+	/* no window in current layer is shown */
+	return RT_NULL;
 }
 
 /* a hidden parent will hide it's children. Top level window can be shown at
@@ -286,23 +297,22 @@ rt_err_t rtgui_topwin_remove(struct rtgui_win* wid)
 
 	old_focus = rtgui_topwin_get_focus();
 
-	// TODO: if the window is hidden, there is no need to update the window
-	// region
-	_rtgui_topwin_union_region_tree(topwin, &region);
-	if (topwin->flag & WINTITLE_SHOWN)
-		rtgui_topwin_update_clip();
+	/* remove the root from _rtgui_topwin_list will remove the whole tree from
+	 * _rtgui_topwin_list. */
+	rtgui_dlist_remove(&topwin->list);
 
 	if (old_focus == topwin)
 	{
-		_rtgui_topwin_activate_next();
+		_rtgui_topwin_activate_next(topwin->flag);
 	}
 
-	/* redraw the old rect */
-	rtgui_topwin_redraw(rtgui_region_extents(&region));
-
-	/* remove the root from _rtgui_topwin_list will remove the whole tree from
-	 * _rtgui_topwin_list. */
-	rtgui_dlist_remove(&topwin->list);
+	if (topwin->flag & WINTITLE_SHOWN)
+	{
+		rtgui_topwin_update_clip();
+		/* redraw the old rect */
+		_rtgui_topwin_union_region_tree(topwin, &region);
+		rtgui_topwin_redraw(rtgui_region_extents(&region));
+	}
 
 	_rtgui_topwin_free_tree(topwin);
 
@@ -327,7 +337,7 @@ static void _rtgui_topwin_only_activate(struct rtgui_topwin *topwin)
 	topwin->flag |= WINTITLE_ACTIVATE;
 
 	event.wid = topwin->wid;
-	rtgui_application_send(topwin->tid, &(event.parent), sizeof(struct rtgui_event_win));
+	rtgui_send(topwin->tid, &(event.parent), sizeof(struct rtgui_event_win));
 
 	/* redraw title */
 	if (topwin->title != RT_NULL)
@@ -336,11 +346,13 @@ static void _rtgui_topwin_only_activate(struct rtgui_topwin *topwin)
 	}
 }
 
-static void _rtgui_topwin_activate_next(void)
+/* activate next window in the same layer as flag. The flag has many other
+ * infomations but we only use the ONTOP/ONBTM */
+static void _rtgui_topwin_activate_next(enum rtgui_topwin_flag flag)
 {
 	struct rtgui_topwin *topwin;
 
-	topwin = _rtgui_topwin_get_topmost_window_shown();
+	topwin = _rtgui_topwin_get_topmost_window_shown(flag);
 	if (topwin == RT_NULL)
 		return;
 
@@ -358,7 +370,7 @@ static void _rtgui_topwin_deactivate(struct rtgui_topwin *topwin)
 
 	RTGUI_EVENT_WIN_DEACTIVATE_INIT(&event);
 	event.wid = topwin->wid;
-	rtgui_application_send(topwin->tid,
+	rtgui_send(topwin->tid,
 			&event.parent, sizeof(struct rtgui_event_win));
 
 	topwin->flag &= ~WINTITLE_ACTIVATE;
@@ -376,17 +388,6 @@ static void _rtgui_topwin_move_whole_tree2top(struct rtgui_topwin *topwin)
 
 	RT_ASSERT(topwin != RT_NULL);
 
-#ifdef RTGUI_USING_DESKTOP_WINDOW
-	/* handle desktop window separately, avoid calling
-	 * _rtgui_topwin_get_root_win */
-	if (topwin == the_desktop_topwin)
-	{
-		rtgui_dlist_remove(&the_desktop_topwin->list);
-		rtgui_dlist_insert_after(&_rtgui_topwin_list, &the_desktop_topwin->list);
-		return;
-	}
-#endif
-
 	/* move the whole tree */
 	topparent = _rtgui_topwin_get_root_win(topwin);
 	RT_ASSERT(topparent != RT_NULL);
@@ -394,20 +395,58 @@ static void _rtgui_topwin_move_whole_tree2top(struct rtgui_topwin *topwin)
 	/* remove node from hidden list */
 	rtgui_dlist_remove(&topparent->list);
 	/* add node to show list */
-#ifdef RTGUI_USING_DESKTOP_WINDOW
-	rtgui_dlist_insert_after(&the_desktop_topwin->child_list, &(topparent->list));
-#else
-	rtgui_dlist_insert_after(&_rtgui_topwin_list, &(topparent->list));
-#endif
+	if (topwin->flag & WINTITLE_ONTOP)
+	{
+		rtgui_dlist_insert_after(&_rtgui_topwin_list, &(topparent->list));
+	}
+	else if (topwin->flag & WINTITLE_ONBTM)
+	{
+		/* botton layer window, before the fisrt bottom window or hidden window. */
+		struct rtgui_topwin *ntopwin = get_topwin_from_list(&_rtgui_topwin_list);
+		struct rtgui_dlist_node *node;
+
+		rtgui_dlist_foreach(node, &_rtgui_topwin_list, next)
+		{
+			ntopwin = get_topwin_from_list(node);
+			if ((ntopwin->flag & WINTITLE_ONBTM)
+					|| !(ntopwin->flag & WINTITLE_SHOWN))
+				break;
+		}
+		/* all other windows are shown top/normal layer windows. Insert it as
+		 * the last window. */
+		if (node == &_rtgui_topwin_list)
+			rtgui_dlist_insert_before(&_rtgui_topwin_list, &(topparent->list));
+		else
+			rtgui_dlist_insert_before(&ntopwin->list, &(topparent->list));
+	}
+	else
+	{
+		/* normal layer window, before the fisrt shown normal layer window. */
+		struct rtgui_topwin *ntopwin = get_topwin_from_list(&_rtgui_topwin_list);
+		struct rtgui_dlist_node *node;
+
+		rtgui_dlist_foreach(node, &_rtgui_topwin_list, next)
+		{
+			ntopwin = get_topwin_from_list(node);
+			if (!((ntopwin->flag & WINTITLE_ONTOP)
+						&& (ntopwin->flag & WINTITLE_SHOWN)))
+				break;
+		}
+		/* all other windows are shown top layer windows. Insert it as
+		 * the last window. */
+		if (node == &_rtgui_topwin_list)
+			rtgui_dlist_insert_before(&_rtgui_topwin_list, &(topparent->list));
+		else
+			rtgui_dlist_insert_before(&ntopwin->list, &(topparent->list));
+	}
 }
 
-static void _rtgui_topwin_raise_topwin_in_tree(struct rtgui_topwin *topwin)
+static void _rtgui_topwin_raise_in_sibling(struct rtgui_topwin *topwin)
 {
 	struct rtgui_dlist_node *win_level;
 
 	RT_ASSERT(topwin != RT_NULL);
 
-	_rtgui_topwin_move_whole_tree2top(topwin);
 	if (topwin->parent == RT_NULL)
 		win_level = &_rtgui_topwin_list;
 	else
@@ -416,33 +455,64 @@ static void _rtgui_topwin_raise_topwin_in_tree(struct rtgui_topwin *topwin)
 	rtgui_dlist_insert_after(win_level, &topwin->list);
 }
 
+/* it will do 2 things. One is moving the whole tree(the root of the tree) to
+ * the front and the other is moving topwin to the front of it's siblings. */
+static void _rtgui_topwin_raise_tree_from_root(struct rtgui_topwin *topwin)
+{
+	RT_ASSERT(topwin != RT_NULL);
+
+	_rtgui_topwin_move_whole_tree2top(topwin);
+	/* root win is aleady moved by _rtgui_topwin_move_whole_tree2top */
+	if (!IS_ROOT_WIN(topwin))
+		_rtgui_topwin_raise_in_sibling(topwin);
+}
+
 /* activate a win means:
  * - deactivate the old focus win if any
  * - raise the window to the front of it's siblings
  * - activate a win
  */
-void rtgui_topwin_activate_win(struct rtgui_topwin* topwin)
+rt_err_t rtgui_topwin_activate(struct rtgui_event_win_activate* event)
+{
+	struct rtgui_topwin *topwin;
+
+	RT_ASSERT(event);
+
+	topwin = rtgui_topwin_search_in_list(event->wid, &_rtgui_topwin_list);
+	if (topwin == RT_NULL)
+		return -RT_ERROR;
+
+	return rtgui_topwin_activate_topwin(topwin);
+}
+
+rt_err_t rtgui_topwin_activate_topwin(struct rtgui_topwin* topwin)
 {
 	struct rtgui_topwin *old_focus_topwin;
 
 	RT_ASSERT(topwin != RT_NULL);
 
+	if (!(topwin->flag & WINTITLE_SHOWN))
+		return -RT_ERROR;
+
 	if (topwin->flag & WINTITLE_NOFOCUS)
 	{
 		/* just raise it, not affect others. */
-		_rtgui_topwin_raise_topwin_in_tree(topwin);
+		_rtgui_topwin_raise_tree_from_root(topwin);
 
 		/* update clip info */
 		rtgui_topwin_update_clip();
-		return;
+		return RT_EOK;
 	}
 
-	old_focus_topwin = rtgui_topwin_get_focus();
+	if (topwin->flag & WINTITLE_ACTIVATE)
+		return RT_EOK;
 
-	if (old_focus_topwin == topwin)
-		return;
+	old_focus_topwin = rtgui_topwin_get_focus();
+	/* if topwin has the focus, it shoule have WINTITLE_ACTIVATE set and
+	 * returned above. */
+	RT_ASSERT(old_focus_topwin != topwin);
 
-	_rtgui_topwin_raise_topwin_in_tree(topwin);
+	_rtgui_topwin_raise_tree_from_root(topwin);
 	/* update clip info */
 	rtgui_topwin_update_clip();
 
@@ -454,6 +524,8 @@ void rtgui_topwin_activate_win(struct rtgui_topwin* topwin)
 	}
 
 	_rtgui_topwin_only_activate(topwin);
+
+	return RT_EOK;
 }
 
 /* map func to the topwin tree in preorder.
@@ -486,6 +558,10 @@ rt_inline void _rtgui_topwin_mark_hidden(struct rtgui_topwin *topwin)
 
 rt_inline void _rtgui_topwin_mark_shown(struct rtgui_topwin *topwin)
 {
+	if (!(topwin->flag & WINTITLE_SHOWN)
+		&& RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(topwin->wid)))
+		return;
+
 	topwin->flag |= WINTITLE_SHOWN;
 	if (topwin->title != RT_NULL)
 	{
@@ -504,10 +580,12 @@ static void _rtgui_topwin_draw_tree(struct rtgui_topwin *topwin, struct rtgui_ev
 	}
 
 	epaint->wid = topwin->wid;
-	rtgui_application_send(topwin->tid, &(epaint->parent), sizeof(struct rtgui_event_paint));
+	rtgui_send(topwin->tid, &(epaint->parent), sizeof(struct rtgui_event_paint));
 
 	rtgui_dlist_foreach(node, &topwin->child_list, prev)
 	{
+		if (!(get_topwin_from_list(node)->flag & WINTITLE_SHOWN))
+			return;
 		_rtgui_topwin_draw_tree(get_topwin_from_list(node), epaint);
 	}
 }
@@ -519,7 +597,7 @@ static void _rtgui_topwin_show_tree(struct rtgui_topwin *topwin, struct rtgui_ev
 	RT_ASSERT(topwin != RT_NULL);
 	RT_ASSERT(epaint != RT_NULL);
 
-	_rtgui_topwin_raise_topwin_in_tree(topwin);
+	_rtgui_topwin_raise_tree_from_root(topwin);
 	/* we have to mark the _all_ tree before update_clip because update_clip
 	 * will stop as hidden windows */
 	_rtgui_topwin_preorder_map(topwin, _rtgui_topwin_mark_shown);
@@ -532,14 +610,6 @@ static void _rtgui_topwin_show_tree(struct rtgui_topwin *topwin, struct rtgui_ev
 	_rtgui_topwin_draw_tree(topwin, epaint);
 }
 
-/** show a window
- *
- * If any parent window in the hierarchy tree is hidden, this window won't be
- * shown. If this window could be shown, all the child windows will be shown as
- * well. The topmost child will be active.
- *
- * Top level window(parent == RT_NULL) can always be shown.
- */
 rt_err_t rtgui_topwin_show(struct rtgui_event_win* event)
 {
 	struct rtgui_topwin *topwin, *old_focus;
@@ -548,25 +618,30 @@ rt_err_t rtgui_topwin_show(struct rtgui_event_win* event)
 
 	RTGUI_EVENT_PAINT_INIT(&epaint);
 
-	/* find in hide list */
 	topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_list);
-	if (topwin == RT_NULL ||
-		!_rtgui_topwin_could_show(topwin))
+	/* no such a window recorded */
+	if (topwin == RT_NULL)
 		return -RT_ERROR;
 
+	/* if the parent is hidden, just mark it as shown. It will be shown when
+	 * the parent is shown. */
+	if (!_rtgui_topwin_could_show(topwin))
+	{
+		topwin->flag |= WINTITLE_SHOWN;
+		_rtgui_topwin_raise_in_sibling(topwin);
+
+		return -RT_ERROR;
+	}
+
 	old_focus = rtgui_topwin_get_focus();
 
 	_rtgui_topwin_show_tree(topwin, &epaint);
 
 	/* we don't want double clipping(bare rtgui_topwin_activate_win will clip),
 	 * so we have to do deactivate/activate manually. */
-	if (old_focus == RT_NULL)
-		_rtgui_topwin_only_activate(topwin);
-	else if (old_focus != topwin)
-	{
+	if (old_focus && old_focus != topwin)
 		_rtgui_topwin_deactivate(old_focus);
-		_rtgui_topwin_only_activate(topwin);
-	}
+	_rtgui_topwin_only_activate(topwin);
 
 	return RT_EOK;
 }
@@ -633,7 +708,7 @@ rt_err_t rtgui_topwin_hide(struct rtgui_event_win* event)
 
 	if (old_focus_topwin == topwin)
 	{
-		_rtgui_topwin_activate_next();
+		_rtgui_topwin_activate_next(topwin->flag);
 	}
 
 	return RT_EOK;
@@ -697,7 +772,7 @@ rt_err_t rtgui_topwin_move(struct rtgui_event_win_move* event)
 		struct rtgui_event_paint epaint;
 		RTGUI_EVENT_PAINT_INIT(&epaint);
 		epaint.wid = topwin->wid;
-		rtgui_application_send(topwin->tid, &(epaint.parent), sizeof(epaint));
+		rtgui_send(topwin->tid, &(epaint.parent), sizeof(epaint));
 	}
 
 	return RT_EOK;
@@ -772,24 +847,7 @@ static struct rtgui_topwin* _rtgui_topwin_get_focus_from_list(struct rtgui_dlist
 
 struct rtgui_topwin* rtgui_topwin_get_focus(void)
 {
-#if 1
-	// debug code
-	struct rtgui_topwin *topwin = _rtgui_topwin_get_focus_from_list(&_rtgui_topwin_list);
-
-	if (topwin != RT_NULL)
-#ifdef RTGUI_USING_DESKTOP_WINDOW
-		RT_ASSERT(topwin == the_desktop_topwin ||\
-				  get_topwin_from_list(the_desktop_topwin->child_list.next) ==
-				  _rtgui_topwin_get_root_win(topwin));
-#else
-		RT_ASSERT(get_topwin_from_list(_rtgui_topwin_list.next) ==
-				  _rtgui_topwin_get_root_win(topwin));
-#endif
-
-	return topwin;
-#else
 	return _rtgui_topwin_get_focus_from_list(&_rtgui_topwin_list);
-#endif
 }
 
 static struct rtgui_topwin* _rtgui_topwin_get_wnd_from_tree(struct rtgui_dlist_node *list,
@@ -885,7 +943,12 @@ static void rtgui_topwin_update_clip(void)
 			rtgui_graphic_driver_get_default()->height);
 
 	/* from top to bottom. */
-	top = _rtgui_topwin_get_topmost_window_shown();
+	top = _rtgui_topwin_get_topmost_window_shown(WINTITLE_ONTOP);
+	/* 0 is normal layer */
+	if (top == RT_NULL)
+		top = _rtgui_topwin_get_topmost_window_shown(0);
+	if (top == RT_NULL)
+		top = _rtgui_topwin_get_topmost_window_shown(WINTITLE_ONBTM);
 
 	while (top != RT_NULL)
 	{
@@ -906,7 +969,7 @@ static void rtgui_topwin_update_clip(void)
 
 		/* send clip event to destination window */
 		eclip.wid = top->wid;
-		rtgui_application_send(top->tid, &(eclip.parent), sizeof(struct rtgui_event_clip_info));
+		rtgui_send(top->tid, &(eclip.parent), sizeof(struct rtgui_event_clip_info));
 
 		/* move to next sibling tree */
 		if (top->parent == RT_NULL)
@@ -915,6 +978,7 @@ static void rtgui_topwin_update_clip(void)
 				top = _rtgui_topwin_get_topmost_child_shown(get_topwin_from_list(top->list.next));
 			else
 				break;
+		/* move to next slibing topwin */
 		else if (top->list.next != &top->parent->child_list &&
 			get_topwin_from_list(top->list.next)->flag & WINTITLE_SHOWN)
 			top = _rtgui_topwin_get_topmost_child_shown(get_topwin_from_list(top->list.next));
@@ -951,7 +1015,7 @@ static void _rtgui_topwin_redraw_tree(struct rtgui_dlist_node *list,
 		if (rtgui_rect_is_intersect(rect, &(topwin->extent)) == RT_EOK)
 		{
 			epaint->wid = topwin->wid;
-			rtgui_application_send(topwin->tid, &(epaint->parent), sizeof(*epaint));
+			rtgui_send(topwin->tid, &(epaint->parent), sizeof(*epaint));
 
 			/* draw title */
 			if (topwin->title != RT_NULL)
@@ -1019,7 +1083,7 @@ void rtgui_topwin_title_onmouse(struct rtgui_topwin* win, struct rtgui_event_mou
 	if (rtgui_rect_contains_point(&win->extent, event->x, event->y) == RT_EOK)
 	{
 		/* send mouse event to thread */
-		rtgui_application_send(win->tid, &(event->parent), sizeof(struct rtgui_event_mouse));
+		rtgui_send(win->tid, &(event->parent), sizeof(struct rtgui_event_mouse));
 		return;
 	}
 
@@ -1058,7 +1122,7 @@ void rtgui_topwin_title_onmouse(struct rtgui_topwin* win, struct rtgui_event_mou
 				/* send close event to window */
 				RTGUI_EVENT_WIN_CLOSE_INIT(&event);
 				event.wid = win->wid;
-				rtgui_application_send(win->tid, &(event.parent), sizeof(struct rtgui_event_win));
+				rtgui_send(win->tid, &(event.parent), sizeof(struct rtgui_event_win));
 			}
 		}
 	}
@@ -1120,19 +1184,18 @@ void rtgui_topwin_dump_tree(void)
 {
 	struct rtgui_dlist_node *node;
 
-#ifdef RTGUI_USING_DESKTOP_WINDOW
-	_rtgui_topwin_dump(the_desktop_topwin);
-	rt_kprintf("\n");
-	rtgui_dlist_foreach(node, &the_desktop_topwin->child_list, next)
-	{
-		_rtgui_topwin_dump_tree(get_topwin_from_list(node));
-		rt_kprintf("\n");
-	}
-#else
 	rtgui_dlist_foreach(node, &_rtgui_topwin_list, next)
 	{
 		_rtgui_topwin_dump_tree(get_topwin_from_list(node));
 		rt_kprintf("\n");
 	}
-#endif
 }
+
+#ifdef RT_USING_FINSH
+#include <finsh.h>
+void dump_tree()
+{
+	rtgui_topwin_dump_tree();
+}
+FINSH_FUNCTION_EXPORT(dump_tree, dump rtgui topwin tree)
+#endif

+ 2 - 2
components/rtgui/server/topwin.h

@@ -23,8 +23,8 @@
 /* add or remove a top win */
 rt_err_t rtgui_topwin_add(struct rtgui_event_win_create* event);
 rt_err_t rtgui_topwin_remove(struct rtgui_win* wid);
-
-void rtgui_topwin_activate_win(struct rtgui_topwin* win);
+rt_err_t rtgui_topwin_activate(struct rtgui_event_win_activate* event);
+rt_err_t rtgui_topwin_activate_topwin(struct rtgui_topwin* win);
 
 /* show a window */
 rt_err_t rtgui_topwin_show(struct rtgui_event_win* event);

+ 0 - 101
components/rtgui/widgets/about_view.c

@@ -1,101 +0,0 @@
-/*
- * File      : about_view.c
- * This file is part of RTGUI in RT-Thread RTOS
- * COPYRIGHT (C) 2010, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE
- *
- * Change Logs:
- * Date           Author       Notes
- * 2010-01-06     Bernard      first version
- */
-
-#include <rtgui/rtgui_theme.h>
-#include <rtgui/widgets/about_view.h>
-
-static void _rtgui_about_view_constructor(struct rtgui_about_view *view)
-{
-	/* default rect */
-	struct rtgui_rect rect = {0, 0, 200, 200};
-
-	/* set default widget rect and set event handler */
-	rtgui_object_set_event_handler(RTGUI_OBJECT(view),rtgui_about_view_event_handler);
-	rtgui_widget_set_rect(RTGUI_WIDGET(view), &rect);
-
-	RTGUI_WIDGET(view)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
-
-	view->logo = RT_NULL;
-	view->description = RT_NULL;
-
-	RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(view)) = RTGUI_ALIGN_CENTER_VERTICAL;
-}
-
-DEFINE_CLASS_TYPE(aboutview, "aboutview", 
-	RTGUI_CONTAINER_TYPE,
-	_rtgui_about_view_constructor,
-	RT_NULL,
-	sizeof(struct rtgui_about_view));
-
-void rtgui_about_view_ondraw(struct rtgui_about_view* view)
-{
-	struct rtgui_rect rect;
-	struct rtgui_dc* dc;
-
-	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view));
-	if (dc == RT_NULL) return;
-
-	rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
-	rtgui_dc_fill_rect(dc, &rect);
-
-	if (view->logo != RT_NULL)
-		rtgui_image_blit(view->logo, dc, &rect);
-
-	rect.y1 += view->logo->h + 5;
-	if (view->description != RT_NULL)
-		rtgui_dc_draw_text(dc, view->description, &rect);
-
-	rect.y1 += rtgui_dc_get_gc(dc)->font->height;
-	rtgui_dc_draw_hline(dc, rect.x1 + 3, rect.x2 - 3, rect.y1);
-	RTGUI_DC_FC(dc) = white;
-	rtgui_dc_draw_hline(dc, rect.x1 + 4, rect.x2 - 2, rect.y1 + 1);
-
-	rtgui_dc_end_drawing(dc);
-}
-
-rt_bool_t rtgui_about_view_event_handler(struct rtgui_object* widget, struct rtgui_event* event)
-{
-	struct rtgui_about_view* view = RT_NULL;
-
-	view = RTGUI_ABOUT_VIEW(widget);
-	switch (event->type)
-	{
-	case RTGUI_EVENT_PAINT:
-		rtgui_about_view_ondraw(view);
-		return RT_FALSE;
-	}
-
-    /* use view event handler */
-    return rtgui_container_event_handler(widget, event);
-}
-
-rtgui_about_view_t* rtgui_about_view_create(rtgui_image_t *logo, const char* description)
-{
-	struct rtgui_about_view* view = RT_NULL;
-
-	view = (struct rtgui_about_view*) rtgui_widget_create(RTGUI_ABOUT_VIEW_TYPE);
-	if (view != RT_NULL)
-	{
-	    view->logo = logo;
-	    view->description = description;
-	}
-
-	return view;
-}
-
-void rtgui_about_view_destroy(rtgui_about_view_t* view)
-{
-    /* destroy view */
-	rtgui_widget_destroy(RTGUI_WIDGET(view));
-}

+ 29 - 114
components/rtgui/widgets/box.c

@@ -14,73 +14,37 @@
 #include <rtgui/dc.h>
 #include <rtgui/widgets/box.h>
 
-#ifndef RTGUI_USING_SMALL_SIZE
 static void _rtgui_box_constructor(rtgui_box_t *box)
 {
 	/* init widget and set event handler */
-	rtgui_object_set_event_handler(RTGUI_OBJECT(box), rtgui_box_event_handler);
-
-	RTGUI_WIDGET(box)->flag |= RTGUI_WIDGET_FLAG_TRANSPARENT;
-	rtgui_object_set_event_handler(RTGUI_OBJECT(box), rtgui_box_event_handler);
+	rtgui_object_set_event_handler(RTGUI_OBJECT(box), RT_NULL);
 
 	/* set proper of control */
 	box->orient = RTGUI_HORIZONTAL;
 	box->border_size = RTGUI_BORDER_DEFAULT_WIDTH;
+	box->container = RT_NULL;
 }
 
 DEFINE_CLASS_TYPE(box, "box",
-	RTGUI_CONTAINER_TYPE,
+	RTGUI_OBJECT_TYPE,
 	_rtgui_box_constructor,
 	RT_NULL,
 	sizeof(struct rtgui_box));
 
-rt_bool_t rtgui_box_event_handler(struct rtgui_object *widget, rtgui_event_t *event)
-{
-	struct rtgui_box* box = (struct rtgui_box*)widget;
-
-	RT_ASSERT(box != RT_NULL);
-
-	switch (event->type)
-	{
-	case RTGUI_EVENT_RESIZE:
-		/* re-layout */
-		rtgui_box_layout(box);
-		break;
-
-	default:
-		return rtgui_container_event_handler(RTGUI_OBJECT(box), event);
-	}
-
-	return RT_FALSE;
-}
-
-struct rtgui_box* rtgui_box_create(int orientation, rtgui_rect_t* rect)
+struct rtgui_box* rtgui_box_create(int orientation, int border_size)
 {
     struct rtgui_box* box;
 
-    box = (struct rtgui_box*) rtgui_widget_create (RTGUI_BOX_TYPE);
+    box = (struct rtgui_box*) rtgui_object_create (RTGUI_BOX_TYPE);
     if (box != RT_NULL)
     {
-		/* set proper of control */
-		rtgui_widget_set_rect(RTGUI_WIDGET(box), rect);
 		box->orient = orientation;
+		box->border_size = border_size;
 	}
 
 	return box;
 }
 
-void rtgui_box_append(struct rtgui_box* box, rtgui_widget_t* widget)
-{
-	/* put to box's children list */
-	rtgui_container_add_child(RTGUI_CONTAINER(box), widget);
-}
-
-void rtgui_box_delete(struct rtgui_box* box, rtgui_widget_t* widget)
-{
-	/* remove from box's children list */
-	rtgui_container_remove_child(RTGUI_CONTAINER(box), widget);
-}
-
 static void rtgui_box_layout_vertical(rtgui_box_t* box)
 {
 	rtgui_list_t *node;
@@ -89,16 +53,18 @@ 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;
 	total_height = 0;
 	space_height = 0;
 
-	rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
+	rtgui_list_foreach(node, &(box->container->children))
 	{
 		rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
 		if (widget->align & RTGUI_ALIGN_STRETCH) space_count ++;
@@ -108,16 +74,16 @@ 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(RTGUI_WIDGET(box)->extent) - total_height - (box->border_size << 1)) / space_count;
+		space_height = (rtgui_rect_height(container_widget->extent) - total_height - (box->border_size << 1)) / space_count;
 	}
 
 	/* init (x, y) and box width */
-	next_x = RTGUI_WIDGET(box)->extent.x1 + box->border_size;
-	next_y = RTGUI_WIDGET(box)->extent.y1 + box->border_size;
-	box_width = rtgui_rect_width(RTGUI_WIDGET(box)->extent) - (box->border_size << 1);
+	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);
 
 	/* layout each widget */
-	rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
+	rtgui_list_foreach(node, &(box->container->children))
 	{
 		rtgui_rect_t *rect;
 		rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
@@ -170,7 +136,7 @@ static void rtgui_box_layout_vertical(rtgui_box_t* box)
 											&size_event.parent);
 
 		/* point to next height */
-		next_y = rect->y2;
+		next_y = rect->y2 + box->border_size;
 	}
 }
 
@@ -182,16 +148,18 @@ 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;
 	total_width = 0;
 	space_width = 0;
 
-	rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
+	rtgui_list_foreach(node, &(box->container->children))
 	{
 		rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
 		if (widget->align & RTGUI_ALIGN_STRETCH) space_count ++;
@@ -201,16 +169,16 @@ 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(RTGUI_WIDGET(box)->extent) - total_width) / space_count;
+		space_width = (rtgui_rect_width(container_widget->extent) - total_width) / space_count;
 	}
 
 	/* init (x, y) and box height */
-	next_x = RTGUI_WIDGET(box)->extent.x1 + box->border_size;
-	next_y = RTGUI_WIDGET(box)->extent.y1 + box->border_size;
-	box_height = rtgui_rect_height(RTGUI_WIDGET(box)->extent) - (box->border_size << 1);
+	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);
 
 	/* layout each widget */
-	rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
+	rtgui_list_foreach(node, &(box->container->children))
 	{
 		rtgui_rect_t *rect;
 		rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
@@ -263,7 +231,7 @@ static void rtgui_box_layout_horizontal(rtgui_box_t* box)
 											&size_event.parent);
 
 		/* point to next width */
-		next_x = rect->x2;
+		next_x = rect->x2 + box->border_size;
 	}
 }
 
@@ -271,6 +239,8 @@ void rtgui_box_layout(rtgui_box_t* box)
 {
     RT_ASSERT(box != RT_NULL);
 
+	if (box->container == RT_NULL) return;
+
 	if (box->orient & RTGUI_VERTICAL)
 	{
 		rtgui_box_layout_vertical(box);
@@ -281,64 +251,9 @@ void rtgui_box_layout(rtgui_box_t* box)
 	}
 
 	/* update box and its children clip */
-	if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(box)))
-	{
-		rtgui_widget_update_clip(RTGUI_WIDGET(box));
-	}
-}
-
-rt_uint32_t rtgui_box_get_width(rtgui_box_t* box)
-{
-	rtgui_list_t *node;
-	rt_uint32_t width;
-
-	width = 0;
-	rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
+	if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(box->container)))
 	{
-		rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
-		rt_uint32_t widget_width;
-
-		widget_width = rtgui_rect_width(widget->extent);
-		if (box->orient & RTGUI_VERTICAL)
-		{
-			/* get the max width */
-			if (width < widget_width) width = widget_width;
-		}
-		else
-		{
-			/* get the total width */
-			width += widget_width;
-		}
+		rtgui_widget_update_clip(RTGUI_WIDGET(box->container));
 	}
-
-	return width;
-}
-
-rt_uint32_t rtgui_box_get_height(rtgui_box_t* box)
-{
-	rtgui_list_t *node;
-	rt_uint32_t height;
-
-	height = 0;
-	rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
-	{
-		rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
-		rt_uint32_t widget_height;
-
-		widget_height = rtgui_rect_height(widget->extent);
-		if (box->orient & RTGUI_HORIZONTAL)
-		{
-			/* get the max height */
-			if (height < widget_height) height = widget_height;
-		}
-		else
-		{
-			/* get the total height */
-			height += widget_height;
-		}
-	}
-
-	return height;
 }
-#endif
 

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

@@ -62,7 +62,7 @@ rt_bool_t rtgui_button_event_handler(struct rtgui_object* object, struct rtgui_e
 	struct rtgui_widget *widget;
 	struct rtgui_button *btn;
 
-	RT_ASSERT(widget != RT_NULL);
+	RT_ASSERT(object != RT_NULL);
 	RT_ASSERT(event != RT_NULL);
 
 	widget = RTGUI_WIDGET(object);
@@ -189,6 +189,8 @@ rt_bool_t rtgui_button_event_handler(struct rtgui_object* object, struct rtgui_e
 
 			return RT_TRUE;
 		}
+	default:
+		return rtgui_widget_event_handler(object, event);
 	}
 
 	return RT_FALSE;

+ 2 - 0
components/rtgui/widgets/checkbox.c

@@ -92,6 +92,8 @@ rt_bool_t rtgui_checkbox_event_handler(struct rtgui_object* object, struct rtgui
 
 			return RT_TRUE;
 		}
+	default:
+		return rtgui_widget_event_handler(object, event);
 	}
 
 	return RT_FALSE;

+ 2 - 1
components/rtgui/widgets/combobox.c

@@ -38,7 +38,6 @@ rt_bool_t rtgui_combobox_pdwin_onitem(struct rtgui_object* object, struct rtgui_
 	rtgui_listbox_t* list;
 
 	RT_ASSERT(object != RT_NULL);
-	RT_ASSERT(event != RT_NULL);
 
 	widget = RTGUI_WIDGET(object);
 	list = RTGUI_LISTBOX(widget);
@@ -228,6 +227,8 @@ rt_bool_t rtgui_combobox_event_handler(struct rtgui_object* object, struct rtgui
 			}
 		}
 		break;
+	default:
+		return rtgui_widget_event_handler(object, event);
 	}
 
 	return RT_FALSE;

+ 19 - 36
components/rtgui/widgets/container.c

@@ -14,7 +14,7 @@
  */
 #include <rtgui/dc.h>
 #include <rtgui/rtgui_system.h>
-#include <rtgui/rtgui_application.h>
+#include <rtgui/rtgui_app.h>
 #include <rtgui/widgets/container.h>
 #include <rtgui/widgets/window.h>
 
@@ -25,26 +25,17 @@ static void _rtgui_container_constructor(rtgui_container_t *container)
 		rtgui_container_event_handler);
 
 	rtgui_list_init(&(container->children));
+	container->layout_box = RT_NULL;
 
-	/* container is used to 'contain'(show) widgets and dispatch events to
-	 * them, not interact with user. So no need to grab focus. If we did it,
-	 * some widget inherited from container(e.g. notebook) will grab the focus
-	 * annoyingly.
-	 *
-	 * For example, a focusable notebook N has a widget W. When the user press
-	 * W, N will gain the focus and W will lose it at first. Then N will set
-	 * focus to W because it is W that eventually interact with people. N will
-	 * yield focus and W will gain the focus again. This loop will make W
-	 * repaint twice every time user press it.
-	 *
-	 * Just eliminate it.
-	 */
-	RTGUI_WIDGET(container)->flag &= ~RTGUI_WIDGET_FLAG_FOCUSABLE;
+	RTGUI_WIDGET(container)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
 }
 
 static void _rtgui_container_destructor(rtgui_container_t *container)
 {
 	rtgui_container_destroy_children(container);
+
+	if (container->layout_box != RT_NULL)
+		rtgui_object_destroy(RTGUI_OBJECT(container->layout_box));
 }
 
 static void _rtgui_container_update_toplevel(rtgui_container_t* container)
@@ -152,15 +143,6 @@ rt_bool_t rtgui_container_event_handler(struct rtgui_object* object, struct rtgu
 		break;
 
 	case RTGUI_EVENT_KBD:
-		/* let parent to handle keyboard event */
-		if (widget->parent != RT_NULL &&
-			widget->parent != RTGUI_WIDGET(widget->toplevel) &&
-			RTGUI_OBJECT(widget->parent)->event_handler)
-		{
-			return RTGUI_OBJECT(widget->parent)->event_handler(
-					RTGUI_OBJECT(widget->parent),
-					event);
-		}
 		break;
 
 	case RTGUI_EVENT_MOUSE_BUTTON:
@@ -169,6 +151,14 @@ rt_bool_t rtgui_container_event_handler(struct rtgui_object* object, struct rtgu
 		return rtgui_container_dispatch_mouse_event(container,
 			(struct rtgui_event_mouse*)event);
 
+	case RTGUI_EVENT_SHOW:
+		rtgui_widget_onshow(RTGUI_OBJECT(container), event);
+		rtgui_container_dispatch_event(container, event);
+		break;
+	case RTGUI_EVENT_HIDE:
+		rtgui_widget_onhide(RTGUI_OBJECT(container), event);
+		rtgui_container_dispatch_event(container, event);
+		break;
 	case RTGUI_EVENT_COMMAND:
 	case RTGUI_EVENT_RESIZE:
 		rtgui_container_dispatch_event(container, event);
@@ -193,7 +183,6 @@ rtgui_container_t* rtgui_container_create(void)
 
 void rtgui_container_destroy(rtgui_container_t* container)
 {
-	rtgui_container_hide(container);
 	rtgui_widget_destroy(RTGUI_WIDGET(container));
 }
 
@@ -296,26 +285,20 @@ rtgui_widget_t* rtgui_container_get_first_child(rtgui_container_t* container)
 	return child;
 }
 
-#ifndef RTGUI_USING_SMALL_SIZE
 void rtgui_container_set_box(rtgui_container_t* container, struct rtgui_box* box)
 {
 	if (container == RT_NULL || box  == RT_NULL)
         return;
 
-	rtgui_container_add_child(RTGUI_CONTAINER(container), RTGUI_WIDGET(box));
-	rtgui_widget_set_rect(RTGUI_WIDGET(box), &(RTGUI_WIDGET(container)->extent));
+	container->layout_box = box;
+	box->container = container;
 }
-#endif
 
-void rtgui_container_hide(rtgui_container_t* container)
+void rtgui_container_layout(struct rtgui_container* container)
 {
-	if (container == RT_NULL)
+	if (container == RT_NULL || container->layout_box == RT_NULL)
 		return;
 
-	if (RTGUI_WIDGET(container)->parent == RT_NULL)
-	{
-		RTGUI_WIDGET_HIDE(RTGUI_WIDGET(container));
-		return;
-	}
+	rtgui_box_layout(container->layout_box);
 }
 

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

@@ -15,7 +15,7 @@
 #include <rtgui/rtgui_object.h>
 #include <rtgui/rtgui_system.h>
 #include <rtgui/rtgui_theme.h>
-#include <rtgui/rtgui_application.h>
+#include <rtgui/rtgui_app.h>
 
 #include <rtgui/list.h>
 #include <rtgui/image.h>
@@ -235,14 +235,14 @@ static struct rtgui_listbox_item items[] =
 };
 static void rtgui_filelist_view_clear(rtgui_filelist_view_t* view);
 
-static void rtgui_filelist_view_on_folder_item(rtgui_widget_t* widget, struct rtgui_event* event)
+static rt_bool_t rtgui_filelist_view_on_folder_item(rtgui_object_t* object, struct rtgui_event* event)
 {
 	rtgui_win_t *menu;
 	rtgui_listbox_t *listbox;
 	rtgui_filelist_view_t *view;
 
-	listbox = RTGUI_LISTBOX(widget);
-	menu = RTGUI_WIN(rtgui_widget_get_toplevel(widget));
+	listbox = RTGUI_LISTBOX(object);
+	menu = RTGUI_WIN(rtgui_widget_get_toplevel(RTGUI_WIDGET(object)));
 	view = RTGUI_FILELIST_VIEW(menu->user_data);
 
 	/* hide window */
@@ -273,12 +273,14 @@ static void rtgui_filelist_view_on_folder_item(rtgui_widget_t* widget, struct rt
 		rtgui_win_destroy(menu);
 		break;
 	}
+
+	return RT_TRUE;
 }
 
-static rt_bool_t rtgui_filelist_view_on_menu_deactivate(rtgui_widget_t* widget, struct rtgui_event* event)
+static rt_bool_t rtgui_filelist_view_on_menu_deactivate(rtgui_object_t* object, struct rtgui_event* event)
 {
 	rtgui_win_t *menu;
-	menu = RTGUI_WIN(rtgui_widget_get_toplevel(widget));
+	menu = RTGUI_WIN(rtgui_widget_get_toplevel(RTGUI_WIDGET(object)));
 
 	/* destroy menu window */
 	rtgui_win_destroy(menu);
@@ -295,7 +297,7 @@ static void rtgui_filelist_view_menu_pop(rtgui_widget_t *parent)
 	rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), &screen);
 	rtgui_rect_moveto_align(&screen, &rect, RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL);
 
-	menu = rtgui_win_create(rtgui_widget_get_toplevel(parent),
+	menu = rtgui_win_create(RTGUI_WIN(rtgui_widget_get_toplevel(parent)),
 							"Folder Menu", &rect, RTGUI_WIN_STYLE_DEFAULT);
 	if (menu != RT_NULL)
 	{
@@ -533,10 +535,12 @@ static void rtgui_filelist_view_onenturn(struct rtgui_filelist_view* view)
 	}
 }
 
-rt_bool_t rtgui_filelist_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
+rt_bool_t rtgui_filelist_view_event_handler(struct rtgui_object* object, struct rtgui_event* event)
 {
+	struct rtgui_widget *widget;
 	struct rtgui_filelist_view* view = RT_NULL;
 
+	widget = RTGUI_WIDGET(object);
 	view = RTGUI_FILELIST_VIEW(widget);
 	switch (event->type)
 	{
@@ -650,7 +654,7 @@ rt_bool_t rtgui_filelist_view_event_handler(struct rtgui_widget* widget, struct
 	}
 
     /* use view event handler */
-    return rtgui_container_event_handler(RTGUI_OBJECT(widget), event);
+    return rtgui_container_event_handler(object, event);
 }
 
 rtgui_filelist_view_t* rtgui_filelist_view_create(const char* directory,

+ 2 - 0
components/rtgui/widgets/iconbox.c

@@ -66,6 +66,8 @@ rt_bool_t rtgui_iconbox_event_handler(struct rtgui_object* object, struct rtgui_
 		}
 
 		break;
+	default:
+		return rtgui_widget_event_handler(object, event);
 	}
 
 	return RT_FALSE;

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

@@ -49,6 +49,8 @@ rt_bool_t rtgui_label_event_handler(struct rtgui_object *object, struct rtgui_ev
 	case RTGUI_EVENT_PAINT:
 		rtgui_theme_draw_label(label);
 		break;
+	default:
+		return rtgui_widget_event_handler(object, event);
 	}
 
 	return RT_FALSE;

+ 10 - 11
components/rtgui/widgets/listbox.c

@@ -267,17 +267,18 @@ rt_bool_t rtgui_listbox_event_handler(struct rtgui_object* object, struct rtgui_
             {
 				rt_int16_t old_item;
 
-				if (box->current_item == -1) 
+				if (box->current_item == -1)
 				{
 					/* set a initial item */
-					if ((box->items_count > 0) && 
+					if ((box->items_count > 0) &&
 						(ekbd->key == RTGUIK_UP || ekbd->key == RTGUIK_DOWN))
 					{
 						box->current_item = 0;
 						rtgui_listbox_update_current(box, -1);
-						break;
+						return RT_TRUE;
 					}
-					else return RT_FALSE;
+					else
+						return RT_FALSE;
 				}
 				old_item = box->current_item;
 
@@ -287,32 +288,30 @@ rt_bool_t rtgui_listbox_event_handler(struct rtgui_object* object, struct rtgui_
 					if (box->current_item - box->page_items >= 0)
 						box->current_item -= box->page_items;
 					rtgui_listbox_update_current(box, old_item);
-					return RT_FALSE;
+					return RT_TRUE;
 
                 case RTGUIK_UP:
 					if (box->current_item > 0)
 						box->current_item --;
 					rtgui_listbox_update_current(box, old_item);
-					return RT_FALSE;
+					return RT_TRUE;
 
 				case RTGUIK_RIGHT:
 					if (box->current_item + box->page_items < box->items_count - 1)
 						box->current_item += box->page_items;
 					rtgui_listbox_update_current(box, old_item);
-					return RT_FALSE;
+					return RT_TRUE;
 
                 case RTGUIK_DOWN:
 					if (box->current_item < box->items_count - 1)
 						box->current_item ++;
 					rtgui_listbox_update_current(box, old_item);
-					return RT_FALSE;
+					return RT_TRUE;
 
 				case RTGUIK_RETURN:
                     if (box->on_item != RT_NULL)
-					{
 						box->on_item(RTGUI_OBJECT(box), RT_NULL);
-					}
-					return RT_FALSE;
+					return RT_TRUE;
 
                 default:
                     break;

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

@@ -316,13 +316,13 @@ rt_bool_t rtgui_listctrl_event_handler(struct rtgui_object* object, struct rtgui
 					if (ctrl->current_item - ctrl->page_items >= 0)
 						ctrl->current_item -= ctrl->page_items;
 					rtgui_listctrl_update_current(ctrl, old_item);
-					return RT_FALSE;
+					return RT_TRUE;
 
                 case RTGUIK_UP:
 					if (ctrl->current_item > 0)
 						ctrl->current_item --;
 					rtgui_listctrl_update_current(ctrl, old_item);
-					return RT_FALSE;
+					return RT_TRUE;
 
 				case RTGUIK_RIGHT:
 					if (ctrl->current_item + ctrl->page_items < ctrl->items_count - 1)
@@ -333,18 +333,18 @@ rt_bool_t rtgui_listctrl_event_handler(struct rtgui_object* object, struct rtgui
 							ctrl->current_item = ((ctrl->current_item / ctrl->page_items) + 1) * ctrl->page_items;
 					}
 					rtgui_listctrl_update_current(ctrl, old_item);
-					return RT_FALSE;
+					return RT_TRUE;
 
                 case RTGUIK_DOWN:
 					if (ctrl->current_item < ctrl->items_count - 1)
 						ctrl->current_item ++;
 					rtgui_listctrl_update_current(ctrl, old_item);
-					return RT_FALSE;
+					return RT_TRUE;
 
 				case RTGUIK_RETURN:
                     if (ctrl->on_item != RT_NULL)
 					{
-						ctrl->on_item(RTGUI_OBJECT(ctrl), RT_NULL);
+						return ctrl->on_item(RTGUI_OBJECT(ctrl), RT_NULL);
 					}
 					return RT_FALSE;
 

+ 5 - 3
components/rtgui/widgets/menu.c

@@ -40,10 +40,12 @@ static void _rtgui_menu_destructor(rtgui_menu_t* menu)
 static rt_bool_t _rtgui_menu_onitem(struct rtgui_object* object, struct rtgui_event* event)
 {
 	struct rtgui_menu* menu;
-	RTGUI_WIDGET_EVENT_HANDLER_PREPARE
+
+	/* event will be NULL, don't check it. */
+	RT_ASSERT(object);
 
 	/* get menu */
-	menu = RTGUI_MENU(rtgui_widget_get_toplevel(widget));
+	menu = RTGUI_MENU(rtgui_widget_get_toplevel(RTGUI_WIDGET(object)));
 	if (menu->items[menu->items_list->current_item].type == RTGUI_ITEM_SUBMENU)
 	{
 		const rtgui_menu_item_t* items;
@@ -84,7 +86,7 @@ static rt_bool_t _rtgui_menu_onitem(struct rtgui_object* object, struct rtgui_ev
 	{
 		/* invoke action */
 		if (menu->items[menu->items_list->current_item].on_menuaction != RT_NULL)
-			menu->items[menu->items_list->current_item].on_menuaction(RTGUI_WIDGET(menu), RT_NULL);
+			menu->items[menu->items_list->current_item].on_menuaction(RTGUI_OBJECT(menu), RT_NULL);
 
 		/* hide sub-menu */
 		if (menu->sub_menu != RT_NULL)

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

@@ -301,12 +301,16 @@ void rtgui_notebook_set_current_by_index(struct rtgui_notebook* notebook, rt_uin
 
 	if ((index < notebook->count) && (notebook->current != index))
 	{
+		struct rtgui_widget *widget;
+
 		if (notebook->current != RTGUI_NOT_FOUND)
 			rtgui_widget_hide(notebook->childs[notebook->current].widget);
 
 		notebook->current = index;
-		rtgui_widget_show(notebook->childs[notebook->current].widget);
-		rtgui_widget_update(notebook->childs[notebook->current].widget);
+		widget = notebook->childs[notebook->current].widget;
+		rtgui_widget_show(widget);
+		rtgui_widget_update(widget);
+		rtgui_widget_focus(widget);
 	}
 }
 
@@ -319,6 +323,16 @@ struct rtgui_widget* rtgui_notebook_get_widget_at(struct rtgui_notebook* noteboo
 	return RT_NULL;
 }
 
+static rt_bool_t _rtgui_notebook_current_widget_handle(struct rtgui_notebook *notebook,
+		                                               struct rtgui_event *event)
+{
+	struct rtgui_widget *widget = rtgui_notebook_get_current(notebook);
+	if (widget && widget != RTGUI_WIDGET(notebook))
+		return RTGUI_OBJECT(widget)->event_handler(RTGUI_OBJECT(widget), event);
+	else
+		return RT_FALSE;
+}
+
 rt_bool_t rtgui_notebook_event_handler(struct rtgui_object* object, struct rtgui_event* event)
 {
 	struct rtgui_notebook* notebook;
@@ -336,17 +350,18 @@ rt_bool_t rtgui_notebook_event_handler(struct rtgui_object* object, struct rtgui
 	case RTGUI_EVENT_MOUSE_BUTTON:
 		_rtgui_notebook_onmouse(notebook, (struct rtgui_event_mouse*)event);
 		break;
+	case RTGUI_EVENT_SHOW:
+		/* show myself */
+		rtgui_widget_onshow(object, event);
+		/* show the tab widget */
+		return _rtgui_notebook_current_widget_handle(notebook, event);
+	case RTGUI_EVENT_HIDE:
+		/* hide myself */
+		rtgui_widget_onhide(object, event);
+		/* hide the tab widget */
+		return _rtgui_notebook_current_widget_handle(notebook, event);
 	case RTGUI_EVENT_KBD:
-		if (notebook->current != RTGUI_NOT_FOUND)
-		{
-			if (RTGUI_OBJECT(notebook->childs[notebook->current].widget
-						)->event_handler != RT_NULL)
-				return RTGUI_OBJECT(notebook->childs[notebook->current].widget
-						)->event_handler(
-							RTGUI_OBJECT(notebook->childs[notebook->current].widget),
-							event);
-		}
-		break;
+		return _rtgui_notebook_current_widget_handle(notebook, event);
 	default:
 		/* use parent event handler */
 		return rtgui_widget_event_handler(object, event);

+ 89 - 0
components/rtgui/widgets/panel.c

@@ -0,0 +1,89 @@
+/*
+ * File      : panel.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-07     Bernard      implement panel as a widget
+ */
+#include <rtgui/dc.h>
+#include <rtgui/widgets/panel.h>
+#include <rtgui/rtgui_system.h>
+#include <rtgui/rtgui_theme.h>
+
+static void _rtgui_panel_constructor(rtgui_panel_t *panel)
+{
+	/* init widget and set event handler */
+	rtgui_object_set_event_handler(RTGUI_OBJECT(panel), rtgui_panel_event_handler);
+
+	/* set field */
+	panel->border_style = RTGUI_BORDER_NONE;
+}
+
+DEFINE_CLASS_TYPE(panel, "panel", 
+	RTGUI_CONTAINER_TYPE,
+	_rtgui_panel_constructor,
+	RT_NULL,
+	sizeof(struct rtgui_panel));
+
+rt_bool_t rtgui_panel_event_handler(struct rtgui_object *object, struct rtgui_event* event)
+{
+	struct rtgui_panel* panel;
+
+	panel = RTGUI_PANEL(object);
+	switch (event->type)
+	{
+	case RTGUI_EVENT_PAINT:
+		{
+			struct rtgui_dc* dc;
+			struct rtgui_rect rect;
+
+			rtgui_widget_get_rect(RTGUI_WIDGET(object), &rect);
+			
+			dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(object));
+			if (dc == RT_NULL) return RT_FALSE;
+
+			rtgui_dc_fill_rect(dc, &rect);
+			// rtgui_rect_inflate(&rect, RTGUI_WIDGET(panel)->);
+			rtgui_dc_draw_border(dc, &rect, panel->border_style);
+
+			/* paint on each child */
+			rtgui_container_dispatch_event(RTGUI_CONTAINER(panel), event);
+
+			rtgui_dc_end_drawing(dc);
+		}
+		break;
+
+	default:
+		return rtgui_container_event_handler(object, event);
+	}
+
+	return RT_FALSE;
+}
+
+rtgui_panel_t* rtgui_panel_create(int border_style)
+{
+    struct rtgui_panel* panel;
+
+    panel = (struct rtgui_panel*) rtgui_widget_create(RTGUI_PANEL_TYPE);
+    if (panel != RT_NULL)
+    {
+		rtgui_rect_t rect = {0, 0, 100, 100};
+		rtgui_widget_set_rect(RTGUI_WIDGET(panel), &rect);
+
+		panel->border_style = border_style;
+    }
+
+    return panel;
+}
+
+void rtgui_panel_destroy(rtgui_panel_t* panel)
+{
+	rtgui_object_destroy(RTGUI_OBJECT(panel));
+}
+

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

@@ -38,6 +38,8 @@ rt_bool_t rtgui_progressbar_event_handler(struct rtgui_object* object,
 	case RTGUI_EVENT_PAINT:
 		rtgui_theme_draw_progressbar(bar);
 		break;
+	default:
+		return rtgui_widget_event_handler(object, event);
 	}
 
 	return RT_FALSE;

+ 15 - 1
components/rtgui/widgets/radiobox.c

@@ -101,7 +101,7 @@ rt_bool_t rtgui_radiobox_event_handler(struct rtgui_object* object, struct rtgui
 
 #ifndef RTGUI_USING_SMALL_SIZE
 		if (widget->on_key != RT_NULL)
-			widget->on_key(RTGUI_OBJECT(widget), event);
+			return widget->on_key(RTGUI_OBJECT(widget), event);
 		else
 #endif
 		{
@@ -116,12 +116,18 @@ rt_bool_t rtgui_radiobox_event_handler(struct rtgui_object* object, struct rtgui
 	            if (e->key == RTGUIK_UP)
 	            {
 	                if (radiobox->item_selection > 0)
+					{
 	                    rtgui_radiobox_set_selection(radiobox, radiobox->item_selection - 1);
+						return RT_TRUE;
+					}
 	            }
 	            else if (e->key == RTGUIK_DOWN)
 	            {
 	                if (radiobox->item_selection < radiobox->item_count - 1)
+					{
 	                    rtgui_radiobox_set_selection(radiobox, radiobox->item_selection + 1);
+						return RT_TRUE;
+					}
 	            }
 			}
 			else
@@ -129,12 +135,18 @@ rt_bool_t rtgui_radiobox_event_handler(struct rtgui_object* object, struct rtgui
 	            if (e->key == RTGUIK_LEFT)
 	            {
 	                if (radiobox->item_selection > 0)
+					{
 	                    rtgui_radiobox_set_selection(radiobox, radiobox->item_selection - 1);
+						return RT_TRUE;
+					}
 	            }
 	            else if (e->key == RTGUIK_RIGHT)
 	            {
 	                if (radiobox->item_selection < radiobox->item_count - 1)
+					{
 	                    rtgui_radiobox_set_selection(radiobox, radiobox->item_selection + 1);
+						return RT_TRUE;
+					}
 	            }
 			}
         }
@@ -150,6 +162,8 @@ rt_bool_t rtgui_radiobox_event_handler(struct rtgui_object* object, struct rtgui
 			rtgui_radiobox_onmouse(radiobox, (struct rtgui_event_mouse*)event);
 		}
 		break;
+	default:
+		return rtgui_widget_event_handler(object, event);
 	}
 
 	return RT_FALSE;

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

@@ -302,7 +302,7 @@ rt_bool_t rtgui_scrollbar_event_handler(struct rtgui_object *object,
 		break;
 
 	default:
-		break;
+		return rtgui_widget_event_handler(object, event);
 	}
 
 	return RT_FALSE;

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

@@ -168,13 +168,10 @@ rt_bool_t rtgui_slider_event_handler(struct rtgui_object *object, struct rtgui_e
 
 #ifndef RTGUI_USING_SMALL_SIZE
 		if (widget->on_key != RT_NULL)
-			widget->on_key(RTGUI_OBJECT(widget), event);
+			return widget->on_key(RTGUI_OBJECT(widget), event);
 		else
 #endif
-		{
 			return rtgui_slider_onkey(slider, (struct rtgui_event_kbd *)event);
-		}
-		break;
 
 	case RTGUI_EVENT_MOUSE_BUTTON:
 		if (!RTGUI_WIDGET_IS_ENABLE(widget) || RTGUI_WIDGET_IS_HIDE(widget)) return RT_FALSE;
@@ -188,6 +185,9 @@ rt_bool_t rtgui_slider_event_handler(struct rtgui_object *object, struct rtgui_e
 			rtgui_slider_onmouse(slider, (struct rtgui_event_mouse*)event);
 		}
 		break;
+
+	default:
+		return rtgui_widget_event_handler(object, event);
 	}
 
 	return RT_FALSE;

+ 2 - 0
components/rtgui/widgets/staticline.c

@@ -36,6 +36,8 @@ rt_bool_t rtgui_staticline_event_handler(struct rtgui_object* object, struct rtg
 #endif
 			rtgui_theme_draw_staticline(staticline);
 		break;
+	default:
+		return rtgui_widget_event_handler(object, event);
 	}
 
 	return RT_FALSE;

+ 422 - 177
components/rtgui/widgets/textbox.c

@@ -11,106 +11,197 @@
  * Date           Author       Notes
  * 2009-10-16     Bernard      first version
  * 2011-01-224    Bernard      fix backspace issue.
+ * 2012-06-09     asml         refactor
+ * 2012-06-17     Grissiom     misc cleanup and merge
  */
-#include <rtgui/dc.h>
-#include <rtgui/rtgui_theme.h>
-#include <rtgui/rtgui_system.h>
+#include <string.h>
 #include <rtgui/widgets/textbox.h>
+#include <rtgui/widgets/combobox.h>
+#include <rtgui/rtgui_system.h>
 
-#ifndef _WIN32
 #include <ctype.h>
-#endif
-
-#define RTGUI_TEXTBOX_LINE_MAX		64
-#define RTGUI_TEXTBOX_MARGIN		3
-
-static void rtgui_textbox_onkey(struct rtgui_textbox* box, struct rtgui_event_kbd* event);
-static rt_bool_t rtgui_textbox_onfocus(struct rtgui_object* object, struct rtgui_event* event);
-static rt_bool_t rtgui_textbox_onunfocus(struct rtgui_object* object, struct rtgui_event* event);
-
-static void _rtgui_textbox_caret_timeout(struct rtgui_timer* timer, void* parameter)
-{
-	rtgui_textbox_t* box;
-
-	box = (rtgui_textbox_t*)parameter;
-	/* set caret flag */
-	if (box->flag & RTGUI_TEXTBOX_CARET_SHOW)
-		box->flag &= ~RTGUI_TEXTBOX_CARET_SHOW;
-	else
-		box->flag |= RTGUI_TEXTBOX_CARET_SHOW;
-
-	/* re-darw textbox */
-	rtgui_theme_draw_textbox(box);
 
-	return ;
-}
+static void rtgui_textbox_draw_caret(rtgui_textbox_t *box, rt_uint16_t position);
+static rt_bool_t rtgui_textbox_onkey(struct rtgui_object* widget, rtgui_event_t* event);
+static rt_bool_t rtgui_textbox_onfocus(struct rtgui_object* widget, rtgui_event_t* event);
+static rt_bool_t rtgui_textbox_onunfocus(struct rtgui_object* widget, rtgui_event_t* event);
 
 static void _rtgui_textbox_constructor(rtgui_textbox_t *box)
 {
-	rtgui_rect_t rect = {0, 0, RTGUI_TEXTBOX_DEFAULT_WIDTH, RTGUI_TEXTBOX_DEFAULT_HEIGHT};
-	rtgui_widget_set_rect(RTGUI_WIDGET(box), &rect);
+	rtgui_rect_t rect;
+
+	RTGUI_WIDGET_FLAG(RTGUI_WIDGET(box)) |= RTGUI_WIDGET_FLAG_FOCUSABLE;
 
-	RTGUI_WIDGET(box)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
 	rtgui_object_set_event_handler(RTGUI_OBJECT(box), rtgui_textbox_event_handler);
 	rtgui_widget_set_onfocus(RTGUI_WIDGET(box), rtgui_textbox_onfocus);
 	rtgui_widget_set_onunfocus(RTGUI_WIDGET(box), rtgui_textbox_onunfocus);
+#ifndef RTGUI_USING_SMALL_SIZE
+	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;
 	/* set default text align */
 	RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(box)) = RTGUI_ALIGN_CENTER_VERTICAL;
-
 	/* set proper of control */
-	box->caret_timer = rtgui_timer_create(RT_TICK_PER_SECOND, RT_TIMER_FLAG_PERIODIC, 
-		_rtgui_textbox_caret_timeout, box);
+	box->caret_timer = RT_NULL;
+	box->caret = RT_NULL;
 
 	box->line = box->line_begin = box->position = 0;
 	box->flag = RTGUI_TEXTBOX_SINGLE;
-
 	/* allocate default line buffer */
 	box->text = RT_NULL;
 
-	rtgui_font_get_metrics(RTGUI_WIDGET(box)->gc.font, "h", &rect);
+	rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(box)), "H", &rect);
 	box->font_width = rtgui_rect_width(rect);
+	box->on_enter = RT_NULL;
+	box->dis_length = 0;
 }
 
-static void _rtgui_textbox_deconstructor(rtgui_textbox_t *box)
+static void _rtgui_textbox_deconstructor(rtgui_textbox_t *textbox)
 {
-	if (box->text != RT_NULL)
+	if(textbox->text != RT_NULL)
 	{
-		rt_free(box->text);
-		box->text = RT_NULL;
+		rtgui_free(textbox->text);
+		textbox->text = RT_NULL;
+	}
+	if(textbox->caret_timer != RT_NULL)
+	{
+		rtgui_timer_destory(textbox->caret_timer);
+		textbox->caret_timer = RT_NULL;
+	}
+	if(textbox->caret != RT_NULL)
+	{
+		rtgui_free(textbox->caret);
+		textbox->caret = RT_NULL;
 	}
-
-	rtgui_timer_destory(box->caret_timer);
-	box->caret_timer = RT_NULL;
 }
 
-DEFINE_CLASS_TYPE(textbox, "textbox", 
+DEFINE_CLASS_TYPE(textbox, "textbox",
 	RTGUI_WIDGET_TYPE,
 	_rtgui_textbox_constructor,
 	_rtgui_textbox_deconstructor,
 	sizeof(struct rtgui_textbox));
 
-static void rtgui_textbox_onmouse(struct rtgui_textbox* box, struct rtgui_event_mouse* event)
+static void rtgui_textbox_get_caret_rect(rtgui_textbox_t *box, rtgui_rect_t *rect, rt_uint16_t position)
+{
+	int font_h,box_h;
+	rtgui_rect_t item_rect;
+
+	RT_ASSERT(box != RT_NULL);
+
+	rtgui_widget_get_rect(RTGUI_WIDGET(box), rect);
+
+	rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(box)), "H", &item_rect);
+	font_h = rtgui_rect_height(item_rect);
+	box_h = rtgui_rect_height(*rect);
+
+	rect->x1 += position * box->font_width + 2;
+	rect->x2 = rect->x1 + 2;
+	rect->y1 += (box_h - font_h) / 2;
+	rect->y2 = rect->y1 + font_h;
+}
+
+static void rtgui_textbox_init_caret(rtgui_textbox_t *box, rt_uint16_t position)
+{
+	int x, y;
+	rtgui_color_t color;
+	rtgui_rect_t rect;
+	int ofs = 0;
+
+	RT_ASSERT(box != RT_NULL);
+
+	if (!RTGUI_WIDGET_IS_FOCUSED(RTGUI_WIDGET(box)))
+		return;
+
+	rtgui_textbox_get_caret_rect(box, &box->caret_rect, position);
+	rect = box->caret_rect;
+	rtgui_widget_rect_to_device(RTGUI_WIDGET(box), &rect);
+
+	if (box->caret == RT_NULL)
+		box->caret = rtgui_malloc(rtgui_rect_width(rect)*rtgui_rect_height(rect)*sizeof(rtgui_color_t));
+
+	for (x = rect.x1; x < rect.x2; x++)
+	{
+		for(y = rect.y1; y < rect.y2; y++)
+		{
+			rtgui_graphic_driver_get_default()->ops->get_pixel(&color, x, y);
+			*(box->caret + ofs) = color;
+			ofs++;
+		}
+	}
+}
+
+/* draw caret */
+static void rtgui_textbox_draw_caret(rtgui_textbox_t *box, rt_uint16_t position)
+{
+	int x,y;
+	rtgui_color_t color;
+	rtgui_rect_t rect;
+	int ofs = 0;
+	struct rtgui_dc *dc;
+
+	RT_ASSERT(box != RT_NULL);
+	if (box->caret == RT_NULL)
+		return;
+
+	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(box));
+	if (dc == RT_NULL)
+		return;
+
+	rect = box->caret_rect;
+
+	for(x = rect.x1; x < rect.x2; x++)
+	{
+		for(y = rect.y1; y < rect.y2; y++)
+		{
+			color = *(box->caret + ofs);
+			ofs++;
+			if(box->flag & RTGUI_TEXTBOX_CARET_SHOW)
+			{
+				color = ~color;
+			}
+			rtgui_dc_draw_color_point(dc, x, y, color);
+		}
+	}
+
+	rtgui_dc_end_drawing(dc);
+}
+
+static void rtgui_textbox_timeout(rtgui_timer_t* timer, void* parameter)
+{
+	rtgui_textbox_t* box;
+
+	box = RTGUI_TEXTBOX(parameter);
+	/* set caret flag */
+	if(box->flag & RTGUI_TEXTBOX_CARET_SHOW)
+		box->flag &= ~RTGUI_TEXTBOX_CARET_SHOW;
+	else
+		box->flag |= RTGUI_TEXTBOX_CARET_SHOW;
+	rtgui_textbox_draw_caret(box,box->position);
+}
+
+static void rtgui_textbox_onmouse(rtgui_textbox_t* box, struct rtgui_event_mouse* event)
 {
 	rt_size_t length;
+	rt_uint16_t posbak = box->position;
 
 	RT_ASSERT(box != RT_NULL);
 	RT_ASSERT(event != RT_NULL);
 
-	length = rt_strlen((const char*)box->text);
+	length = rt_strlen(box->text);
 
-	if (event->button & RTGUI_MOUSE_BUTTON_LEFT &&
-		event->button & RTGUI_MOUSE_BUTTON_DOWN)
+	if(event->button & RTGUI_MOUSE_BUTTON_LEFT && event->button & RTGUI_MOUSE_BUTTON_DOWN)
 	{
 		rt_int32_t x;
-
+		/* single line text */
 		/* set caret position */
 		x = event->x - RTGUI_WIDGET(box)->extent.x1;
-		if (x < 0)
+		if(x < 0)
 		{
 			box->position = 0;
 		}
-		else if (x > length * box->font_width)
+		else if(x > length * box->font_width)
 		{
 			box->position = length;
 		}
@@ -119,30 +210,54 @@ static void rtgui_textbox_onmouse(struct rtgui_textbox* box, struct rtgui_event_
 			box->position = x / box->font_width;
 		}
 
-		/* set caret to show */
-		box->flag |= RTGUI_TEXTBOX_CARET_SHOW;
+		if(box->flag & RTGUI_TEXTBOX_CARET_SHOW)
+		{
+			if(box->caret_timer != RT_NULL)
+				rtgui_timer_stop(box->caret_timer);
 
-		/* set widget focus */
-		rtgui_widget_focus(RTGUI_WIDGET(box));
-		/* re-draw text box */
-		rtgui_theme_draw_textbox(box);
+			box->flag &= ~RTGUI_TEXTBOX_CARET_SHOW;
+			rtgui_textbox_draw_caret(box, posbak);
+
+			if(box->caret_timer != RT_NULL)
+				rtgui_timer_start(box->caret_timer);
+		}
+
+		rtgui_textbox_init_caret(box, box->position);
+		box->flag |= RTGUI_TEXTBOX_CARET_SHOW;
+		rtgui_textbox_draw_caret(box,box->position);
 	}
 }
 
-static void rtgui_textbox_onkey(struct rtgui_textbox* box, struct rtgui_event_kbd* event)
+static rt_bool_t rtgui_textbox_onkey(struct rtgui_object* widget, rtgui_event_t* event)
 {
+	rtgui_textbox_t* box = RTGUI_TEXTBOX(widget);
+	struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
 	rt_size_t length;
+	rt_uint16_t posbak = box->position;
 
 	RT_ASSERT(box != RT_NULL);
-	RT_ASSERT(event != RT_NULL);
+	RT_ASSERT(ekbd != RT_NULL);
 
-	if (event->type != RTGUI_KEYUP)
-		return ;
+	/* handle the key at down time and nothing to do with up */
+	if (RTGUI_KBD_IS_UP(ekbd))
+		return RT_TRUE;
 
-	length = rt_strlen((const char*)box->text);
-	if (event->key == RTGUIK_DELETE)
+	if (box->dis_length == 0)
 	{
-		if (box->position == length - 1)
+		rtgui_rect_t rect;
+
+		rtgui_widget_get_rect(RTGUI_WIDGET(box), &rect);
+
+		if (box->font_width == 0)
+			return RT_FALSE;
+
+		box->dis_length = (rtgui_rect_width(rect) - 5) / box->font_width;
+	}
+
+	length = rt_strlen(box->text);
+	if(ekbd->key == RTGUIK_DELETE)
+	{/* delete latter character */
+		if(box->position == length - 1)
 		{
 			box->text[box->position] = '\0';
 		}
@@ -151,197 +266,278 @@ static void rtgui_textbox_onkey(struct rtgui_textbox* box, struct rtgui_event_kb
 			char *c;
 
 			/* remove character */
-			for (c = &box->text[box->position]; c[1] != '\0'; c++)
+			for(c = &box->text[box->position]; c[1] != '\0'; c++)
 				*c = c[1];
 			*c = '\0';
 		}
 	}
-	else if (event->key == RTGUIK_BACKSPACE)
-	{
-		if ((box->position == length - 1) && length != 1)
+	else if(ekbd->key == RTGUIK_BACKSPACE)
+	{/* delete front character */
+
+		if(box->position == length - 1)
 		{
 			box->text[box->position] = '\0';
 			box->position --;
 		}
-		else if (box->position != 0)
+		else if(box->position != 0)
 		{
 			/* remove current character */
-			char *c;
+			if(box->position != 0)
+			{
+				char *c;
 
-			/* remove character */
-			for (c = &box->text[box->position - 1]; c[1] != '\0'; c++)
-				*c = c[1];
-			*c = '\0';
+				/* remove character */
+				for(c = &box->text[box->position - 1]; c[1] != '\0'; c++)
+					*c = c[1];
+				*c = '\0';
+			}
 			box->position --;
 		}
 	}
-	else if (event->key == RTGUIK_LEFT)
-	{
-		if (box->position > 0) box->position --;
+	else if(ekbd->key == RTGUIK_LEFT)
+	{/* move to prev */
+		if(box->position > 0)
+		{
+			box->position --;
+		}
 	}
-	else if (event->key == RTGUIK_RIGHT)
-	{
-		if (box->position < length) box->position ++;
+	else if(ekbd->key == RTGUIK_RIGHT)
+	{/* move to next */
+		if(box->position < length)
+		{
+			box->position ++;
+		}
 	}
-	else if (event->key == RTGUIK_HOME)
-	{
+	else if(ekbd->key == RTGUIK_HOME)
+	{/* move cursor to start */
 		box->position = 0;
 	}
-	else if (event->key == RTGUIK_END)
-	{
+	else if(ekbd->key == RTGUIK_END)
+	{/* move cursor to end */
 		box->position = length;
 	}
-	else if (event->key == RTGUIK_RETURN)
+	else if(ekbd->key == RTGUIK_RETURN)
 	{
-		if (box->on_enter != RT_NULL)
+		if(box->on_enter != RT_NULL)
 		{
-			box->on_enter(RTGUI_WIDGET(box), RT_NULL);
+			box->on_enter(box, event);
 		}
 	}
+	else if(ekbd->key == RTGUIK_NUMLOCK)
+	{
+		/* change numlock state */
+		/*
+		extern void update_number_lock(void);
+		update_number_lock();
+		*/
+	}
 	else
 	{
-		if (isprint(event->key) || isdigit(event->key))
-		{
+		if(isprint(ekbd->key))
+		{/* it's may print character */
 			/* no buffer on this line */
-			if (length + 1 > box->line_length) return;
+			if(box->flag & RTGUI_TEXTBOX_DIGIT)
+			{/* only input digit */
+				if(!isdigit(ekbd->key))
+				{/* exception: '.' and '-' */
+					if(ekbd->key != '.' && ekbd->key !='-')return RT_FALSE;
+					if(ekbd->key == '.' && strchr(box->text,'.'))return RT_FALSE;
+
+					if(ekbd->key == '-')
+					{
+						if(length+1 > box->line_length) return RT_FALSE;
+						if(length+1 > box->dis_length) return RT_FALSE;
+
+						if(strchr(box->text,'-'))
+						{
+							char* c;
+							for(c = &box->text[0]; c != &box->text[length]; c++)
+								*c = *(c+1);
+							box->text[length] = '\0';
+							box->position --;
+							goto _exit;
+						}
+						else
+						{
+							char* c;
+							for(c = &box->text[length]; c != &box->text[0]; c--)
+								*c = *(c-1);
+							box->text[0] = '-';
+							box->text[length+1] = '\0';
+							box->position ++;
+							goto _exit;
+						}
+					}
+				}
+				//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;
 
-			if (box->position < length - 1)
+			if(box->position <= length-1)
 			{
 				char* c;
 
-				for (c = &box->text[length]; c != &box->text[box->position]; c--)
+				for(c = &box->text[length]; c != &box->text[box->position]; c--)
 					*c = *(c-1);
-				box->text[length + 1] = '\0';
+				box->text[length+1] = '\0';
 			}
 
-			box->text[box->position] = event->key;
+			box->text[box->position] = ekbd->key;
 			box->position ++;
 		}
 	}
 
-	/* set caret to show */
-	box->flag |= RTGUI_TEXTBOX_CARET_SHOW;
+_exit:
+	if(box->flag & RTGUI_TEXTBOX_CARET_SHOW)
+	{
+		if(box->caret_timer != RT_NULL)
+			rtgui_timer_stop(box->caret_timer);
 
-	/* re-draw text box */
-	rtgui_theme_draw_textbox(box);
-}
+		box->flag &= ~RTGUI_TEXTBOX_CARET_SHOW;
+		rtgui_textbox_draw_caret(box, posbak);/* refresh it */
+		if(box->caret_timer != RT_NULL)
+			rtgui_timer_start(box->caret_timer);
+	}
 
-static rt_bool_t rtgui_textbox_onfocus(struct rtgui_object* object, struct rtgui_event* event)
-{
-	struct rtgui_textbox* box;
-	RTGUI_WIDGET_EVENT_HANDLER_PREPARE
+	/* re-draw text box */
+	rtgui_textbox_ondraw(box);
 
-	box = RTGUI_TEXTBOX(object);
-	/* set caret to show */
+	rtgui_textbox_init_caret(box, box->position);
 	box->flag |= RTGUI_TEXTBOX_CARET_SHOW;
-	/* start caret timer */
-	rtgui_timer_start(box->caret_timer);
+	rtgui_textbox_draw_caret(box,box->position);
 
 	return RT_TRUE;
 }
 
-static rt_bool_t rtgui_textbox_onunfocus(struct rtgui_object* object, struct rtgui_event* event)
+static rt_bool_t rtgui_textbox_onfocus(struct rtgui_object* widget, rtgui_event_t* event)
 {
-	struct rtgui_textbox* box;
-	RTGUI_WIDGET_EVENT_HANDLER_PREPARE
+	rtgui_textbox_t* box = RTGUI_TEXTBOX(widget);
 
-	box = RTGUI_TEXTBOX(object);
-	/* stop caret timer */
-	rtgui_timer_stop(box->caret_timer);
-	/* set caret to hide */
-	box->flag &= ~RTGUI_TEXTBOX_CARET_SHOW;
+	/* 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);
+		/* set caret to show */
+		box->flag |= RTGUI_TEXTBOX_CARET_SHOW;
+		/* start caret timer */
+		if(box->caret_timer != RT_NULL)
+			rtgui_timer_start(box->caret_timer);
+	}
 
 	return RT_TRUE;
 }
 
-rt_bool_t rtgui_textbox_event_handler(struct rtgui_object* object, struct rtgui_event* event)
+static rt_bool_t rtgui_textbox_onunfocus(struct rtgui_object* widget, rtgui_event_t* event)
 {
-	struct rtgui_textbox* box;
-	RTGUI_WIDGET_EVENT_HANDLER_PREPARE
+	rtgui_textbox_t* box = RTGUI_TEXTBOX(widget);
 
-	box = RTGUI_TEXTBOX(object);
-	switch (event->type)
+	/* stop caret timer */
+	if(box->caret_timer != RT_NULL)
 	{
-	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_textbox(box);
-		break;
-
-	case RTGUI_EVENT_MOUSE_BUTTON:
-		if (!RTGUI_WIDGET_IS_ENABLE(widget) || RTGUI_WIDGET_IS_HIDE(widget)) return RT_FALSE;
-
-#ifndef RTGUI_USING_SMALL_SIZE
-		if (widget->on_mouseclick != RT_NULL)
-			widget->on_mouseclick(RTGUI_OBJECT(widget), event);
-		else
-#endif
-			rtgui_textbox_onmouse(box, (struct rtgui_event_mouse*)event);
-		return RT_TRUE;
-
-	case RTGUI_EVENT_KBD:
-		if (!RTGUI_WIDGET_IS_ENABLE(widget) || RTGUI_WIDGET_IS_HIDE(widget)) return RT_FALSE;
-
-#ifndef RTGUI_USING_SMALL_SIZE
-		if (widget->on_key != RT_NULL)
-			widget->on_key(RTGUI_OBJECT(widget), event);
-		else 
-#endif
-			rtgui_textbox_onkey(box, (struct rtgui_event_kbd*)event);
-		return RT_TRUE;
+		rtgui_timer_stop(box->caret_timer);
+		rtgui_timer_destory(box->caret_timer);
+		box->caret_timer = RT_NULL;
 	}
+	/* set caret to hide */
+	box->flag &= ~RTGUI_TEXTBOX_CARET_SHOW;
+	rtgui_textbox_draw_caret(box,box->position);
 
-	return RT_FALSE;
+	if(box->on_enter != RT_NULL)
+		box->on_enter(box,event);
+
+	return RT_TRUE;
 }
 
-struct rtgui_textbox* rtgui_textbox_create(const char* text, rt_uint8_t flag)
+rtgui_textbox_t* rtgui_textbox_create(const char* text, rt_uint32_t flag)
 {
-    struct rtgui_textbox* box;
+	rtgui_textbox_t* box;
 
-    box = (struct rtgui_textbox*) rtgui_widget_create (RTGUI_TEXTBOX_TYPE);
-    if (box != RT_NULL)
+    box = (struct rtgui_textbox*)rtgui_widget_create(RTGUI_TEXTBOX_TYPE);
+    if(box != RT_NULL)
     {
-		rtgui_rect_t rect = {0, 0, RTGUI_TEXTBOX_DEFAULT_WIDTH, RTGUI_TEXTBOX_DEFAULT_HEIGHT};
-
 		/* allocate default line buffer */
 		rtgui_textbox_set_value(box, text);
 		box->flag = flag;
-
-		rtgui_font_get_metrics(RTGUI_WIDGET(box)->gc.font, "h", &rect);
 	}
 
 	return box;
 }
 
-void rtgui_textbox_destroy(struct rtgui_textbox* box)
+void rtgui_textbox_destroy(rtgui_textbox_t* box)
 {
 	rtgui_widget_destroy(RTGUI_WIDGET(box));
 }
 
-void rtgui_textbox_set_value(struct rtgui_textbox* box, const char* text)
+void rtgui_textbox_ondraw(rtgui_textbox_t* box)
 {
-	if (box->text != RT_NULL)
+	/* draw button */
+	rtgui_rect_t rect;
+	struct rtgui_dc* dc;
+	rtgui_color_t fc;
+
+	RT_ASSERT(box != RT_NULL);
+
+	/* begin drawing */
+	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(box));
+	if (dc == RT_NULL)
+		return;
+
+	/* get widget rect */
+	rtgui_widget_get_rect(RTGUI_WIDGET(box), &rect);
+	fc = RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(box));
+
+	rtgui_rect_inflate(&rect, -1);
+
+	/* fill widget rect with white color */
+	RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(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_dc_draw_rect(dc, &rect);
+
+	/* draw text */
+	RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(box)) = fc;
+	if(box->text != RT_NULL)
 	{
-		if (box->line_length > rt_strlen(text) + 1)
+		rect.x1 += RTGUI_WIDGET_DEFAULT_MARGIN;
+		/* draw single text */
+		if(box->flag & RTGUI_TEXTBOX_MASK)
 		{
-			rt_memcpy(box->text, text, rt_strlen(text) + 1);
-			/* set current position */
-			box->position = 0;
-			return;
+			/* draw '*' */
+			rt_size_t len = rt_strlen(box->text);
+			if(len > 0)
+			{
+				char *text_mask = rtgui_malloc(len + 1);
+				rt_memset(text_mask, '*', len + 1);
+				text_mask[len] = 0;
+				rtgui_dc_draw_text(dc, text_mask, &rect);
+				rtgui_free(text_mask);
+			}
 		}
 		else
 		{
-			/* free the old text */
-			rtgui_free(box->text);
-			box->text = RT_NULL;
+			rtgui_dc_draw_text(dc, box->text, &rect);
 		}
 	}
 
-	box->line_length = RTGUI_TEXTBOX_LINE_MAX > rt_strlen(text) + 1 ?
-		RTGUI_TEXTBOX_LINE_MAX : rt_strlen(text) + 1;
+	rtgui_dc_end_drawing(dc);
+}
+
+/* set textbox text */
+void rtgui_textbox_set_value(rtgui_textbox_t* box, const char* text)
+{
+	if(box->text != RT_NULL)
+	{/* yet exist something */
+		/* free the old text */
+		rtgui_free(box->text);
+		box->text = RT_NULL;
+	}
+
+	/* no something */
+	box->line_length = ((rt_strlen(text)+1)/RTGUI_TEXTBOX_LINE_MAX+1)*RTGUI_TEXTBOX_LINE_MAX;
 
 	/* allocate line buffer */
 	box->text = rtgui_malloc(box->line_length);
@@ -351,25 +547,26 @@ void rtgui_textbox_set_value(struct rtgui_textbox* box, const char* text)
 	rt_memcpy(box->text, text, rt_strlen(text) + 1);
 
 	/* set current position */
-	box->position = 0;
+	box->position = rt_strlen(text);
 }
 
-const char* rtgui_textbox_get_value(struct rtgui_textbox* box)
+const char* rtgui_textbox_get_value(rtgui_textbox_t* box)
 {
 	return (const char*)box->text;
 }
 
-void rtgui_textbox_set_line_length(struct rtgui_textbox* box, rt_size_t length)
+void rtgui_textbox_set_line_length(rtgui_textbox_t* box, rt_size_t length)
 {
 	rt_uint8_t* new_line;
 
 	RT_ASSERT(box != RT_NULL);
 
 	/* invalid length */
-	if (length <= 0) return;
+	if(length <= 0)
+		return;
 
 	new_line = rtgui_malloc(length);
-	if (length < box->line_length)
+	if(length < box->line_length)
 	{
 		rt_memcpy(new_line, box->text, length - 1);
 		new_line[length] = '\0';
@@ -383,3 +580,51 @@ void rtgui_textbox_set_line_length(struct rtgui_textbox* box, rt_size_t length)
 	box->line_length = length;
 }
 
+/* get textbox text area */
+void rtgui_textbox_get_edit_rect(rtgui_textbox_t *box,rtgui_rect_t *rect)
+{
+	rtgui_widget_get_rect(RTGUI_WIDGET(box), rect);
+	rtgui_rect_inflate(rect,-1);
+}
+
+rt_bool_t rtgui_textbox_event_handler(struct rtgui_object *object, rtgui_event_t* event)
+{
+	rtgui_widget_t *widget = RTGUI_WIDGET(object);
+	rtgui_textbox_t* box = RTGUI_TEXTBOX(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_textbox_ondraw(box);
+			break;
+
+		case RTGUI_EVENT_MOUSE_BUTTON:
+#ifndef RTGUI_USING_SMALL_SIZE
+			if(widget->on_mouseclick != RT_NULL)
+				widget->on_mouseclick(RTGUI_OBJECT(widget), event);
+			else
+#endif
+				rtgui_textbox_onmouse(box, (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(RTGUI_OBJECT(widget), event);
+			else
+#endif
+				rtgui_textbox_onkey(RTGUI_OBJECT(box), (struct rtgui_event*)event);
+			return RT_TRUE;
+
+		default:
+			return rtgui_widget_event_handler(RTGUI_OBJECT(widget),event);
+	}
+
+	return RT_FALSE;
+}
+

+ 2 - 0
components/rtgui/widgets/textview.c

@@ -307,6 +307,8 @@ rt_bool_t rtgui_textview_event_handler(struct rtgui_object* object, struct rtgui
 		}
 		break;
 		}
+	default:
+		return rtgui_widget_event_handler(RTGUI_OBJECT(widget),event);
 	}
 
 	return RT_FALSE;

+ 55 - 21
components/rtgui/widgets/widget.c

@@ -14,7 +14,7 @@
  */
 
 #include <rtgui/dc_client.h>
-#include <rtgui/rtgui_application.h>
+#include <rtgui/rtgui_app.h>
 #include <rtgui/widgets/widget.h>
 #include <rtgui/widgets/window.h>
 #include <rtgui/widgets/container.h>
@@ -36,9 +36,7 @@ static void _rtgui_widget_constructor(rtgui_widget_t *widget)
 	widget->gc.font = rtgui_font_default();
 	widget->gc.textstyle = RTGUI_TEXTSTYLE_NORMAL;
 	widget->gc.textalign = RTGUI_ALIGN_LEFT | RTGUI_ALIGN_TOP;
-#ifndef RTGUI_USING_SMALL_SIZE
 	widget->align = RTGUI_ALIGN_LEFT | RTGUI_ALIGN_TOP;
-#endif
 
 	/* set parent and toplevel root */
 	widget->parent        = RT_NULL;
@@ -88,7 +86,7 @@ static void _rtgui_widget_destructor(rtgui_widget_t *widget)
 	rtgui_region_fini(&(widget->clip));
 }
 
-DEFINE_CLASS_TYPE(widget, "widget", 
+DEFINE_CLASS_TYPE(widget, "widget",
 	RTGUI_OBJECT_TYPE,
 	_rtgui_widget_constructor,
 	_rtgui_widget_destructor,
@@ -114,11 +112,9 @@ void rtgui_widget_set_rect(rtgui_widget_t* widget, const rtgui_rect_t* rect)
 
 	widget->extent = *rect;
 
-#ifndef RTGUI_USING_SMALL_SIZE
 	/* reset mini width and height */
 	widget->mini_width  = rtgui_rect_width(widget->extent);
 	widget->mini_height = rtgui_rect_height(widget->extent);
-#endif
 
 	/* it's not empty, fini it */
 	if (rtgui_region_not_empty(&(widget->clip)))
@@ -166,7 +162,6 @@ void rtgui_widget_get_extent(rtgui_widget_t* widget, rtgui_rect_t *rect)
 	*rect = widget->extent;
 }
 
-#ifndef RTGUI_USING_SMALL_SIZE
 void rtgui_widget_set_miniwidth(rtgui_widget_t* widget, int width)
 {
 	RT_ASSERT(widget != RT_NULL);
@@ -180,7 +175,6 @@ void rtgui_widget_set_miniheight(rtgui_widget_t* widget, int height)
 
 	widget->mini_height = height;
 }
-#endif
 
 /*
  * This function moves widget and its children to a logic point
@@ -410,16 +404,16 @@ struct rtgui_win* rtgui_widget_get_toplevel(rtgui_widget_t* widget)
 
 rt_bool_t rtgui_widget_event_handler(struct rtgui_object* object, rtgui_event_t* event)
 {
-#ifndef RTGUI_USING_SMALL_SIZE
-	struct rtgui_widget *widget;
-
 	RT_ASSERT(object != RT_NULL);
 	RT_ASSERT(event != RT_NULL);
 
-	widget = RTGUI_WIDGET(object);
-
 	switch (event->type)
 	{
+	case RTGUI_EVENT_SHOW:
+		return rtgui_widget_onshow(object, event);
+	case RTGUI_EVENT_HIDE:
+		return rtgui_widget_onhide(object, event);
+#ifndef RTGUI_USING_SMALL_SIZE
 	case RTGUI_EVENT_PAINT:
 		if (widget->on_draw != RT_NULL)
 			return widget->on_draw(RTGUI_OBJECT(widget), event);
@@ -444,8 +438,8 @@ rt_bool_t rtgui_widget_event_handler(struct rtgui_object* object, rtgui_event_t*
 		if (widget->on_size != RT_NULL)
 			return widget->on_size(RTGUI_OBJECT(widget), event);
 		break;
-	}
 #endif
+	}
 
 	return RT_FALSE;
 }
@@ -512,12 +506,26 @@ void rtgui_widget_update_clip(rtgui_widget_t* widget)
 	}
 }
 
-void rtgui_widget_show(rtgui_widget_t* widget)
+void rtgui_widget_show(struct rtgui_widget *widget)
 {
-	/* there is no parent or the parent is hide, no show at all */
-	if (widget->parent == RT_NULL ||
-			RTGUI_WIDGET_IS_HIDE(widget->parent))
-		return;
+	struct rtgui_event_show eshow;
+	RT_ASSERT(widget != RT_NULL);
+
+    if (!RTGUI_WIDGET_IS_HIDE(widget))
+        return;
+
+	RTGUI_EVENT_SHOW_INIT(&eshow);
+	if (RTGUI_OBJECT(widget)->event_handler != RT_NULL)
+	{
+		RTGUI_OBJECT(widget)->event_handler(
+				RTGUI_OBJECT(widget),
+				&eshow);
+	}
+}
+
+rt_bool_t rtgui_widget_onshow(struct rtgui_object *object, struct rtgui_event *event)
+{
+	struct rtgui_widget *widget = RTGUI_WIDGET(object);
 
 	/* update the clip info of widget */
 	RTGUI_WIDGET_UNHIDE(widget);
@@ -525,10 +533,14 @@ void rtgui_widget_show(rtgui_widget_t* widget)
 
 	if (widget->on_show != RT_NULL)
 		widget->on_show(RTGUI_OBJECT(widget), RT_NULL);
+
+	return RT_FALSE;
 }
 
-void rtgui_widget_hide(rtgui_widget_t* widget)
+rt_bool_t rtgui_widget_onhide(struct rtgui_object *object, struct rtgui_event *event)
 {
+	struct rtgui_widget *widget = RTGUI_WIDGET(object);
+
 	/* hide this widget */
 	RTGUI_WIDGET_HIDE(widget);
 
@@ -549,12 +561,31 @@ void rtgui_widget_hide(rtgui_widget_t* widget)
 
 	if (widget->on_hide != RT_NULL)
 		widget->on_hide(RTGUI_OBJECT(widget), RT_NULL);
+
+	return RT_FALSE;
+}
+
+void rtgui_widget_hide(struct rtgui_widget *widget)
+{
+	struct rtgui_event_hide ehide;
+	RT_ASSERT(widget != RT_NULL);
+
+    if (RTGUI_WIDGET_IS_HIDE(widget))
+        return;
+
+	RTGUI_EVENT_HIDE_INIT(&ehide);
+	if (RTGUI_OBJECT(widget)->event_handler != RT_NULL)
+	{
+		RTGUI_OBJECT(widget)->event_handler(
+				RTGUI_OBJECT(widget),
+				&ehide);
+	}
 }
 
 rtgui_color_t rtgui_widget_get_parent_foreground(rtgui_widget_t* widget)
 {
 	rtgui_widget_t* parent;
-	
+
 	/* get parent widget */
 	parent = widget->parent;
 	while (parent->parent != RT_NULL && (RTGUI_WIDGET_FLAG(parent) & RTGUI_WIDGET_FLAG_TRANSPARENT))
@@ -591,6 +622,9 @@ void rtgui_widget_update(rtgui_widget_t* widget)
 
 	RT_ASSERT(widget != RT_NULL);
 
+    if (RTGUI_WIDGET_IS_HIDE(widget))
+        return;
+
 	if (RTGUI_OBJECT(widget)->event_handler != RT_NULL)
 	{
 		RTGUI_OBJECT(widget)->event_handler(

+ 82 - 64
components/rtgui/widgets/window.c

@@ -16,7 +16,7 @@
 #include <rtgui/image.h>
 #include <rtgui/rtgui_system.h>
 #include <rtgui/rtgui_server.h>
-#include <rtgui/rtgui_application.h>
+#include <rtgui/rtgui_app.h>
 
 #include <rtgui/widgets/window.h>
 #include <rtgui/widgets/button.h>
@@ -108,10 +108,6 @@ DEFINE_CLASS_TYPE(win, "win",
 	_rtgui_win_destructor,
 	sizeof(struct rtgui_win));
 
-#ifdef RTGUI_USING_DESKTOP_WINDOW
-static struct rtgui_win *the_desktop_window;
-#endif
-
 rtgui_win_t* rtgui_win_create(struct rtgui_win* parent_window,
 		                      const char* title,
 							  rtgui_rect_t *rect,
@@ -125,23 +121,7 @@ rtgui_win_t* rtgui_win_create(struct rtgui_win* parent_window,
 		return RT_NULL;
 
 	/* set parent toplevel */
-#ifdef RTGUI_USING_DESKTOP_WINDOW
-	if (style & RTGUI_WIN_STYLE_DESKTOP)
-	{
-		RT_ASSERT(the_desktop_window == RT_NULL);
-		win->parent_window = RT_NULL;
-		the_desktop_window = win;
-	}
-	else if (parent_window == RT_NULL)
-	{
-		RT_ASSERT(the_desktop_window != RT_NULL);
-		win->parent_window = the_desktop_window;
-	}
-	else
-		win->parent_window = parent_window;
-#else
 	win->parent_window = parent_window;
-#endif
 
 	/* set title, rect and style */
 	if (title != RT_NULL)
@@ -163,25 +143,13 @@ __on_err:
 	return RT_NULL;
 }
 
-void rtgui_win_destroy(struct rtgui_win* win)
-{
-	if (win->flag & RTGUI_WIN_FLAG_MODAL)
-	{
-		/* set the RTGUI_WIN_STYLE_DESTROY_ON_CLOSE flag so the window will be
-		 * destroyed after the event_loop */
-		win->style |= RTGUI_WIN_STYLE_DESTROY_ON_CLOSE;
-		rtgui_win_end_modal(win, RTGUI_MODAL_CANCEL);
-	}
-	else
-		rtgui_widget_destroy(RTGUI_WIDGET(win));
-}
-
 static rt_bool_t _rtgui_win_deal_close(struct rtgui_win *win,
-									   struct rtgui_event *event)
+									   struct rtgui_event *event,
+									   rt_bool_t force_close)
 {
 	if (win->on_close != RT_NULL)
 	{
-		if (win->on_close(RTGUI_OBJECT(win), event) == RT_FALSE)
+		if ((win->on_close(RTGUI_OBJECT(win), event) == RT_FALSE) && !force_close)
 			return RT_FALSE;
 	}
 
@@ -201,6 +169,42 @@ static rt_bool_t _rtgui_win_deal_close(struct rtgui_win *win,
 	return RT_TRUE;
 }
 
+void rtgui_win_destroy(struct rtgui_win* win)
+{
+	/* close the window first if it's not. */
+	if (!(win->flag & RTGUI_WIN_FLAG_CLOSED))
+	{
+		struct rtgui_event_win_close eclose;
+
+		RTGUI_EVENT_WIN_CLOSE_INIT(&eclose);
+		eclose.wid = win;
+
+		if (win->style & RTGUI_WIN_STYLE_DESTROY_ON_CLOSE)
+		{
+			_rtgui_win_deal_close(win,
+					(struct rtgui_event*)&eclose,
+					RT_TRUE);
+			return;
+		}
+		else
+			_rtgui_win_deal_close(win,
+					(struct rtgui_event*)&eclose,
+					RT_TRUE);
+	}
+
+	if (win->flag & RTGUI_WIN_FLAG_MODAL)
+	{
+		/* set the RTGUI_WIN_STYLE_DESTROY_ON_CLOSE flag so the window will be
+		 * destroyed after the event_loop */
+		win->style |= RTGUI_WIN_STYLE_DESTROY_ON_CLOSE;
+		rtgui_win_end_modal(win, RTGUI_MODAL_CANCEL);
+	}
+	else
+	{
+		rtgui_widget_destroy(RTGUI_WIDGET(win));
+	}
+}
+
 /* send a close event to myself to get a consistent behavior */
 rt_bool_t rtgui_win_close(struct rtgui_win* win)
 {
@@ -209,14 +213,17 @@ rt_bool_t rtgui_win_close(struct rtgui_win* win)
 	RTGUI_EVENT_WIN_CLOSE_INIT(&eclose);
 	eclose.wid = win;
 	return _rtgui_win_deal_close(win,
-								 (struct rtgui_event*)&eclose);
+								 (struct rtgui_event*)&eclose,
+								 RT_FALSE);
 }
 
 rt_base_t rtgui_win_show(struct rtgui_win* win, rt_bool_t is_modal)
 {
-	struct rtgui_event_win_show eshow;
 	rt_base_t exit_code = -1;
+	struct rtgui_app *app;
+	struct rtgui_event_win_show eshow;
 
+	app = rtgui_app_self();
 	RTGUI_EVENT_WIN_SHOW_INIT(&eshow);
 	eshow.wid = win;
 
@@ -230,29 +237,33 @@ rt_base_t rtgui_win_show(struct rtgui_win* win, rt_bool_t is_modal)
 			return exit_code;
 	}
 
+	/* set window unhidden before notify the server */
+	rtgui_widget_show(RTGUI_WIDGET(win));
+
 	if (rtgui_server_post_event_sync(RTGUI_EVENT(&eshow),
-									 sizeof(struct rtgui_event_win_show)
-			) != RT_EOK)
+		sizeof(struct rtgui_event_win_show)) != RT_EOK)
 	{
-		rt_kprintf("show win failed\n");
+		/* It could not be shown if a parent window is hidden. */
+		rtgui_widget_hide(RTGUI_WIDGET(win));
 		return exit_code;
 	}
 
-	/* set window unhidden */
-	RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(win));
-
 	if (win->focused_widget == RT_NULL)
 		rtgui_widget_focus(RTGUI_WIDGET(win));
 
+	/* set main window */
+	if (app->main_object == RT_NULL)
+		rtgui_app_set_main_win(win);
+
     if (is_modal == RT_TRUE)
     {
-		struct rtgui_application *app;
+		struct rtgui_app *app;
 		struct rtgui_event_win_modal_enter emodal;
 
 		RTGUI_EVENT_WIN_MODAL_ENTER_INIT(&emodal);
 		emodal.wid = win;
 
-		app = rtgui_application_self();
+		app = rtgui_app_self();
 		RT_ASSERT(app != RT_NULL);
 
 		win->flag |= RTGUI_WIN_FLAG_MODAL;
@@ -263,7 +274,7 @@ rt_base_t rtgui_win_show(struct rtgui_win* win, rt_bool_t is_modal)
 
 		app->modal_object = RTGUI_OBJECT(win);
 
-		exit_code = rtgui_application_run(app);
+		exit_code = rtgui_app_run(app);
 
 		app->modal_object = RT_NULL;
 		win->flag &= ~RTGUI_WIN_FLAG_MODAL;
@@ -282,7 +293,7 @@ void rtgui_win_end_modal(struct rtgui_win* win, rtgui_modal_code_t modal_code)
 	if (win == RT_NULL || !(win->flag & RTGUI_WIN_FLAG_MODAL))
 		return;
 
-	rtgui_application_exit(rtgui_application_self(), modal_code);
+	rtgui_app_exit(rtgui_app_self(), modal_code);
 
 	/* remove modal mode */
 	win->flag &= ~RTGUI_WIN_FLAG_MODAL;
@@ -291,9 +302,6 @@ void rtgui_win_end_modal(struct rtgui_win* win, rtgui_modal_code_t modal_code)
 void rtgui_win_hiden(struct rtgui_win* win)
 {
 	RT_ASSERT(win != RT_NULL);
-#ifdef RTGUI_USING_DESKTOP_WINDOW
-	RT_ASSERT(win != the_desktop_window);
-#endif
 
 	if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(win)) &&
 		win->flag & RTGUI_WIN_FLAG_CONNECTED)
@@ -310,12 +318,21 @@ void rtgui_win_hiden(struct rtgui_win* win)
 			return;
 		}
 
-		/* set window hide and deactivated */
-		RTGUI_WIDGET_HIDE(RTGUI_WIDGET(win));
+		rtgui_widget_hide(RTGUI_WIDGET(win));
 		win->flag &= ~RTGUI_WIN_FLAG_ACTIVATE;
 	}
 }
 
+rt_err_t rtgui_win_activate(struct rtgui_win *win)
+{
+	struct rtgui_event_win_activate eact;
+	RTGUI_EVENT_WIN_ACTIVATE_INIT(&eact);
+	eact.wid = win;
+
+	return rtgui_server_post_event_sync(RTGUI_EVENT(&eact),
+									    sizeof(eact));
+}
+
 rt_bool_t rtgui_win_is_activated(struct rtgui_win* win)
 {
 	RT_ASSERT(win != RT_NULL);
@@ -341,7 +358,7 @@ void rtgui_win_move(struct rtgui_win* win, int x, int y)
 	if (win->flag & RTGUI_WIN_FLAG_CONNECTED)
 	{
 		/* set win hide firstly */
-		RTGUI_WIDGET_HIDE(RTGUI_WIDGET(win));
+		rtgui_widget_hide(RTGUI_WIDGET(win));
 
 		emove.wid	= win;
 		emove.x		= x;
@@ -354,7 +371,7 @@ void rtgui_win_move(struct rtgui_win* win, int x, int y)
 	}
 
 	/* set window visible */
-	RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(win));
+	rtgui_widget_show(RTGUI_WIDGET(win));
 	return;
 }
 
@@ -405,7 +422,7 @@ rt_bool_t rtgui_win_event_handler(struct rtgui_object* object, struct rtgui_even
 		break;
 
 	case RTGUI_EVENT_WIN_CLOSE:
-		_rtgui_win_deal_close(win, event);
+		_rtgui_win_deal_close(win, event, RT_FALSE);
 		/* don't broadcast WIN_CLOSE event to others */
 		return RT_TRUE;
 
@@ -522,20 +539,21 @@ rt_bool_t rtgui_win_event_handler(struct rtgui_object* object, struct rtgui_even
 		/* we should dispatch key event firstly */
 		if (!(win->flag & RTGUI_WIN_FLAG_HANDLE_KEY))
 		{
+			struct rtgui_widget *widget;
 			rt_bool_t res = RT_FALSE;
 			/* we should dispatch the key event just once. Once entered the
 			 * dispatch mode, we should swtich to key handling mode. */
 			win->flag |= RTGUI_WIN_FLAG_HANDLE_KEY;
 
 			/* dispatch the key event */
-			if (win->focused_widget != RT_NULL &&
-					RTGUI_OBJECT(win->focused_widget)->event_handler != RT_NULL)
-				res = RTGUI_OBJECT(win->focused_widget)->event_handler(
-						RTGUI_OBJECT(win->focused_widget), event);
-
-			/* if the focused widget doesn't handle it, I will handle it. */
-			if (res != RT_TRUE && win->on_key != RT_NULL)
-				res = win->on_key(RTGUI_OBJECT(win), event);
+			for (widget = win->focused_widget;
+				 widget && !res;
+				 widget = widget->parent)
+			{
+				if (RTGUI_OBJECT(widget)->event_handler != RT_NULL)
+					res = RTGUI_OBJECT(widget)->event_handler(
+							RTGUI_OBJECT(widget), event);
+			}
 
 			win->flag &= ~RTGUI_WIN_FLAG_HANDLE_KEY;
 			return res;

+ 1 - 0
examples/gui/SConscript

@@ -36,6 +36,7 @@ demo_view_combobox.c
 demo_view_slider.c
 demo_view_notebook.c
 demo_view_mywidget.c
+demo_view_box.c
 mywidget.c
 """)
 

+ 13 - 12
examples/gui/demo_application.c

@@ -1,6 +1,6 @@
 #include <rtgui/rtgui.h>
 #include <rtgui/rtgui_system.h>
-#include <rtgui/rtgui_application.h>
+#include <rtgui/rtgui_app.h>
 
 #include <rtgui/widgets/window.h>
 #include <rtgui/widgets/notebook.h>
@@ -11,7 +11,7 @@ static rt_bool_t demo_handle_key(struct rtgui_object* object, struct rtgui_event
 {
 	struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
 
-	if (ekbd->type == RTGUI_KEYDOWN)
+	if (ekbd->type == RTGUI_KEYUP)
 	{
 		if (ekbd->key == RTGUIK_RIGHT)
 		{
@@ -30,10 +30,10 @@ static rt_bool_t demo_handle_key(struct rtgui_object* object, struct rtgui_event
 struct rtgui_win *main_win;
 static void application_entry(void* parameter)
 {
-	struct rtgui_application *app;
+	struct rtgui_app *app;
 	struct rtgui_rect rect;
 
-	app = rtgui_application_create(rt_thread_self(), "gui_demo");
+	app = rtgui_app_create(rt_thread_self(), "gui_demo");
 	if (app == RT_NULL)
 		return;
 
@@ -41,11 +41,10 @@ static void application_entry(void* parameter)
 	rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), &rect);
 
 	main_win = rtgui_win_create(RT_NULL, "demo_win", &rect,
-						/*RTGUI_WIN_STYLE_DESKTOP_DEFAULT);*/
-						RTGUI_WIN_STYLE_NO_BORDER | RTGUI_WIN_STYLE_NO_TITLE);
+                        RTGUI_WIN_STYLE_NO_BORDER | RTGUI_WIN_STYLE_NO_TITLE);
 	if (main_win == RT_NULL)
 	{
-		rtgui_application_destroy(app);
+		rtgui_app_destroy(app);
 		return;
 	}
 
@@ -56,12 +55,14 @@ static void application_entry(void* parameter)
 	if (the_notebook == RT_NULL)
 	{
 		rtgui_win_destroy(main_win);
-		rtgui_application_destroy(app);
+		rtgui_app_destroy(app);
 		return;
 	}
 
 	rtgui_container_add_child(RTGUI_CONTAINER(main_win), RTGUI_WIDGET(the_notebook));
 
+	demo_view_box();
+
 	/* 初始化各个例子的视图 */
 	demo_view_benchmark();
 
@@ -112,12 +113,12 @@ static void application_entry(void* parameter)
 	rtgui_win_show(main_win, RT_FALSE);
 
 	/* 执行工作台事件循环 */
-	rtgui_application_run(app);
+	rtgui_app_run(app);
 
-	rtgui_application_destroy(app);
+	rtgui_app_destroy(app);
 }
 
-void application_init(void)
+void application_init()
 {
 	static rt_bool_t inited = RT_FALSE;
 
@@ -138,7 +139,7 @@ void application_init(void)
 
 #ifdef RT_USING_FINSH
 #include <finsh.h>
-void application(void)
+void application()
 {
 	application_init();
 }

+ 0 - 4
examples/gui/demo_listview_icon.c

@@ -45,11 +45,7 @@ static void listitem_action(rtgui_widget_t* widget, void* parameter)
 }
 
 /* 返回功能的动作函数 */
-#if RT_VERSION == 4
 static void return_action(rtgui_widget_t* widget, void* parameter)
-#else
-static void return_action(void* parameter)
-#endif
 {
 	/* 退出模态显示 */
 	rtgui_container_end_modal(RTGUI_CONTAINER(_view), RTGUI_MODAL_OK);

+ 3 - 3
examples/gui/demo_view.c

@@ -1,10 +1,11 @@
 #include <rtgui/rtgui.h>
-#include <rtgui/rtgui_application.h>
+#include <rtgui/rtgui_app.h>
 
 #include <rtgui/widgets/container.h>
 #include <rtgui/widgets/notebook.h>
 #include <rtgui/widgets/button.h>
 #include <rtgui/widgets/staticline.h>
+#include <rtgui/widgets/box.h>
 
 extern struct rtgui_notebook *the_notebook;
 
@@ -130,7 +131,6 @@ void demo_view_get_logic_rect(rtgui_container_t* container, rtgui_rect_t *rect)
 
 /* 当是标准版本时,这个函数用于返回自动布局引擎box控件 */
 #ifndef RTGUI_USING_SMALL_SIZE
-#include <rtgui/widgets/box.h>
 struct rtgui_box* demo_view_create_box(struct rtgui_container *container, int orient)
 {
 	rtgui_rect_t rect;
@@ -142,7 +142,7 @@ struct rtgui_box* demo_view_create_box(struct rtgui_container *container, int or
 	rect.y2 -= 25;
 
 	/* 创建一个自动布局引擎 */
-	box = rtgui_box_create(orient, &rect);
+	box = rtgui_box_create(orient, 5);
 	/* 添加box控件到视图中 */
 	rtgui_container_add_child(container, RTGUI_WIDGET(box));
 

+ 1 - 1
examples/gui/demo_view.h

@@ -15,7 +15,7 @@
 #define __DEMO_VIEW_H__
 
 #include <rtgui/rtgui.h>
-#include <rtgui/rtgui_application.h>
+#include <rtgui/rtgui_app.h>
 #include <rtgui/widgets/container.h>
 
 /* 如果是标准版本,可以启用box自动布局引擎 */

+ 13 - 2
examples/gui/demo_view_benchmark.c

@@ -74,18 +74,21 @@ rt_bool_t benchmark_event_handler(struct rtgui_object *object, rtgui_event_t *ev
 	{
 		struct rtgui_event_kbd *kbd = (struct rtgui_event_kbd*)event;
 
+		if (kbd->key == RTGUIK_LEFT || kbd->key == RTGUIK_RIGHT)
+			return RT_FALSE;
+
 		if (RTGUI_KBD_IS_UP(kbd))
 		{
 			if (running)
 			{
 				/* stop */
-				rtgui_application_set_onidle(RT_NULL);
+				rtgui_app_set_onidle(RT_NULL);
 				_draw_default(object, event);
 			}
 			else
 			{
 				/* run */
-				rtgui_application_set_onidle(_onidle);
+				rtgui_app_set_onidle(_onidle);
 			}
 
 			running = !running;
@@ -101,11 +104,19 @@ rt_bool_t benchmark_event_handler(struct rtgui_object *object, rtgui_event_t *ev
 	return RT_FALSE;
 }
 
+static rt_bool_t _benchmark_onshow(struct rtgui_object *obj, struct rtgui_event* ev)
+{
+	rtgui_widget_focus(RTGUI_WIDGET(obj));
+	return RT_TRUE;
+}
+
 rtgui_container_t *demo_view_benchmark(void)
 {
 	srand(100);
 	container = demo_view("»æÍ¼²âÊÔ");
+	RTGUI_WIDGET(container)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
 	rtgui_object_set_event_handler(RTGUI_OBJECT(container), benchmark_event_handler);
+	rtgui_widget_set_onshow(RTGUI_WIDGET(container), _benchmark_onshow);
 
 	return container;
 }

+ 33 - 4
examples/gui/demo_view_box.c

@@ -1,15 +1,44 @@
 #include "demo_view.h"
-#ifndef RTGUI_USING_SMALL_SIZE
 #include <rtgui/widgets/box.h>
+#include <rtgui/widgets/panel.h>
+#include <rtgui/widgets/label.h>
+#include <rtgui/widgets/button.h>
 
-rtgui_container_t* demo_view_box(rtgui_workbench_t* workbench)
+rtgui_container_t* demo_view_box(void)
 {
     rtgui_rect_t  rect;
     rtgui_container_t* view;
+	struct rtgui_panel *panel;
+	struct rtgui_box *box;
 
-    view = demo_view(workbench, "Box View");
+	struct rtgui_label *label;
+	struct rtgui_button *button;
+
+    view = demo_view("Box View");
     demo_view_get_rect(view, &rect);
 
+	panel = rtgui_panel_create(RTGUI_BORDER_NONE);
+	rtgui_widget_set_rect(RTGUI_WIDGET(panel), &rect);
+	rtgui_container_add_child(RTGUI_CONTAINER(view), RTGUI_WIDGET(panel));
+
+	box = rtgui_box_create(RTGUI_VERTICAL, 5);
+	rtgui_container_set_box(RTGUI_CONTAINER(panel), box);
+
+	label = rtgui_label_create("label 1");
+	rtgui_container_add_child(RTGUI_CONTAINER(panel), RTGUI_WIDGET(label));
+	label = rtgui_label_create("label 2");
+	rtgui_container_add_child(RTGUI_CONTAINER(panel), RTGUI_WIDGET(label));
+
+	button = rtgui_button_create("button 1");
+	rtgui_container_add_child(RTGUI_CONTAINER(panel), RTGUI_WIDGET(button));
+
+	button = rtgui_button_create("button 2");
+	rtgui_container_add_child(RTGUI_CONTAINER(panel), RTGUI_WIDGET(button));
+	rtgui_widget_set_miniheight(RTGUI_WIDGET(button), 25);
+	RTGUI_WIDGET_ALIGN(button) = RTGUI_ALIGN_EXPAND;
+
+	rtgui_container_layout(RTGUI_CONTAINER(panel));
+
     return view;
 }
-#endif
+

+ 1 - 1
examples/gui/demo_view_image.c

@@ -26,7 +26,7 @@ static void open_btn_onbutton(rtgui_widget_t* widget, struct rtgui_event* event)
 	filelist = rtgui_filelist_view_create("/", "*.*", &rect);
 #endif
 	/* 模态显示一个文件列表视图,以提供给用户选择图像文件 */
-	if (rtgui_container_show(RTGUI_CONTAINER(filelist), RT_TRUE) == RTGUI_MODAL_OK)
+	if (rtgui_widget_show(RTGUI_WIDGET(filelist), RT_TRUE) == RTGUI_MODAL_OK)
 	{
 		char path[32], image_type[8];
 

+ 4 - 2
examples/gui/demo_view_listbox.c

@@ -141,14 +141,16 @@ static struct rtgui_listbox_item items[] =
 	{"list #3", RT_NULL},
 };
 
-static void on_items(rtgui_widget_t* widget, struct rtgui_event* event)
+static rt_bool_t on_items(struct rtgui_object* object, struct rtgui_event* event)
 {
 	rtgui_listbox_t* box;
 	/* get listbox */
-	box = RTGUI_LISTBOX(widget);
+	box = RTGUI_LISTBOX(object);
 
 	/* 打印当前的项 */
 	rt_kprintf("current item: %d\n", box->current_item);
+
+	return RT_TRUE;
 }
 
 /* 创建用于演示label控件的视图 */

+ 4 - 2
examples/gui/demo_view_listctrl.c

@@ -204,14 +204,16 @@ void _rtgui_listctrl_item_draw(struct rtgui_listctrl *list,
 	}
 }
 
-static void on_items(rtgui_widget_t* widget, struct rtgui_event* event)
+static rt_bool_t on_items(struct rtgui_object* object, struct rtgui_event* event)
 {
 	rtgui_listctrl_t* ctrl;
 	/* get listctrl */
-	ctrl = RTGUI_LISTCTRL(widget);
+	ctrl = RTGUI_LISTCTRL(object);
 
 	/* 打印当前的项 */
 	rt_kprintf("current item: %d\n", ctrl->current_item);
+
+	return RT_TRUE;
 }
 
 /* 创建用于演示label控件的视图 */

+ 6 - 4
examples/gui/demo_view_menu.c

@@ -7,7 +7,7 @@
 #include <rtgui/widgets/menu.h>
 #include <rtgui/widgets/button.h>
 
-static rt_bool_t _onmenuitem(struct rtgui_widget *widget, struct rtgui_event* event)
+static rt_bool_t _onmenuitem(struct rtgui_object *object, struct rtgui_event* event)
 {
 	rt_kprintf("menu action!!\n");
 	return RT_TRUE;
@@ -31,15 +31,17 @@ static const rtgui_menu_item_t items[] =
 };
 static rtgui_menu_t* menu;
 
-static _onmenu(struct rtgui_widget* widget, struct rtgui_event* event)
+static rt_bool_t _onmenu(struct rtgui_object* object, struct rtgui_event* event)
 {
 	rtgui_rect_t rect;
 
-	rtgui_widget_get_rect(widget, &rect);
-	rtgui_widget_rect_to_device(widget, &rect);
+	rtgui_widget_get_rect(RTGUI_WIDGET(object), &rect);
+	rtgui_widget_rect_to_device(RTGUI_WIDGET(object), &rect);
 
 	if (menu != RT_NULL)
 		rtgui_menu_pop(menu, rect.x1, rect.y2 + 5);
+
+	return RT_TRUE;
 }
 
 /* 创建用于演示menu控件的视图 */

+ 10 - 12
examples/gui/demo_view_window.c

@@ -57,14 +57,16 @@ static void create_normal_win(void)
 }
 
 /* 触发正常窗口显示 */
-static void demo_normal_window_onbutton(struct rtgui_widget* widget, rtgui_event_t* event)
+static void demo_normal_window_onbutton(struct rtgui_object* object, rtgui_event_t* event)
 {
     rt_sprintf(normal_window_label_text,
             "第 %d 次显示", normal_window_show_count);
     rtgui_label_set_text(normal_window_label,
                          normal_window_label_text);
-	/* 非模态显示窗口 */
-	rtgui_win_show(normal_window, RT_FALSE);
+    if (RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(normal_window)))
+        rtgui_win_show(normal_window, RT_FALSE);
+    else
+        rtgui_win_activate(normal_window);
 }
 
 /* 获取一个递增的窗口标题 */
@@ -91,10 +93,6 @@ void diag_close(struct rtgui_timer* timer, void* parameter)
 	{
 		/* 超时,关闭对话框 */
 		rtgui_win_destroy(msgbox);
-
-		/* 停止并删除定时器 */
-		rtgui_timer_stop(timer);
-		rtgui_timer_destory(timer);
 	}
 }
 
@@ -117,7 +115,7 @@ static rt_uint16_t delta_x = 20;
 static rt_uint16_t delta_y = 40;
 
 /* 触发自动窗口显示 */
-static void demo_autowin_onbutton(struct rtgui_widget* widget, rtgui_event_t* event)
+static void demo_autowin_onbutton(struct rtgui_object* object, rtgui_event_t* event)
 {
 	struct rtgui_rect rect ={50, 50, 200, 200};
 
@@ -147,7 +145,7 @@ static void demo_autowin_onbutton(struct rtgui_widget* widget, rtgui_event_t* ev
 }
 
 /* 触发模态窗口显示 */
-static void demo_modalwin_onbutton(struct rtgui_widget* widget, rtgui_event_t* event)
+static void demo_modalwin_onbutton(struct rtgui_object* object, rtgui_event_t* event)
 {
 	rtgui_win_t *win;
 	rtgui_label_t *label;
@@ -177,19 +175,19 @@ static void demo_modalwin_onbutton(struct rtgui_widget* widget, rtgui_event_t* e
 	rtgui_win_destroy(win);
 }
 
-static void demo_close_ntitle_window(struct rtgui_widget* widget, rtgui_event_t* event)
+static void demo_close_ntitle_window(struct rtgui_object* object, rtgui_event_t* event)
 {
 	rtgui_win_t* win;
 
 	/* 获得最顶层控件 */
-	win = RTGUI_WIN(rtgui_widget_get_toplevel(widget));
+	win = RTGUI_WIN(rtgui_widget_get_toplevel(RTGUI_WIDGET(object)));
 
 	/* 销毁窗口 */
 	rtgui_win_destroy(win);
 }
 
 /* 触发无标题窗口显示 */
-static void demo_ntitlewin_onbutton(struct rtgui_widget* widget, rtgui_event_t* event)
+static void demo_ntitlewin_onbutton(struct rtgui_object* object, rtgui_event_t* event)
 {
 	rtgui_win_t *win;
 	rtgui_label_t *label;

+ 3 - 3
examples/gui/mywidget.c

@@ -71,10 +71,10 @@ static void rtgui_mywidget_onmouse(struct rtgui_mywidget* me, struct rtgui_event
 }
 
 /* mywidget控件的事件处�函�*/
-rt_bool_t rtgui_mywidget_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
+rt_bool_t rtgui_mywidget_event_handler(struct rtgui_object* object, struct rtgui_event* event)
 {
 	/* 调用事件处�函数时,widget指针指�控件本身,所以先获得相应控件对象的指�*/
-	struct rtgui_mywidget* me = RTGUI_MYWIDGET(widget);
+	struct rtgui_mywidget* me = RTGUI_MYWIDGET(object);
 
 	switch (event->type)
 	{
@@ -90,7 +90,7 @@ rt_bool_t rtgui_mywidget_event_handler(struct rtgui_widget* widget, struct rtgui
 
 		/* 其他事件调用父类的事件处�函�*/
 	default:
-		return rtgui_widget_event_handler(RTGUI_OBJECT(widget), event);
+		return rtgui_widget_event_handler(object, event);
 	}
 
 	return RT_FALSE;

+ 1 - 1
examples/gui/mywidget.h

@@ -45,6 +45,6 @@ void rtgui_mywidget_destroy(struct rtgui_mywidget* me);
  * 对一个控件而言,如果派生自它的�控件很�能会调用父控件的事件处�函数,
  * 所以这里采用公开声明的方��
  */
-rt_bool_t rtgui_mywidget_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);
+rt_bool_t rtgui_mywidget_event_handler(struct rtgui_object* object, struct rtgui_event* event);
 
 #endif