/*
 * File      : filelist_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_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>
#include <rtgui/widgets/listbox.h>
#include <rtgui/widgets/window.h>

#if defined(RTGUI_USING_DFS_FILERW) || defined(RTGUI_USING_STDIO_FILERW)
#ifdef _WIN32
#include <io.h>
#include <dirent.h>
#include <sys/stat.h>
#define PATH_SEPARATOR		'\\'
#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_listbox_item items[] = 
{
#ifdef RTGUI_USING_FONTHZ
	{"���ļ���", RT_NULL},
	{"ѡ���ļ���", RT_NULL},
	{"�˳�", RT_NULL}
#else
	{"Open folder", RT_NULL},
	{"Select folder", RT_NULL},
	{"Cancel", RT_NULL}
#endif
};
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_win_show(menu, RT_FALSE);
		rtgui_widget_focus(RTGUI_WIDGET(listbox));
		rtgui_listbox_set_current_item(listbox, 0);
	}
}

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);
}

static void _rtgui_filelist_view_destructor(struct rtgui_filelist_view *view)
{
    /* delete all file items */
    rtgui_filelist_view_clear(view);
	/* delete current directory and pattern */
	rtgui_free(view->current_directory); view->current_directory = RT_NULL;
	rtgui_free(view->pattern); view->pattern = RT_NULL;

	/* delete image */
	rtgui_image_destroy(file_image);
	rtgui_image_destroy(folder_image);
}

DEFINE_CLASS_TYPE(filelist, "filelist", 
	RTGUI_VIEW_TYPE,
	_rtgui_filelist_view_constructor,
	_rtgui_filelist_view_destructor,
	sizeof(struct rtgui_filelist_view));

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);
}

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;

	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_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;
				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 + current_page * view->page_items < view->items_count)
				{
					/* set selected 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;

    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_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_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_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_TRUE;

				case RTGUIK_RETURN:
					rtgui_filelist_view_onenturn(view);
					return RT_TRUE;

                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)
{
    /* destroy view */
	rtgui_widget_destroy(RTGUI_WIDGET(view));
}

/* clear all file items */
static 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)
{
    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;
		char* fullpath;
		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);
		fullpath = rtgui_malloc(256);
		while (index < view->items_count)
		{
			dirent = readdir(dir);
			if (dirent == RT_NULL) break;

			if (strcmp(dirent->d_name, ".") == 0) continue;
			if (strcmp(dirent->d_name, "..") == 0) continue;

			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)
				rt_snprintf(fullpath, 256, "%s%c%s", directory, PATH_SEPARATOR, dirent->d_name);
			else
				rt_snprintf(fullpath, 256, "%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;
			}

			index ++;
		}
		rtgui_free(fullpath);
		closedir(dir);
    }

	view->current_item = 0;

__return:
    /* update view */
    rtgui_widget_update(RTGUI_WIDGET(view));
}

void rtgui_filelist_view_get_fullpath(rtgui_filelist_view_t* view, char* path, rt_size_t len)
{
	RT_ASSERT(view != RT_NULL);

	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);
}
#endif