Просмотр исходного кода

add icon display mode in listview.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@710 bbd45198-f89e-11dd-88c7-29a3b14d5316
bernard.xiong 15 лет назад
Родитель
Сommit
3f319a875c

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

@@ -16,7 +16,7 @@ struct rtgui_font_engine hz_bmp_font_engine =
 
 static void rtgui_hz_bitmap_font_draw_text(struct rtgui_font* font, struct rtgui_dc* dc, const char* text, rt_ubase_t len, struct rtgui_rect* rect)
 {
-	rt_base_t h;
+	register rt_base_t h, word_bytes;
 	rt_uint8_t* str;
 	struct rtgui_font_bitmap* bmp_font = (struct rtgui_font_bitmap*)(font->data);
 
@@ -24,6 +24,7 @@ static void rtgui_hz_bitmap_font_draw_text(struct rtgui_font* font, struct rtgui
 
 	/* drawing height */
 	h = (bmp_font->height + rect->y1 > rect->y2)? rect->y2 - rect->y1 : bmp_font->height;
+	word_bytes = (bmp_font->width + 7)/8;
 
 	str = (rt_uint8_t*)text;
 
@@ -43,7 +44,7 @@ static void rtgui_hz_bitmap_font_draw_text(struct rtgui_font* font, struct rtgui
 		/* draw word */
 		for (i=0; i < h; i ++)
 		{
-			for (j=0; j < 2; j++)
+			for (j=0; j < word_bytes; j++)
 				for (k=0; k < 8; k++)
 				{
 					if ( ((font_ptr[i*2 + j] >> (7-k)) & 0x01) != 0 &&

+ 2 - 1
components/rtgui/common/font_hz_file.c

@@ -93,7 +93,7 @@ static void rtgui_hz_file_font_load(struct rtgui_font* font)
 
 static void rtgui_hz_file_font_draw_text(struct rtgui_font* font, struct rtgui_dc* dc, const char* text, rt_ubase_t len, struct rtgui_rect* rect)
 {
-	rt_base_t h;
+	register rt_base_t h, word_bytes;
 	rt_uint8_t* str;
     struct rtgui_hz_file_font* hz_file_font = (struct rtgui_hz_file_font*)font->data;
     RT_ASSERT(hz_file_font != RT_NULL);
@@ -101,6 +101,7 @@ static void rtgui_hz_file_font_draw_text(struct rtgui_font* font, struct rtgui_d
 	/* drawing height */
 	h = (hz_file_font->font_size + rect->y1 > rect->y2)?
         rect->y2 - rect->y1 : hz_file_font->font_size;
+	word_bytes = (hz_file_font->font_size + 7) / 8;
 
 	str = (rt_uint8_t*)text;
 

+ 8 - 0
components/rtgui/common/rtgui_system.c

@@ -125,6 +125,14 @@ static void rtgui_event_dump(rt_thread_t tid, rtgui_event_t* event)
 		}
 		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);
+		}
+		break;
+
 	case RTGUI_EVENT_CLIP_INFO:
 		{
 			struct rtgui_event_clip_info *info = (struct rtgui_event_clip_info *)event;

+ 20 - 19
components/rtgui/include/rtgui/rtgui_config.h

@@ -19,25 +19,26 @@
 /* RTGUI options */
 
 #ifdef _WIN32
-/* name length of RTGUI object */
-#define RTGUI_NAME_MAX		12
-/* support 16 weight font */
-#define RTGUI_USING_FONT16
-/* support Chinese font */
-#define RTGUI_USING_FONTHZ
-/* use small size in RTGUI */
-#define RTGUI_USING_SMALL_SIZE
-/* use mouse cursor */
-/* #define RTGUI_USING_MOUSE_CURSOR */
-/* default font size in RTGUI */
-#define RTGUI_DEFAULT_FONT_SIZE	12
-
-#define RTGUI_USING_STDIO_FILERW
-#define RTGUI_IMAGE_PNG
-#define RTGUI_IMAGE_JPEG
-#define RTGUI_USING_FONT12
-#define RTGUI_USING_HZ_BMP
-#define RTGUI_MEM_TRACE
+	/* name length of RTGUI object */
+	#define RTGUI_NAME_MAX		12
+	/* support 16 weight font */
+	#define RTGUI_USING_FONT16
+	/* support Chinese font */
+	#define RTGUI_USING_FONTHZ
+	/* use small size in RTGUI */
+	#define RTGUI_USING_SMALL_SIZE
+	/* use mouse cursor */
+	/* #define RTGUI_USING_MOUSE_CURSOR */
+	/* default font size in RTGUI */
+	#define RTGUI_DEFAULT_FONT_SIZE	12
+
+	#define RTGUI_USING_STDIO_FILERW
+	#define RTGUI_IMAGE_PNG
+	#define RTGUI_IMAGE_JPEG
+	#define RTGUI_USING_FONT12
+	#define RTGUI_USING_HZ_BMP
+	#define RTGUI_MEM_TRACE
+	#define RTGUI_USING_WINMOVE
 #endif
 
 #if RTGUI_DEFAULT_FONT_SIZE == 0

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

@@ -51,6 +51,6 @@ 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);
 void rtgui_filelist_view_set_directory(rtgui_filelist_view_t* view, const char* directory);
 
-void rtgui_filelist_get_fullpath(rtgui_filelist_view_t* view, char* path, rt_size_t len);
+void rtgui_filelist_view_get_fullpath(rtgui_filelist_view_t* view, char* path, rt_size_t len);
 
 #endif

+ 12 - 2
components/rtgui/include/rtgui/widgets/list_view.h

@@ -38,6 +38,10 @@ struct rtgui_list_item
 /** Checks if the object is a filelist view */
 #define RTGUI_IS_LIST_VIEW(obj)    (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_LIST_VIEW_TYPE))
 
+#define RTGUI_LIST_VIEW_LIST		0x00
+#define RTGUI_LIST_VIEW_ICON		0x01
+#define RTGUI_LIST_VIEW_REPORT		0x02
+
 struct rtgui_list_view
 {
 	struct rtgui_view parent;
@@ -46,19 +50,25 @@ struct rtgui_list_view
 	/* list item */
     const struct rtgui_list_item* items;
 
+	/* layout flag */
+	rt_uint16_t flag;
+
 	/* total number of items */
 	rt_uint16_t items_count;
     /* the number of item in a page */
     rt_uint16_t page_items;
-    /* current item */
+	/* current item */
     rt_uint16_t current_item;
+
+	/* icon layout */
+	rt_uint8_t row_items, col_items;
 };
 typedef struct rtgui_list_view rtgui_list_view_t;
 
 rtgui_type_t *rtgui_list_view_type_get(void);
 
 rtgui_list_view_t* rtgui_list_view_create(const struct rtgui_list_item* items, rt_uint16_t count,
-    rtgui_rect_t *rect);
+    rtgui_rect_t *rect, rt_uint16_t flag);
 void rtgui_list_view_destroy(rtgui_list_view_t* view);
 
 rt_bool_t rtgui_list_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);

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

@@ -61,6 +61,8 @@ rtgui_listbox_t* rtgui_listbox_create(const struct rtgui_listbox_item* items, rt
 void rtgui_listbox_destroy(rtgui_listbox_t* box);
 
 rt_bool_t rtgui_listbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);
+void rtgui_listbox_set_onitem(rtgui_listbox_t* box, rtgui_onitem_func_t func);
+void rtgui_listbox_set_items(rtgui_listbox_t* box, struct rtgui_listbox_item* items, rt_uint16_t count);
 
 #endif
 

+ 182 - 74
components/rtgui/widgets/filelist_view.c

@@ -21,6 +21,8 @@
 #include <rtgui/widgets/view.h>
 #include <rtgui/widgets/workbench.h>
 #include <rtgui/widgets/filelist_view.h>
+#include <rtgui/widgets/listbox.h>
+#include <rtgui/widgets/window.h>
 
 #ifdef _WIN32
 #include <io.h>
@@ -219,8 +221,96 @@ const static char * folder_xpm[] = {
 
 /* image for file and folder */
 static rtgui_image_t *file_image, *folder_image;
+static struct rtgui_listbox_item items[] = 
+{
+	{"打开文件夹", RT_NULL},
+	{"选择文件夹", RT_NULL},
+	{"退出", RT_NULL}
+};
 static void rtgui_filelist_view_clear(rtgui_filelist_view_t* view);
 
+static void rtgui_filelist_view_on_folder_item(rtgui_widget_t* widget, struct rtgui_event* event)
+{
+	rtgui_win_t *menu;
+	rtgui_listbox_t *listbox;
+	rtgui_filelist_view_t *view;
+
+	listbox = RTGUI_LISTBOX(widget);
+	menu = RTGUI_WIN(rtgui_widget_get_toplevel(widget));
+	view = RTGUI_FILELIST_VIEW(menu->user_data);
+
+	/* hide window */
+	rtgui_win_hiden(menu);
+
+	switch (listbox->current_item)
+	{
+	case 0:
+		{
+			char* dir_ptr;
+
+			/* destroy menu window */
+			rtgui_win_destroy(menu);
+
+			dir_ptr = (char*) rtgui_malloc (256);
+			rtgui_filelist_view_get_fullpath(view, dir_ptr, 256);
+			rtgui_filelist_view_set_directory(view, dir_ptr);
+			rt_free(dir_ptr);
+		}
+		break;
+	case 1:
+		/* destroy menu window */
+		rtgui_win_destroy(menu);
+		if (RTGUI_VIEW(view)->modal_show == RT_TRUE)
+		{
+			rtgui_view_end_modal(RTGUI_VIEW(view), RTGUI_MODAL_OK);
+		}
+		break;
+
+	default:
+		/* destroy menu window */
+		rtgui_win_destroy(menu);
+		break;
+	}
+}
+
+static rt_bool_t rtgui_filelist_view_on_menu_deactivate(rtgui_widget_t* widget, struct rtgui_event* event)
+{
+	rtgui_win_t *menu;
+	menu = RTGUI_WIN(rtgui_widget_get_toplevel(widget));
+
+	/* destroy menu window */
+	rtgui_win_destroy(menu);
+
+	return RT_TRUE;
+}
+
+static void rtgui_filelist_view_menu_pop(rtgui_widget_t *parent)
+{
+	rtgui_win_t *menu;
+	rtgui_listbox_t *listbox;
+	rtgui_rect_t screen, rect = {0, 0, 140, 85};
+
+	rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), &screen);
+	rtgui_rect_moveto_align(&screen, &rect, RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL);
+
+	menu = rtgui_win_create(RTGUI_TOPLEVEL(rtgui_widget_get_toplevel(parent)), 
+		"Folder Menu", &rect, RTGUI_WIN_STYLE_DEFAULT);
+	if (menu != RT_NULL)
+	{
+		/* set user data on menu window */
+		menu->user_data = (rt_uint32_t)parent;
+
+		rtgui_win_set_ondeactivate(menu, rtgui_filelist_view_on_menu_deactivate);
+
+		listbox = rtgui_listbox_create(items, sizeof(items)/sizeof(items[0]), &rect);
+		rtgui_listbox_set_onitem(listbox, rtgui_filelist_view_on_folder_item);
+		rtgui_container_add_child(RTGUI_CONTAINER(menu), RTGUI_WIDGET(listbox));
+		rtgui_widget_focus(RTGUI_WIDGET(listbox));
+
+		rtgui_win_show(menu, RT_FALSE);
+	}
+}
+
 static void _rtgui_filelist_view_constructor(struct rtgui_filelist_view *view)
 {
 	/* default rect */
@@ -390,6 +480,65 @@ void rtgui_filelist_view_update_current(struct rtgui_filelist_view* view, rt_uin
 	rtgui_dc_end_drawing(dc);
 }
 
+static void rtgui_filelist_view_onenturn(struct rtgui_filelist_view* view)
+{
+	if (view->items[view->current_item].type == RTGUI_FITEM_DIR)
+	{
+		char new_path[64];
+
+		if (strcmp(view->items[view->current_item].name, ".") == 0) return ;
+		if (strcmp(view->items[view->current_item].name, "..") == 0)
+		{
+			char *ptr;
+			ptr = strrchr(view->current_directory, PATH_SEPARATOR);
+
+			if (ptr == RT_NULL) return ;
+			if (ptr == &(view->current_directory[0]))
+			{
+				/* it's root directory */
+				new_path[0] = PATH_SEPARATOR;
+				new_path[1] = '\0';
+			}
+			else
+			{
+				strncpy(new_path, view->current_directory, ptr - view->current_directory + 1);
+				new_path[ptr - view->current_directory] = '\0';
+			}
+		}
+		else if (view->current_item == 0 && 
+#ifdef _WIN32
+			(view->current_directory[1] == ':') && (view->current_directory[2] == '\\'))
+#else
+			(view->current_directory[0] == '/') && (view->current_directory[1] == '\0'))
+#endif
+		{
+			if (RTGUI_VIEW(view)->modal_show == RT_TRUE)
+			{
+				rtgui_view_end_modal(RTGUI_VIEW(view), RTGUI_MODAL_CANCEL);
+			}
+			else
+			{
+				rtgui_filelist_view_destroy(view);
+			}
+
+			return ;
+		}
+		else
+		{
+			rtgui_filelist_view_menu_pop(RTGUI_WIDGET(view));
+			return ;
+		}
+		rtgui_filelist_view_set_directory(view, new_path);
+	}
+	else
+	{
+		if (RTGUI_VIEW(view)->modal_show == RT_TRUE)
+		{
+			rtgui_view_end_modal(RTGUI_VIEW(view), RTGUI_MODAL_OK);
+		}
+	}
+}
+
 rt_bool_t rtgui_filelist_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
 {
 	struct rtgui_filelist_view* view = RT_NULL;
@@ -431,18 +580,31 @@ rt_bool_t rtgui_filelist_view_event_handler(struct rtgui_widget* widget, struct
 			if (rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK)
 			{
 				rt_uint16_t index;
+				rt_uint16_t current_page;
+				rt_uint16_t old_item;
+
 				index = (emouse->y - rect.y1) / (2 + rtgui_theme_get_selected_height());
+				
+				/* get current page */
+				current_page = view->current_item/view->page_items;
+				old_item = view->current_item;
 
-				if ((index < view->items_count) && (index < view->page_items))
+				if (index + current_page * view->page_items < view->items_count)
 				{
-					rt_uint16_t old_item;
-
-					old_item = view->current_item;
-
 					/* set selected item */
-					view->current_item = (old_item/view->page_items) * view->page_items + index;
-					rtgui_filelist_view_update_current(view, old_item);
+					view->current_item = index + current_page * view->page_items;
+					if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN)
+					{
+						rtgui_filelist_view_update_current(view, old_item);
+					}
+					else
+					{
+						/* up event */
+						rtgui_filelist_view_onenturn(view);
+					}
 				}
+
+				return RT_TRUE;
 			}
 		}
 		break;
@@ -461,87 +623,29 @@ rt_bool_t rtgui_filelist_view_event_handler(struct rtgui_widget* widget, struct
 					if (view->current_item > 0)
 						view->current_item --;
 					rtgui_filelist_view_update_current(view, old_item);
-					return RT_FALSE;
+					return RT_TRUE;
 
                 case RTGUIK_DOWN:
 					if (view->current_item < view->items_count - 1)
 						view->current_item ++;
 					rtgui_filelist_view_update_current(view, old_item);
-					return RT_FALSE;
+					return RT_TRUE;
 
 				case RTGUIK_LEFT:
 					if (view->current_item - view->page_items >= 0)
 						view->current_item -= view->page_items;
 					rtgui_filelist_view_update_current(view, old_item);
-					return RT_FALSE;
+					return RT_TRUE;
 
 				case RTGUIK_RIGHT:
 					if (view->current_item + view->page_items < view->items_count - 1)
 						view->current_item += view->page_items;
 					rtgui_filelist_view_update_current(view, old_item);
-					return RT_FALSE;
+					return RT_TRUE;
 
 				case RTGUIK_RETURN:
-					if (view->items[view->current_item].type == RTGUI_FITEM_DIR)
-					{
-						char new_path[64];
-
-						if (strcmp(view->items[view->current_item].name, ".") == 0) return RT_FALSE;
-						if (strcmp(view->items[view->current_item].name, "..") == 0)
-						{
-							char *ptr;
-							ptr = strrchr(view->current_directory, PATH_SEPARATOR);
-
-							if (ptr == RT_NULL) return RT_FALSE;
-							if (ptr == &(view->current_directory[0]))
-							{
-								/* it's root directory */
-								new_path[0] = PATH_SEPARATOR;
-								new_path[1] = '\0';
-							}
-							else
-							{
-								strncpy(new_path, view->current_directory, ptr - view->current_directory + 1);
-								new_path[ptr - view->current_directory] = '\0';
-							}
-						}
-						else if (view->current_item == 0 && 
-#ifdef _WIN32
-							(view->current_directory[1] == ':') && (view->current_directory[2] == '\\'))
-#else
-							(view->current_directory[0] == '/') && (view->current_directory[1] == '\0'))
-#endif
-						{
-							if (RTGUI_VIEW(view)->modal_show == RT_TRUE)
-							{
-								rtgui_view_end_modal(RTGUI_VIEW(view), RTGUI_MODAL_CANCEL);
-							}
-							else
-							{
-								rtgui_filelist_view_destroy(view);
-							}
-
-							return RT_FALSE;
-						}
-						else
-						{
-							if (view->current_directory[strlen(view->current_directory) - 1] != PATH_SEPARATOR)
-								rt_snprintf(new_path, sizeof(new_path), "%s%c%s",view->current_directory, PATH_SEPARATOR,
-									view->items[view->current_item].name);
-							else
-								rt_snprintf(new_path, sizeof(new_path), "%s%s",view->current_directory, 
-									view->items[view->current_item].name);
-						}
-						rtgui_filelist_view_set_directory(view, new_path);
-					}
-					else
-					{
-						if (RTGUI_VIEW(view)->modal_show == RT_TRUE)
-						{
-							rtgui_view_end_modal(RTGUI_VIEW(view), RTGUI_MODAL_OK);
-						}
-					}
-					return RT_FALSE;
+					rtgui_filelist_view_onenturn(view);
+					return RT_TRUE;
 
                 default:
                     break;
@@ -720,10 +824,14 @@ __return:
     rtgui_widget_update(RTGUI_WIDGET(view));
 }
 
-void rtgui_filelist_get_fullpath(rtgui_filelist_view_t* view, char* path, rt_size_t len)
+void rtgui_filelist_view_get_fullpath(rtgui_filelist_view_t* view, char* path, rt_size_t len)
 {
 	RT_ASSERT(view != RT_NULL);
 
-	rt_sprintf(path, "%s%c%s", view->current_directory, PATH_SEPARATOR,
-		view->items[view->current_item].name);
+	if (view->current_directory[strlen(view->current_directory) - 1] != PATH_SEPARATOR)
+		rt_snprintf(path, len, "%s%c%s",view->current_directory, PATH_SEPARATOR,
+			view->items[view->current_item].name);
+	else
+		rt_snprintf(path, len, "%s%s",view->current_directory, 
+			view->items[view->current_item].name);
 }

+ 381 - 59
components/rtgui/widgets/list_view.c

@@ -28,6 +28,7 @@ static void _rtgui_list_view_constructor(struct rtgui_list_view *view)
 
 	RTGUI_WIDGET(view)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
 
+	view->flag = RTGUI_LIST_VIEW_LIST;
 	view->current_item = 0;
 	view->items_count = 0;
 	view->page_items = 0;
@@ -49,18 +50,149 @@ rtgui_type_t *rtgui_list_view_type_get(void)
 	return list_view_type;
 }
 
-void rtgui_list_view_ondraw(struct rtgui_list_view* view)
+static void rtgui_list_view_onicondraw(struct rtgui_list_view* view, struct rtgui_dc *dc)
+{
+	struct rtgui_rect rect, item_rect, drawing_rect;
+	rt_ubase_t c, r, item_index; /* col and row index */
+	rt_ubase_t item_width, item_height;
+	rtgui_image_t* image;
+
+	if (view->items_count == 0) return;
+
+	rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
+	item_index = (view->current_item / view->page_items) * view->page_items;
+
+	item_width = (rtgui_rect_width(rect) - 2 * LIST_MARGIN)/view->col_items;
+	item_height = (rtgui_rect_height(rect) - 4)/view->row_items;
+	image = view->items[0].image;
+
+	for (r = 0; r < view->row_items; r ++)
+	{
+		for (c = 0; c < view->col_items; c ++)
+		{
+			if (item_index < view->items_count)
+			{
+				item_rect.y1 = rect.y1 + LIST_MARGIN + r * item_height;
+				item_rect.x1 = rect.x1 + LIST_MARGIN + c * item_width;
+				item_rect.x2 = item_rect.x1 + item_width;
+				item_rect.y2 = item_rect.y1 + item_height;
+
+				if (item_index == view->current_item)
+				{
+					rtgui_theme_draw_selected(dc, &item_rect);
+				}
+
+				drawing_rect.x1 = drawing_rect.y1 = 0;
+				drawing_rect.x2 = image->w;
+				drawing_rect.y2 = image->h;
+				rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL);
+				drawing_rect.y1 += 3; drawing_rect.y2 += 3;
+				rtgui_image_blit(view->items[item_index].image, dc, &drawing_rect);
+
+				item_rect.y1 = drawing_rect.y2 + LIST_MARGIN; 
+				item_rect.x1 += 3; item_rect.x2 -=3;
+				rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), view->items[item_index].name, 
+					&drawing_rect);
+				rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL);
+				rtgui_dc_draw_text(dc, view->items[item_index].name, &drawing_rect);
+
+				item_index ++;
+			}
+			else break;
+		}
+	}
+}
+
+static void rtgui_list_view_update_icon(struct rtgui_list_view* view, rt_uint16_t old_item)
 {
-	struct rtgui_rect rect, item_rect;
+	struct rtgui_rect rect, item_rect, drawing_rect;
+	rt_ubase_t c, r; /* col and row index */
+	rt_ubase_t item_width, item_height;
+	rtgui_image_t* image;
 	struct rtgui_dc* dc;
-	rt_uint16_t page_index, index;
-	const struct rtgui_list_item* item;
+
+	if ((view->items_count == 0) ||
+		(old_item == view->current_item))
+		return;
+
+	if (old_item/view->page_items != view->current_item/view->page_items)
+	{
+		/* it's not a same page, update all */
+		rtgui_widget_update(RTGUI_WIDGET(view));
+		return;
+	}
 
 	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view));
 	if (dc == RT_NULL) return;
 
 	rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
-	rtgui_dc_fill_rect(dc, &rect);
+
+	item_width = (rtgui_rect_width(rect) - 2 * LIST_MARGIN)/view->col_items;
+	item_height = (rtgui_rect_height(rect) - 4)/view->row_items;
+	image = view->items[0].image;
+
+	/* update old item */
+	r = (old_item % view->page_items)/ view->col_items;
+	c = (old_item % view->page_items)% view->col_items;
+	item_rect.y1 = rect.y1 + LIST_MARGIN + r * item_height;
+	item_rect.x1 = rect.x1 + LIST_MARGIN + c * item_width;
+	item_rect.x2 = item_rect.x1 + item_width;
+	item_rect.y2 = item_rect.y1 + item_height;
+	rtgui_dc_fill_rect(dc, &item_rect);
+
+	/* draw image */
+	drawing_rect.x1 = drawing_rect.y1 = 0;
+	drawing_rect.x2 = image->w;
+	drawing_rect.y2 = image->h;
+	rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL);
+	drawing_rect.y1 += 3; drawing_rect.y2 += 3;
+	rtgui_image_blit(view->items[old_item].image, dc, &drawing_rect);
+
+	/* draw text */
+	item_rect.y1 = drawing_rect.y2 + LIST_MARGIN; 
+	item_rect.x1 += 3; item_rect.x2 -=3;
+	rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), view->items[old_item].name, 
+		&drawing_rect);
+	rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL);
+	rtgui_dc_draw_text(dc, view->items[old_item].name, &drawing_rect);
+
+	/* update new item as selected */
+	r = (view->current_item % view->page_items) / view->col_items;
+	c = (view->current_item % view->page_items) % view->col_items;
+	item_rect.y1 = rect.y1 + LIST_MARGIN + r * item_height;
+	item_rect.x1 = rect.x1 + LIST_MARGIN + c * item_width;
+	item_rect.x2 = item_rect.x1 + item_width;
+	item_rect.y2 = item_rect.y1 + item_height;
+	rtgui_theme_draw_selected(dc, &item_rect);
+
+	/* draw image */
+	drawing_rect.x1 = 0;
+	drawing_rect.y1 = 3;
+	drawing_rect.x2 = image->w;
+	drawing_rect.y2 = 3 + image->h;
+
+	rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL);
+	rtgui_image_blit(view->items[view->current_item].image, dc, &drawing_rect);
+
+	/* draw text */
+	item_rect.y1 = drawing_rect.y2 + LIST_MARGIN; 
+	item_rect.x1 += 3; item_rect.x2 -=3;
+	rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), 
+		view->items[view->current_item].name, 
+		&drawing_rect);
+	rtgui_rect_moveto_align(&item_rect, &drawing_rect, RTGUI_ALIGN_CENTER_HORIZONTAL);
+	rtgui_dc_draw_text(dc, view->items[view->current_item].name, &drawing_rect);
+
+	rtgui_dc_end_drawing(dc);
+}
+
+static void rtgui_list_view_onlistdraw(struct rtgui_list_view* view, struct rtgui_dc *dc)
+{
+	rt_ubase_t index, page_index;
+	rtgui_rect_t rect, item_rect, image_rect;
+	const struct rtgui_list_item* item;
+
+	rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
 
 	/* get item base rect */
 	item_rect = rect;
@@ -83,24 +215,29 @@ void rtgui_list_view_ondraw(struct rtgui_list_view* view)
 
 		if (item->image != RT_NULL)
 		{
-			rtgui_image_blit(item->image, dc, &item_rect);
+			/* blit on center */
+			image_rect.x1 = 0; image_rect.y1 = 0;
+			image_rect.x2 = item->image->w;
+			image_rect.y2 = item->image->h;
+
+			rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
+			rtgui_image_blit(item->image, dc, &image_rect);
 			item_rect.x1 += item->image->w + 2;
 		}
-        /* draw text */
+		/* draw text */
 		rtgui_dc_draw_text(dc, item->name, &item_rect);
 
-        if (item->image != RT_NULL)
-            item_rect.x1 -= (item->image->w + 2);
+		if (item->image != RT_NULL)
+			item_rect.x1 -= (item->image->w + 2);
 		item_rect.x1 -= LIST_MARGIN;
 
-        /* move to next item position */
+		/* move to next item position */
 		item_rect.y1 += (rtgui_theme_get_selected_height() + 2);
 		item_rect.y2 += (rtgui_theme_get_selected_height() + 2);
 	}
-	rtgui_dc_end_drawing(dc);
 }
 
-void rtgui_list_view_update_current(struct rtgui_list_view* view, rt_uint16_t old_item)
+void rtgui_list_view_update_list(struct rtgui_list_view* view, rt_uint16_t old_item)
 {
 	struct rtgui_dc* dc;
 	const struct rtgui_list_item* item;
@@ -118,13 +255,11 @@ void rtgui_list_view_update_current(struct rtgui_list_view* view, rt_uint16_t ol
 
 	rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
 
-	item_rect = rect;
-	/* get old item's rect */
-	item_rect.y1 += 2;
+	/* get old item's rect and draw old item */
+	item_rect.x1 = rect.x1; item_rect.x2 = rect.x2;
+	item_rect.y1 = rect.y1 + 2;
 	item_rect.y1 += (old_item % view->page_items) * (2 + rtgui_theme_get_selected_height());
 	item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height());
-
-	/* draw old item */
 	rtgui_dc_fill_rect(dc, &item_rect);
 
 	item_rect.x1 += LIST_MARGIN;
@@ -132,7 +267,15 @@ void rtgui_list_view_update_current(struct rtgui_list_view* view, rt_uint16_t ol
 	item = &(view->items[old_item]);
 	if (item->image != RT_NULL)
 	{
-		rtgui_image_blit(item->image, dc, &item_rect);
+		struct rtgui_rect image_rect;
+
+		/* blit on center */
+		image_rect.x1 = 0; image_rect.y1 = 0;
+		image_rect.x2 = item->image->w;
+		image_rect.y2 = item->image->h;
+
+		rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
+		rtgui_image_blit(item->image, dc, &image_rect);
 		item_rect.x1 += item->image->w + 2;
 	}
 	rtgui_dc_draw_text(dc, item->name, &item_rect);
@@ -152,14 +295,135 @@ void rtgui_list_view_update_current(struct rtgui_list_view* view, rt_uint16_t ol
 	item = &(view->items[view->current_item]);
 	if (item->image != RT_NULL)
 	{
-		rtgui_image_blit(item->image, dc, &item_rect);
-        item_rect.x1 += (item->image->w + 2);
+		struct rtgui_rect image_rect;
+
+		/* blit on center */
+		image_rect.x1 = 0; image_rect.y1 = 0;
+		image_rect.x2 = item->image->w;
+		image_rect.y2 = item->image->h;
+
+		rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
+		rtgui_image_blit(item->image, dc, &image_rect);
+		item_rect.x1 += (item->image->w + 2);
 	}
 	rtgui_dc_draw_text(dc, item->name, &item_rect);
 
 	rtgui_dc_end_drawing(dc);
 }
 
+void rtgui_list_view_ondraw(struct rtgui_list_view* view)
+{
+	struct rtgui_rect rect;
+	struct rtgui_dc* dc;
+
+	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view));
+	if (dc == RT_NULL) return;
+
+	rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
+	rtgui_dc_fill_rect(dc, &rect);
+
+	switch (view->flag)
+	{
+	case RTGUI_LIST_VIEW_LIST:
+		rtgui_list_view_onlistdraw(view, dc);
+		break;
+
+	case RTGUI_LIST_VIEW_ICON:
+		rtgui_list_view_onicondraw(view, dc);
+		break;
+	}
+
+	rtgui_dc_end_drawing(dc);
+}
+
+static rt_bool_t rtgui_list_view_onmouse(struct rtgui_list_view* view, struct rtgui_event_mouse* emouse)
+{
+	rtgui_rect_t rect;
+
+	/* calculate selected item */
+
+	/* get physical extent information */
+	rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
+	rtgui_widget_rect_to_device(RTGUI_WIDGET(view), &rect);
+
+	if (rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK)
+	{
+		rt_uint16_t index;
+		rt_uint16_t old_item;
+
+		/* get old item */
+		old_item = view->current_item;
+
+		switch (view->flag)
+		{
+		case RTGUI_LIST_VIEW_LIST:
+			index = (emouse->y - rect.y1) / (2 + rtgui_theme_get_selected_height());
+
+			if ((index < view->items_count) && (index < view->page_items))
+			{
+				/* set selected item */
+				view->current_item = (view->current_item/view->page_items) * view->page_items + index;
+				if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN)
+				{
+					/* down event */
+					rtgui_list_view_update_list(view, old_item);
+				}
+				else
+				{
+					/* up event */
+					if (view->items[view->current_item].action != RT_NULL)
+					{
+						view->items[view->current_item].action(view->items[view->current_item].parameter);
+					}
+				}
+			}
+			break;
+
+		case RTGUI_LIST_VIEW_ICON:
+			{
+				rt_uint16_t x, y;
+				rt_uint16_t item_height, item_width;
+				rt_ubase_t current_page;
+
+				item_width = (rtgui_rect_width(rect) - 2 * LIST_MARGIN)/view->col_items;
+				item_height = (rtgui_rect_height(rect) - 4)/view->row_items;
+				x = emouse->x - rect.x1;
+				y = emouse->y - rect.y1;
+
+				index = (y / item_height * view->col_items) + x / item_width;
+				current_page = view->current_item / view->page_items;
+
+				if ((index + (current_page * view->page_items) < view->items_count))
+				{
+					if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN)
+					{
+						view->current_item = index + (current_page * view->page_items);
+
+						/* down event */
+						rtgui_list_view_update_icon(view, old_item);
+					}
+					else
+					{
+						/* up event */
+						if (view->items[view->current_item].action != RT_NULL)
+						{
+							view->items[view->current_item].action(view->items[view->current_item].parameter);
+						}
+					}
+				}
+			}
+			break;
+
+		case RTGUI_LIST_VIEW_REPORT:
+			break;
+		}
+
+		return RT_TRUE;
+	}
+
+	return RT_FALSE;
+}
+
 rt_bool_t rtgui_list_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
 {
 	struct rtgui_list_view* view = RT_NULL;
@@ -184,35 +448,11 @@ rt_bool_t rtgui_list_view_event_handler(struct rtgui_widget* widget, struct rtgu
 
 	case RTGUI_EVENT_MOUSE_BUTTON:
 		{
-			rtgui_rect_t rect;
 			struct rtgui_event_mouse* emouse;
 
 			emouse = (struct rtgui_event_mouse*)event;
-
-			/* calculate selected item */
-
-			/* get physical extent information */
-			rtgui_widget_get_rect(widget, &rect);
-			rtgui_widget_rect_to_device(widget, &rect);
-
-			if (rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK)
-			{
-				rt_uint16_t index;
-				index = (emouse->y - rect.y1) / (2 + rtgui_theme_get_selected_height());
-
-				if ((index < view->items_count) && (index < view->page_items))
-				{
-					rt_uint16_t old_item;
-
-					old_item = view->current_item;
-
-					/* set selected item */
-					view->current_item = (view->current_item/view->page_items) * view->page_items + index;
-					rtgui_list_view_update_current(view, old_item);
-				}
-			}
+			return rtgui_list_view_onmouse(view, emouse);
 		}
-		break;
 
     case RTGUI_EVENT_KBD:
         {
@@ -225,27 +465,73 @@ rt_bool_t rtgui_list_view_event_handler(struct rtgui_widget* widget, struct rtgu
                 switch (ekbd->key)
                 {
 				case RTGUIK_LEFT:
-					if (view->current_item - view->page_items >= 0)
-						view->current_item -= view->page_items;
-					rtgui_list_view_update_current(view, old_item);
+					if (view->flag == RTGUI_LIST_VIEW_LIST)
+					{
+						if (view->current_item - view->page_items >= 0)
+							view->current_item -= view->page_items;
+						
+						rtgui_list_view_update_list(view, old_item);
+					}
+					else if (view->flag == RTGUI_LIST_VIEW_ICON)
+					{
+						if (view->current_item > 0)
+							view->current_item --;
+						rtgui_list_view_update_icon(view, old_item);
+					}
 					return RT_FALSE;
 
                 case RTGUIK_UP:
-					if (view->current_item > 0)
-						view->current_item --;
-					rtgui_list_view_update_current(view, old_item);
+					if (view->flag == RTGUI_LIST_VIEW_LIST)
+					{
+						if (view->current_item > 0)
+							view->current_item --;
+						rtgui_list_view_update_list(view, old_item);
+					}
+					else if (view->flag == RTGUI_LIST_VIEW_ICON)
+					{
+						if (view->current_item >= view->col_items)
+							view->current_item -= view->col_items;
+						else 
+							view->current_item = 0;
+						
+						rtgui_list_view_update_icon(view, old_item);
+					}
 					return RT_FALSE;
 
 				case RTGUIK_RIGHT:
-					if (view->current_item + view->page_items < view->items_count - 1)
-						view->current_item += view->page_items;
-					rtgui_list_view_update_current(view, old_item);
+					if (view->flag == RTGUI_LIST_VIEW_LIST)
+					{
+						if (view->current_item + view->page_items < view->items_count - 1)
+							view->current_item += view->page_items;
+						
+						rtgui_list_view_update_list(view, old_item);
+					}
+					else if (view->flag == RTGUI_LIST_VIEW_ICON)
+					{
+						if (view->current_item < view->items_count - 1)
+							view->current_item ++;
+						
+						rtgui_list_view_update_icon(view, old_item);
+					}
 					return RT_FALSE;
 
                 case RTGUIK_DOWN:
-					if (view->current_item < view->items_count - 1)
-						view->current_item ++;
-					rtgui_list_view_update_current(view, old_item);
+					if (view->flag == RTGUI_LIST_VIEW_LIST)
+					{
+						if (view->current_item < view->items_count - 1)
+							view->current_item ++;
+						
+						rtgui_list_view_update_list(view, old_item);
+					}
+					else if (view->flag == RTGUI_LIST_VIEW_ICON)
+					{
+						if (view->current_item + view->col_items <= (view->items_count - 1))
+							view->current_item += view->col_items;
+						else 
+							view->current_item = view->items_count - 1;
+
+						rtgui_list_view_update_icon(view, old_item);
+					}
 					return RT_FALSE;
 
 				case RTGUIK_RETURN:
@@ -267,7 +553,35 @@ rt_bool_t rtgui_list_view_event_handler(struct rtgui_widget* widget, struct rtgu
     return rtgui_view_event_handler(widget, event);
 }
 
-rtgui_list_view_t* rtgui_list_view_create(const struct rtgui_list_item* items, rt_uint16_t count, rtgui_rect_t *rect)
+static void rtgui_list_view_calc(struct rtgui_list_view* view)
+{
+	/* get image of first item*/
+	rtgui_image_t *image;
+	rtgui_rect_t rect;
+	rt_ubase_t text_width, text_height;
+	rt_ubase_t item_width, item_height;
+
+	if (view->items_count == 0) return;
+
+	image = view->items[0].image;
+	rtgui_font_get_metrics(RTGUI_WIDGET_FONT(RTGUI_WIDGET(view)), "HHHHHH", &rect);
+
+	text_height = rtgui_rect_height(rect);
+	text_width = rtgui_rect_width(rect);
+
+	rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
+
+	item_width = (image->w + LIST_MARGIN);
+	if (item_width < (text_width + LIST_MARGIN)) item_width = text_width + LIST_MARGIN;
+	item_height = image->h + 3 + text_height + LIST_MARGIN; 
+
+	view->row_items = (rtgui_rect_height(rect) - 2 * LIST_MARGIN) / item_height;
+	view->col_items = (rtgui_rect_width(rect) - 2 * LIST_MARGIN) / item_width;
+	view->page_items = view->row_items * view->col_items;
+}
+
+rtgui_list_view_t* rtgui_list_view_create(const struct rtgui_list_item* items, rt_uint16_t count, 
+	rtgui_rect_t *rect, rt_uint16_t flag)
 {
 	struct rtgui_list_view* view = RT_NULL;
 
@@ -277,7 +591,15 @@ rtgui_list_view_t* rtgui_list_view_create(const struct rtgui_list_item* items, r
 	    view->items = items;
 	    view->items_count = count;
 
-		view->page_items = rtgui_rect_height(*rect) / (2 + rtgui_theme_get_selected_height());
+		view->flag = flag;
+		rtgui_widget_set_rect(RTGUI_WIDGET(view), rect);
+
+		if (flag == RTGUI_LIST_VIEW_LIST)
+			view->page_items = rtgui_rect_height(*rect) / (2 + rtgui_theme_get_selected_height());
+		else if ((flag == RTGUI_LIST_VIEW_ICON) && (count > 0))
+		{
+			rtgui_list_view_calc(view);
+		}
 	}
 
 	return view;

+ 19 - 3
components/rtgui/widgets/listbox.c

@@ -201,7 +201,7 @@ rt_bool_t rtgui_listbox_event_handler(struct rtgui_widget* widget, struct rtgui_
 			rtgui_widget_get_rect(widget, &rect);
 			rtgui_widget_rect_to_device(widget, &rect);
 
-			if (rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK)
+			if ((rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK) && (box->items_count > 0))
 			{
 				rt_uint16_t index;
 				index = (emouse->y - rect.y1) / (2 + rtgui_theme_get_selected_height());
@@ -249,13 +249,14 @@ rt_bool_t rtgui_listbox_event_handler(struct rtgui_widget* widget, struct rtgui_
 					}
 				}
 			}
+
+			return RT_TRUE;
 		}
-		break;
 
     case RTGUI_EVENT_KBD:
         {
             struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
-            if (ekbd->type == RTGUI_KEYDOWN)
+            if ((ekbd->type == RTGUI_KEYDOWN) && (box->items_count > 0))
             {
 				rt_uint16_t old_item;
 
@@ -334,3 +335,18 @@ void rtgui_listbox_set_onitem(rtgui_listbox_t* box, rtgui_onitem_func_t func)
 
 	box->on_item = func;
 }
+
+void rtgui_listbox_set_items(rtgui_listbox_t* box, struct rtgui_listbox_item* items, rt_uint16_t count)
+{
+	rtgui_rect_t rect;
+	
+	box->items = items;
+	box->items_count = count;
+	box->current_item = 0;
+
+	rtgui_widget_get_rect(RTGUI_WIDGET(box), &rect);
+	box->page_items = rtgui_rect_height(rect) / (2 + rtgui_theme_get_selected_height());
+
+	rtgui_widget_update(RTGUI_WIDGET(box));
+}
+

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

@@ -465,7 +465,7 @@ rt_bool_t rtgui_win_event_handler(struct rtgui_widget* widget, struct rtgui_even
 		break;
 
 	case RTGUI_EVENT_MOUSE_BUTTON:
-		if (win->flag & RTGUI_WORKBENCH_FLAG_MODAL_MODE)
+		if (win->flag & RTGUI_WIN_STYLE_MODAL)
 		{
 			if (win->modal_widget != RT_NULL)
 				return win->modal_widget->event_handler(win->modal_widget, event);
@@ -500,7 +500,7 @@ rt_bool_t rtgui_win_event_handler(struct rtgui_widget* widget, struct rtgui_even
 		break;
 
     case RTGUI_EVENT_KBD:
-		if (win->flag & RTGUI_WORKBENCH_FLAG_MODAL_MODE)
+		if (win->flag & RTGUI_WIN_STYLE_MODAL)
 		{
 			if (win->modal_widget != RT_NULL)
 				return win->modal_widget->event_handler(win->modal_widget, event);