Browse Source

update more GUI examples.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@339 bbd45198-f89e-11dd-88c7-29a3b14d5316
bernard.xiong 15 years ago
parent
commit
4c70ff59d3

+ 3 - 0
examples/gui/demo_fnview.c

@@ -7,6 +7,9 @@ static rtgui_label_t* label;
 void open_btn_onbutton(rtgui_widget_t* widget, struct rtgui_event* event)
 {
     /* create a fn view */
+	rtgui_view_t *view;
+
+	view = rtgui_filelist_view_create(workbench, "/", "*.*");
 }
 
 rtgui_view_t* demo_fn_view(rtgui_workbench_t* workbench)

+ 45 - 0
rtgui/include/rtgui/widgets/about_view.h

@@ -0,0 +1,45 @@
+/*
+ * 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/view.h>
+
+/** Gets the type of a about view */
+#define RTGUI_ABOUT_VIEW_TYPE       (rtgui_about_view_type_get())
+/** 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_view parent;
+
+	/* widget private data */
+	rtgui_image_t* logo;
+	const char* description;
+};
+typedef struct rtgui_about_view rtgui_about_view_t;
+
+rtgui_type_t *rtgui_about_view_type_get(void);
+
+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_widget* widget, struct rtgui_event* event);
+
+#endif

+ 56 - 0
rtgui/include/rtgui/widgets/filelist_view.h

@@ -0,0 +1,56 @@
+#ifndef __RTGUI_FILELIST_VIEW_H__
+#define __RTGUI_FILELIST_VIEW_H__
+
+#include <rtgui/widgets/view.h>
+
+#define RTGUI_FITEM_FILE      0x0
+#define RTGUI_FITEM_DIR       0x1
+struct rtgui_file_item
+{
+	rt_uint8_t* name;
+
+	rt_uint32_t type;
+	rt_uint32_t size;
+};
+
+/** Gets the type of a filelist view */
+#define RTGUI_FILELIST_VIEW_TYPE       (rtgui_filelist_view_type_get())
+/** Casts the object to a filelist */
+#define RTGUI_FILELIST_VIEW(obj)       (RTGUI_OBJECT_CAST((obj), RTGUI_FILELIST_VIEW_TYPE, rtgui_filelist_view_t))
+/** Checks if the object is a filelist view */
+#define RTGUI_IS_FILELIST_VIEW(obj)    (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_FILELIST_VIEW_TYPE))
+
+struct rtgui_filelist_view
+{
+	struct rtgui_view parent;
+
+	/* widget private data */
+
+    /* current directory */
+    rt_uint8_t* current_directory;
+    rt_uint8_t* pattern;
+
+    /* the number of item in a page */
+    rt_uint16_t page_items;
+	rt_uint16_t items_count;
+
+	/* the selected item */
+	rt_uint16_t current_item;
+
+	/* items array */
+	struct rtgui_file_item *items;
+};
+typedef struct rtgui_filelist_view rtgui_filelist_view_t;
+
+rtgui_type_t *rtgui_filelist_view_type_get(void);
+
+rtgui_filelist_view_t* rtgui_filelist_view_create(rtgui_workbench_t* workbench, 
+	const char* directory, const char* pattern, const rtgui_rect_t* rect);
+void rtgui_filelist_view_destroy(rtgui_filelist_view_t* view);
+
+void rtgui_filelist_view_clear(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);
+
+#endif

+ 66 - 0
rtgui/include/rtgui/widgets/list_view.h

@@ -0,0 +1,66 @@
+/*
+ * 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_LIST_VIEW_H__
+#define __RTGUI_LIST_VIEW_H__
+
+#include <rtgui/rtgui.h>
+#include <rtgui/image.h>
+#include <rtgui/rtgui_system.h>
+
+#include <rtgui/widgets/view.h>
+
+typedef void (*item_action)(void* parameter);
+struct rtgui_list_item
+{
+    char* name;
+	rtgui_image_t *image;
+
+    item_action action;
+    void *parameter;
+};
+
+/** Gets the type of a list view */
+#define RTGUI_LIST_VIEW_TYPE       (rtgui_list_view_type_get())
+/** Casts the object to a filelist */
+#define RTGUI_LIST_VIEW(obj)       (RTGUI_OBJECT_CAST((obj), RTGUI_LIST_VIEW_TYPE, rtgui_list_view_t))
+/** Checks if the object is a filelist view */
+#define RTGUI_IS_LIST_VIEW(obj)    (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_LIST_VIEW_TYPE))
+
+struct rtgui_list_view
+{
+	struct rtgui_view parent;
+
+	/* widget private data */
+	/* list item */
+    struct rtgui_list_item* items;
+
+	/* total number of items */
+	rt_uint16_t items_count;
+    /* the number of item in a page */
+    rt_uint16_t page_items;
+    /* current item */
+    rt_uint16_t current_item;
+};
+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(struct rtgui_list_item* items, rt_uint16_t count,
+    rtgui_rect_t *rect);
+void rtgui_list_view_clear(rtgui_list_view_t* view);
+
+rt_bool_t rtgui_list_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);
+
+#endif

+ 108 - 0
rtgui/widgets/about_view.c

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

+ 672 - 0
rtgui/widgets/filelist_view.c

@@ -11,3 +11,675 @@
  * Date           Author       Notes
  * 2010-01-06     Bernard      first version
  */
+
+#include <rtgui/rtgui_object.h>
+#include <rtgui/rtgui_system.h>
+#include <rtgui/rtgui_theme.h>
+
+#include <rtgui/list.h>
+#include <rtgui/image.h>
+#include <rtgui/widgets/view.h>
+#include <rtgui/widgets/workbench.h>
+#include <rtgui/widgets/filelist_view.h>
+
+#ifdef _WIN32
+#include <io.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#define PATH_SEPARATOR		'\\'
+#define stat _stat
+#else
+#include <dfs_posix.h>
+#define PATH_SEPARATOR		'/'
+#endif
+
+#include <string.h>
+
+#define RTGUI_FILELIST_MARGIN		5
+
+const static char * file_xpm[] = {
+"16 16 21 1",
+" 	c None",
+".	c #999999",
+"+	c #818181",
+"@	c #FFFFFF",
+"#	c #ECECEC",
+"$	c #EAEAEA",
+"%	c #EBEBEB",
+"&	c #EDEDED",
+"*	c #F0F0F0",
+"=	c #C4C4C4",
+"-	c #C5C5C5",
+";	c #C6C6C6",
+">	c #C7C7C7",
+",	c #EEEEEE",
+"'	c #EDEDE5",
+")	c #EDEDE6",
+"!	c #EFEFEF",
+"~	c #C8C8C8",
+"{	c #F1F1F1",
+"]	c #F2F2F2",
+"^	c #959595",
+".++++++++++++   ",
+"+@@@@@@@@@@@@+  ",
+"+@#$$%%%##&*@+  ",
+"+@$=--;;;;>*@+  ",
+"+@$%%###&&,*@+  ",
+"+@%-;;;;;;>*@+  ",
+"+@%%##&&'#,*@+  ",
+"+@%;;;;,,),*@+  ",
+"+@##&&,,!!!*@+  ",
+"+@#;;;>>~~~*@+  ",
+"+@#&,,!!*{{{@+  ",
+"+@&;>>~~~{{]@+  ",
+"+@&&,!!**{]]@+  ",
+"+@@@@@@@@@@@@+  ",
+"^++++++++++++^  ",
+"                "};
+
+const static char * folder_xpm[] = {
+"16 16 121 2",
+"  	c None",
+". 	c #D9B434",
+"+ 	c #E1C25E",
+"@ 	c #E2C360",
+"# 	c #E2C35F",
+"$ 	c #DBB63C",
+"% 	c #DAB336",
+"& 	c #FEFEFD",
+"* 	c #FFFFFE",
+"= 	c #FFFEFE",
+"- 	c #FFFEFD",
+"; 	c #FBF7EA",
+"> 	c #E4C76B",
+", 	c #E3C76B",
+"' 	c #E6CD79",
+") 	c #E5CA74",
+"! 	c #DAAF35",
+"~ 	c #FEFCF7",
+"{ 	c #F8E48E",
+"] 	c #F5DE91",
+"^ 	c #F5E09F",
+"/ 	c #F6E1AC",
+"( 	c #FEFBEF",
+"_ 	c #FEFDF4",
+": 	c #FEFCF3",
+"< 	c #FEFCF1",
+"[ 	c #FEFBEE",
+"} 	c #FFFDFA",
+"| 	c #DAAF36",
+"1 	c #DAAA36",
+"2 	c #FDFAF1",
+"3 	c #F5DE94",
+"4 	c #F4DC93",
+"5 	c #F2D581",
+"6 	c #EDCA6A",
+"7 	c #EACB6C",
+"8 	c #EFD385",
+"9 	c #EFD280",
+"0 	c #EFD07A",
+"a 	c #EECF76",
+"b 	c #EECF72",
+"c 	c #FBF7E9",
+"d 	c #DAAE34",
+"e 	c #DAAB35",
+"f 	c #FBF6E8",
+"g 	c #EFD494",
+"h 	c #EECE88",
+"i 	c #E9C173",
+"j 	c #F6E9C9",
+"k 	c #FEFCF2",
+"l 	c #FEFCF0",
+"m 	c #DAAB36",
+"n 	c #DAA637",
+"o 	c #FFFDF8",
+"p 	c #FFFDF6",
+"q 	c #FFFCF5",
+"r 	c #FCF6D8",
+"s 	c #F8E694",
+"t 	c #F7E385",
+"u 	c #F6DF76",
+"v 	c #F5DB68",
+"w 	c #F4D85C",
+"x 	c #FCF4D7",
+"y 	c #DAA435",
+"z 	c #DAA136",
+"A 	c #FEFCF6",
+"B 	c #FCF2C8",
+"C 	c #FBEFB9",
+"D 	c #FAECAC",
+"E 	c #F9E89C",
+"F 	c #F7E38B",
+"G 	c #F6E07C",
+"H 	c #F6DC6C",
+"I 	c #F5D95D",
+"J 	c #F4D64F",
+"K 	c #F3D344",
+"L 	c #FCF3D0",
+"M 	c #DA9F35",
+"N 	c #DA9A36",
+"O 	c #FDFAF2",
+"P 	c #FAEDB3",
+"Q 	c #F9E9A4",
+"R 	c #F8E695",
+"S 	c #F7E285",
+"T 	c #F6DE76",
+"U 	c #F5DB65",
+"V 	c #F4D757",
+"W 	c #F3D449",
+"X 	c #F2D13B",
+"Y 	c #F1CE30",
+"Z 	c #FBF2CC",
+"` 	c #DA9835",
+" .	c #DA9435",
+"..	c #FEFAEF",
+"+.	c #F9E9A1",
+"@.	c #F8E591",
+"#.	c #F7E181",
+"$.	c #F6DE72",
+"%.	c #F5DA63",
+"&.	c #F4D754",
+"*.	c #F3D347",
+"=.	c #F2D039",
+"-.	c #F1CD2E",
+";.	c #F0CB26",
+">.	c #FBF2CA",
+",.	c #D98E33",
+"'.	c #FAF0DC",
+").	c #F4DDA7",
+"!.	c #F4DB9E",
+"~.	c #F3DA96",
+"{.	c #F3D88E",
+"].	c #F3D786",
+"^.	c #F2D47F",
+"/.	c #F2D379",
+"(.	c #F1D272",
+"_.	c #F1D06C",
+":.	c #F1CF69",
+"<.	c #F8EAC2",
+"[.	c #D8882D",
+"}.	c #D8872D",
+"|.	c #D8862C",
+"                                ",
+"                                ",
+"                                ",
+"  . + @ @ @ # $                 ",
+"  % & * = - * ; > , , , ' )     ",
+"  ! ~ { ] ^ / ( _ : < ( [ } |   ",
+"  1 2 3 4 5 6 7 8 9 0 a b c d   ",
+"  e f g h i j k : k l ( [ * m   ",
+"  n * o p q : r s t u v w x y   ",
+"  z A B C D E F G H I J K L M   ",
+"  N O P Q R S T U V W X Y Z `   ",
+"   ...+.@.#.$.%.&.*.=.-.;.>. .  ",
+"  ,.'.).!.~.{.].^./.(._.:.<.,.  ",
+"    [.}.[.[.[.[.[.[.[.[.}.[.|.  ",
+"                                ",
+"                                "};
+
+/* image for file and folder */
+static rtgui_image_t *file_image, *folder_image;
+static struct rtgui_filelist_view *filelist_view = RT_NULL; /* only one view in global */
+
+static void _rtgui_filelist_view_constructor(struct rtgui_filelist_view *view)
+{
+	/* default rect */
+	struct rtgui_rect rect = {0, 0, 200, 200};
+
+	/* set default widget rect and set event handler */
+	rtgui_widget_set_event_handler(RTGUI_WIDGET(view), rtgui_filelist_view_event_handler);
+	rtgui_widget_set_rect(RTGUI_WIDGET(view), &rect);
+
+	RTGUI_WIDGET(view)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
+
+	view->current_item = 0;
+	view->items_count = 0;
+	view->page_items = 0;
+
+	view->current_directory = RT_NULL;
+	view->pattern = RT_NULL;
+	RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(view)) = white;
+	RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(view)) = RTGUI_ALIGN_CENTER_VERTICAL;
+
+	file_image = rtgui_image_create_from_mem("xpm",
+		(rt_uint8_t*)file_xpm, sizeof(file_xpm), RT_TRUE);
+	folder_image = rtgui_image_create_from_mem("xpm",
+		(rt_uint8_t*)folder_xpm, sizeof(folder_xpm), RT_TRUE);
+}
+
+rtgui_type_t *rtgui_filelist_view_type_get(void)
+{
+	static rtgui_type_t *filelist_view_type = RT_NULL;
+
+	if (!filelist_view_type)
+	{
+		filelist_view_type = rtgui_type_create("flview", RTGUI_VIEW_TYPE,
+			sizeof(rtgui_filelist_view_t), RTGUI_CONSTRUCTOR(_rtgui_filelist_view_constructor), RT_NULL);
+	}
+
+	return filelist_view_type;
+}
+
+void rtgui_filelist_view_ondraw(struct rtgui_filelist_view* view)
+{
+	struct rtgui_dc* dc;
+	rt_uint16_t page_index, index;
+	struct rtgui_file_item* item;
+	struct rtgui_rect rect, item_rect, image_rect;
+
+	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view));
+	if (dc == RT_NULL) return;
+
+	rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
+	rtgui_dc_fill_rect(dc, &rect);
+
+	/* get item base rect */
+	item_rect = rect;
+	item_rect.y1 += 1;	
+	item_rect.y2 = item_rect.y1 + (1 + rtgui_theme_get_selected_height());
+
+	/* get image base rect */
+	image_rect.x1 = RTGUI_FILELIST_MARGIN; image_rect.y1 = 0;
+	image_rect.x2 = RTGUI_FILELIST_MARGIN + file_image->w; image_rect.y2 = file_image->h;
+	rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
+
+	/* get current page */
+	page_index = (view->current_item / view->page_items) * view->page_items;
+	for (index = 0; index < view->page_items; index ++)
+	{
+		if (page_index + index >= view->items_count) break;
+
+		item = &(view->items[page_index + index]);
+
+		if (page_index + index == view->current_item)
+		{
+			rtgui_theme_draw_selected(dc, &item_rect);
+		}
+		else
+		{
+			/* draw background */
+			rtgui_dc_fill_rect(dc, &item_rect);
+		}
+		
+		/* draw item */
+		
+		if (item->type == RTGUI_FITEM_FILE)
+			rtgui_image_blit(file_image, dc, &image_rect);
+		else
+			rtgui_image_blit(folder_image, dc, &image_rect);
+
+        /* draw text */
+		item_rect.x1 += RTGUI_FILELIST_MARGIN + file_image->w + 2;
+		rtgui_dc_draw_text(dc, item->name, &item_rect);
+		item_rect.x1 -= RTGUI_FILELIST_MARGIN + file_image->w + 2;
+
+        /* move to next item position */
+		item_rect.y1 += (rtgui_theme_get_selected_height() + 1);
+		item_rect.y2 += (rtgui_theme_get_selected_height() + 1);
+
+		image_rect.y1 += (rtgui_theme_get_selected_height() + 1);
+		image_rect.y2 += (rtgui_theme_get_selected_height() + 1);
+	}
+
+	rtgui_dc_end_drawing(dc);
+}
+
+void rtgui_filelist_view_update_current(struct rtgui_filelist_view* view, rt_uint16_t old_item)
+{
+	struct rtgui_dc* dc;
+	struct rtgui_file_item* item;
+	rtgui_rect_t rect, item_rect, image_rect;
+
+	if (old_item/view->page_items != view->current_item/view->page_items)
+	{
+		/* it's not a same page, update all */
+		rtgui_widget_update(RTGUI_WIDGET(view));
+		return;
+	}
+
+	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view));
+	if (dc == RT_NULL) return;
+
+	rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
+
+	/* get old item rect */
+	item_rect = rect;
+	item_rect.y1 += 1;	
+	item_rect.y1 += (old_item % view->page_items) * (1 + rtgui_theme_get_selected_height());
+	item_rect.y2 = item_rect.y1 + (1 + rtgui_theme_get_selected_height());
+
+	/* get image rect */
+	image_rect.x1 = RTGUI_FILELIST_MARGIN; image_rect.y1 = 0;
+	image_rect.x2 = RTGUI_FILELIST_MARGIN + file_image->w; image_rect.y2 = file_image->h;
+	rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
+	
+	/* draw old item */
+	rtgui_dc_fill_rect(dc, &item_rect);
+
+	item = &(view->items[old_item]);
+	if (item->type == RTGUI_FITEM_FILE) /* draw item image */
+		rtgui_image_blit(file_image, dc, &image_rect);
+	else
+		rtgui_image_blit(folder_image, dc, &image_rect);
+
+	item_rect.x1 += RTGUI_FILELIST_MARGIN + file_image->w + 2;
+	rtgui_dc_draw_text(dc, item->name, &item_rect);
+
+	/* draw current item */
+	item_rect = rect;
+	item_rect.y1 += 1;
+	item_rect.y1 += (view->current_item % view->page_items) * (1 + rtgui_theme_get_selected_height());
+	item_rect.y2 = item_rect.y1 + (1 + rtgui_theme_get_selected_height());
+
+	rtgui_theme_draw_selected(dc, &item_rect);
+
+	/* get image base rect */
+	image_rect.x1 = RTGUI_FILELIST_MARGIN; image_rect.y1 = 0;
+	image_rect.x2 = RTGUI_FILELIST_MARGIN + file_image->w; image_rect.y2 = file_image->h;
+	rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
+
+	item = &(view->items[view->current_item]);
+	if (item->type == RTGUI_FITEM_FILE) /* draw item image */
+		rtgui_image_blit(file_image, dc, &image_rect);
+	else
+		rtgui_image_blit(folder_image, dc, &image_rect);
+
+	item_rect.x1 += RTGUI_FILELIST_MARGIN + file_image->w + 2;
+	rtgui_dc_draw_text(dc, item->name, &item_rect);
+
+	rtgui_dc_end_drawing(dc);
+}
+
+rt_bool_t rtgui_filelist_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
+{
+	struct rtgui_filelist_view* view = RT_NULL;
+
+	view = RTGUI_FILELIST_VIEW(widget);
+	switch (event->type)
+	{
+	case RTGUI_EVENT_PAINT:
+		rtgui_filelist_view_ondraw(view);
+		return RT_FALSE;
+
+    case RTGUI_EVENT_RESIZE:
+        {
+			struct rtgui_event_resize* resize;
+
+			resize = (struct rtgui_event_resize*)event;
+
+            /* recalculate page items */
+			if (file_image != RT_NULL)
+				view->page_items = resize->h  / (1 + rtgui_theme_get_selected_height());
+			else
+				view->page_items = resize->h / (2 + 14);
+        }
+        break;
+
+    case RTGUI_EVENT_KBD:
+        {
+            struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
+            if (ekbd->type == RTGUI_KEYDOWN)
+            {
+				rt_uint16_t old_item;
+
+				old_item = view->current_item;
+                switch (ekbd->key)
+                {
+                case RTGUIK_UP:
+					if (view->current_item > 0)
+						view->current_item --;
+					rtgui_filelist_view_update_current(view, old_item);
+					return RT_FALSE;
+
+                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;
+
+				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;
+
+				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;
+
+				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 && 
+							(view->current_directory[0] == '/') && (view->current_directory[1] == '\0'))
+						{
+							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)
+								sprintf(new_path, "%s%c%s",view->current_directory, PATH_SEPARATOR,
+									view->items[view->current_item].name);
+							else
+								sprintf(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;
+
+                default:
+                    break;
+                }
+            }
+        }
+		return RT_FALSE;
+	}
+
+    /* use view event handler */
+    return rtgui_view_event_handler(widget, event);
+}
+
+rtgui_filelist_view_t* rtgui_filelist_view_create(rtgui_workbench_t* workbench, 
+	const char* directory, const char* pattern, const rtgui_rect_t* rect)
+{
+	struct rtgui_filelist_view* view = RT_NULL;
+
+	/* create a new view */
+	view = (struct rtgui_filelist_view*) rtgui_widget_create(RTGUI_FILELIST_VIEW_TYPE);
+	if (view != RT_NULL)
+	{
+		view->items = RT_NULL;
+		view->pattern = rt_strdup(pattern);
+		view->page_items = rtgui_rect_height(*rect) / (1 + rtgui_theme_get_selected_height());
+		rtgui_filelist_view_set_directory(view, directory);
+		
+		rtgui_workbench_add_view(workbench, RTGUI_VIEW(view));
+	}
+
+	return view;
+}
+
+void rtgui_filelist_view_destroy(rtgui_filelist_view_t* view)
+{
+    /* delete all file items */
+    rtgui_filelist_view_clear(view);
+	/* delete current directory and pattern */
+	rtgui_free(view->current_directory); view->current_directory = RT_NULL;
+	rtgui_free(view->pattern); view->pattern = RT_NULL;
+
+	/* delete image */
+	rtgui_image_destroy(file_image);
+	rtgui_image_destroy(folder_image);
+
+    /* destroy view */
+	rtgui_widget_destroy(RTGUI_WIDGET(view));
+}
+
+/* clear all file items */
+void rtgui_filelist_view_clear(rtgui_filelist_view_t* view)
+{
+	rt_uint32_t index;
+    struct rtgui_file_item* item;
+
+	for (index = 0; index < view->items_count; index ++)
+	{
+		item = &(view->items[index]);
+
+		/* release item name */
+		rt_free(item->name);
+		item->name = RT_NULL;
+	}
+
+	/* release items */
+	rtgui_free(view->items);
+	view->items = RT_NULL;
+
+	view->items_count = 0;
+	view->current_item = 0;
+}
+
+void rtgui_filelist_view_set_directory(rtgui_filelist_view_t* view, const char* directory)
+{
+    rt_uint8_t fullpath[256];
+    struct rtgui_file_item *item;
+
+    RT_ASSERT(view != RT_NULL);
+
+    /* clear file items firstly */
+    rtgui_filelist_view_clear(view);
+    if (directory != RT_NULL)
+    {
+		DIR* dir;
+		struct stat s;
+		rt_uint32_t index;
+		struct dirent* dirent;
+
+		view->items_count = 0;
+        dir = opendir(directory);
+		if (dir == RT_NULL)  goto __return;
+
+		/* current directory exists, set it */
+		if (view->current_directory != RT_NULL) rt_free(view->current_directory);
+		view->current_directory = rt_strdup(directory);
+
+		do 
+		{
+			dirent = readdir(dir);
+			if (dirent == RT_NULL) break;
+
+			if (strcmp(dirent->d_name, ".") == 0) continue;
+			if (strcmp(dirent->d_name, "..") == 0) continue;
+			
+			view->items_count ++;
+		} while (dirent != RT_NULL);
+		closedir(dir);
+
+		view->items_count ++; /* root directory for [x] exit, others for .. */
+
+		view->items = (struct rtgui_file_item*) rtgui_malloc(sizeof(struct rtgui_file_item) * view->items_count);
+		if (view->items == RT_NULL) return; /* no memory */
+
+		index = 0;
+		if (directory[0] == '/' && directory[1] != '\0')
+		{
+			item = &(view->items[0]);
+
+			/* add .. directory */
+			item->name = rt_strdup("..");
+			item->type = RTGUI_FITEM_DIR;
+			item->size = 0;
+			
+			index ++;
+		}
+		else
+		{
+			item = &(view->items[0]);
+
+			/* add .. directory */
+			item->name = rt_strdup("ÍËłöÎÄźţäŻŔŔ");
+			item->type = RTGUI_FITEM_DIR;
+			item->size = 0;
+			
+			index ++;
+		}
+
+		/* reopen directory */
+		dir = opendir(directory);
+		for (; index < view->items_count; index ++)
+		{
+			dirent = readdir(dir);
+			if (dirent == RT_NULL) break;
+
+			item = &(view->items[index]);
+			item->name = rt_strdup(dirent->d_name);
+
+			rt_memset(&s, 0, sizeof(struct stat));
+
+			/* build full path for the file */
+			if (directory[strlen(directory) - 1] != PATH_SEPARATOR)
+				sprintf(fullpath, "%s%c%s", directory, PATH_SEPARATOR, dirent->d_name);
+			else
+				sprintf(fullpath, "%s%s", directory, dirent->d_name);
+
+			stat(fullpath, &s);
+			if ( s.st_mode & S_IFDIR )
+			{
+				item->type = RTGUI_FITEM_DIR;
+				item->size = 0;
+			}
+			else
+			{
+				item->type = RTGUI_FITEM_FILE;
+				item->size = s.st_size;
+			}
+		}
+
+		closedir(dir);
+    }
+
+	view->current_item = 0;
+
+__return:
+    /* update view */
+    rtgui_widget_update(RTGUI_WIDGET(view));
+}

+ 245 - 0
rtgui/widgets/list_view.c

@@ -11,3 +11,248 @@
  * Date           Author       Notes
  * 2010-01-06     Bernard      first version
  */
+
+#include <rtgui/rtgui_theme.h>
+#include <rtgui/widgets/list_view.h>
+
+#define LIST_MARGIN		5
+
+static void _rtgui_list_view_constructor(struct rtgui_list_view *view)
+{
+	/* default rect */
+	struct rtgui_rect rect = {0, 0, 200, 200};
+
+	/* set default widget rect and set event handler */
+	rtgui_widget_set_event_handler(RTGUI_WIDGET(view),rtgui_list_view_event_handler);
+	rtgui_widget_set_rect(RTGUI_WIDGET(view), &rect);
+
+	RTGUI_WIDGET(view)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
+
+	view->current_item = 0;
+	view->items_count = 0;
+	view->page_items = 0;
+
+	RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(view)) = white;
+	RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(view)) = RTGUI_ALIGN_CENTER_VERTICAL;
+}
+
+rtgui_type_t *rtgui_list_view_type_get(void)
+{
+	static rtgui_type_t *list_view_type = RT_NULL;
+
+	if (!list_view_type)
+	{
+		list_view_type = rtgui_type_create("listview", RTGUI_VIEW_TYPE,
+			sizeof(rtgui_list_view_t), RTGUI_CONSTRUCTOR(_rtgui_list_view_constructor), RT_NULL);
+	}
+
+	return list_view_type;
+}
+
+void rtgui_list_view_ondraw(struct rtgui_list_view* view)
+{
+	struct rtgui_rect rect, item_rect;
+	struct rtgui_dc* dc;
+	rt_uint16_t page_index, index;
+	struct rtgui_list_item* item;
+
+	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view));
+	if (dc == RT_NULL) return;
+
+	rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
+	rtgui_dc_fill_rect(dc, &rect);
+
+	/* get item base rect */
+	item_rect = rect;
+	item_rect.y1 += 2;
+	item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height());
+
+	/* get current page */
+	page_index = (view->current_item / view->page_items) * view->page_items;
+	for (index = 0; index < view->page_items; index ++)
+	{
+		if (page_index + index >= view->items_count) break;
+
+		item = &(view->items[page_index + index]);
+
+		if (page_index + index == view->current_item)
+		{
+			rtgui_theme_draw_selected(dc, &item_rect);
+		}
+		item_rect.x1 += LIST_MARGIN;
+
+		if (item->image != RT_NULL)
+		{
+			rtgui_image_blit(item->image, dc, &item_rect);
+			item_rect.x1 += item->image->w + 2;
+		}
+        /* draw text */
+		rtgui_dc_draw_text(dc, item->name, &item_rect);
+
+        if (item->image != RT_NULL)
+            item_rect.x1 -= (item->image->w + 2);
+		item_rect.x1 -= LIST_MARGIN;
+
+        /* move to next item position */
+		item_rect.y1 += (rtgui_theme_get_selected_height() + 2);
+		item_rect.y2 += (rtgui_theme_get_selected_height() + 2);
+	}
+	rtgui_dc_end_drawing(dc);
+}
+
+void rtgui_list_view_update_current(struct rtgui_list_view* view, rt_uint16_t old_item)
+{
+	struct rtgui_dc* dc;
+	struct rtgui_list_item* item;
+	rtgui_rect_t rect, item_rect;
+
+	if (old_item/view->page_items != view->current_item/view->page_items)
+	{
+		/* it's not a same page, update all */
+		rtgui_widget_update(RTGUI_WIDGET(view));
+		return;
+	}
+
+	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view));
+	if (dc == RT_NULL) return;
+
+	rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
+
+	item_rect = rect;
+	/* get old item's rect */
+	item_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;
+
+	item = &(view->items[old_item]);
+	if (item->image != RT_NULL)
+	{
+		rtgui_image_blit(item->image, dc, &item_rect);
+		item_rect.x1 += item->image->w + 2;
+	}
+	rtgui_dc_draw_text(dc, item->name, &item_rect);
+
+	/* draw current item */
+	item_rect = rect;
+	/* get current item's rect */
+	item_rect.y1 += 2;
+	item_rect.y1 += (view->current_item % view->page_items) * (2 + rtgui_theme_get_selected_height());
+	item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height());
+
+	/* draw current item */
+	rtgui_theme_draw_selected(dc, &item_rect);
+
+	item_rect.x1 += LIST_MARGIN;
+
+	item = &(view->items[view->current_item]);
+	if (item->image != RT_NULL)
+	{
+		rtgui_image_blit(item->image, dc, &item_rect);
+        item_rect.x1 += (item->image->w + 2);
+	}
+	rtgui_dc_draw_text(dc, item->name, &item_rect);
+
+	rtgui_dc_end_drawing(dc);
+}
+
+rt_bool_t rtgui_list_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
+{
+	struct rtgui_list_view* view = RT_NULL;
+
+	view = RTGUI_LIST_VIEW(widget);
+	switch (event->type)
+	{
+	case RTGUI_EVENT_PAINT:
+		rtgui_list_view_ondraw(view);
+		return RT_FALSE;
+
+    case RTGUI_EVENT_RESIZE:
+        {
+			struct rtgui_event_resize* resize;
+
+			resize = (struct rtgui_event_resize*)event;
+
+            /* recalculate page items */
+			view->page_items = resize->h  / (2 + rtgui_theme_get_selected_height());
+        }
+        break;
+
+    case RTGUI_EVENT_KBD:
+        {
+            struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
+            if (ekbd->type == RTGUI_KEYDOWN)
+            {
+				rt_uint16_t old_item;
+
+				old_item = view->current_item;
+                switch (ekbd->key)
+                {
+				case RTGUIK_LEFT:
+					if (view->current_item - view->page_items >= 0)
+						view->current_item -= view->page_items;
+					rtgui_list_view_update_current(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);
+					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);
+					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);
+					return RT_FALSE;
+
+				case RTGUIK_RETURN:
+                    if (view->items[view->current_item].action != RT_NULL)
+					{
+					    view->items[view->current_item].action(view->items[view->current_item].parameter);
+					}
+					return RT_FALSE;
+
+                default:
+                    break;
+                }
+            }
+        }
+		return RT_FALSE;
+	}
+
+    /* use view event handler */
+    return rtgui_view_event_handler(widget, event);
+}
+
+rtgui_list_view_t* rtgui_list_view_create(struct rtgui_list_item* items, rt_uint16_t count, rtgui_rect_t *rect)
+{
+	struct rtgui_list_view* view = RT_NULL;
+
+	view = (struct rtgui_list_view*) rtgui_widget_create(RTGUI_LIST_VIEW_TYPE);
+	if (view != RT_NULL)
+	{
+	    view->items = items;
+	    view->items_count = count;
+
+		view->page_items = rtgui_rect_height(*rect) / (2 + rtgui_theme_get_selected_height());
+	}
+
+	return view;
+}
+
+void rtgui_list_view_destroy(rtgui_list_view_t* view)
+{
+    /* destroy view */
+	rtgui_widget_destroy(RTGUI_WIDGET(view));
+}