filelist_view.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. /*
  2. * File : filelist_view.c
  3. * This file is part of RTGUI in RT-Thread RTOS
  4. * COPYRIGHT (C) 2010, RT-Thread Development Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2010-01-06 Bernard first version
  13. */
  14. #include <rtgui/rtgui_object.h>
  15. #include <rtgui/rtgui_system.h>
  16. #include <rtgui/rtgui_theme.h>
  17. #include <rtgui/list.h>
  18. #include <rtgui/image.h>
  19. #include <rtgui/widgets/view.h>
  20. #include <rtgui/widgets/workbench.h>
  21. #include <rtgui/widgets/filelist_view.h>
  22. #include <rtgui/widgets/listbox.h>
  23. #include <rtgui/widgets/window.h>
  24. #if defined(RTGUI_USING_DFS_FILERW) || defined(RTGUI_USING_STDIO_FILERW)
  25. #ifdef _WIN32
  26. #include <io.h>
  27. #include <dirent.h>
  28. #include <sys/stat.h>
  29. #define PATH_SEPARATOR '\\'
  30. #else
  31. #include <dfs_posix.h>
  32. #define PATH_SEPARATOR '/'
  33. #endif
  34. #include <string.h>
  35. #define RTGUI_FILELIST_MARGIN 5
  36. const static char * file_xpm[] = {
  37. "16 16 21 1",
  38. " c None",
  39. ". c #999999",
  40. "+ c #818181",
  41. "@ c #FFFFFF",
  42. "# c #ECECEC",
  43. "$ c #EAEAEA",
  44. "% c #EBEBEB",
  45. "& c #EDEDED",
  46. "* c #F0F0F0",
  47. "= c #C4C4C4",
  48. "- c #C5C5C5",
  49. "; c #C6C6C6",
  50. "> c #C7C7C7",
  51. ", c #EEEEEE",
  52. "' c #EDEDE5",
  53. ") c #EDEDE6",
  54. "! c #EFEFEF",
  55. "~ c #C8C8C8",
  56. "{ c #F1F1F1",
  57. "] c #F2F2F2",
  58. "^ c #959595",
  59. ".++++++++++++ ",
  60. "+@@@@@@@@@@@@+ ",
  61. "+@#$$%%%##&*@+ ",
  62. "+@$=--;;;;>*@+ ",
  63. "+@$%%###&&,*@+ ",
  64. "+@%-;;;;;;>*@+ ",
  65. "+@%%##&&'#,*@+ ",
  66. "+@%;;;;,,),*@+ ",
  67. "+@##&&,,!!!*@+ ",
  68. "+@#;;;>>~~~*@+ ",
  69. "+@#&,,!!*{{{@+ ",
  70. "+@&;>>~~~{{]@+ ",
  71. "+@&&,!!**{]]@+ ",
  72. "+@@@@@@@@@@@@+ ",
  73. "^++++++++++++^ ",
  74. " "};
  75. const static char * folder_xpm[] = {
  76. "16 16 121 2",
  77. " c None",
  78. ". c #D9B434",
  79. "+ c #E1C25E",
  80. "@ c #E2C360",
  81. "# c #E2C35F",
  82. "$ c #DBB63C",
  83. "% c #DAB336",
  84. "& c #FEFEFD",
  85. "* c #FFFFFE",
  86. "= c #FFFEFE",
  87. "- c #FFFEFD",
  88. "; c #FBF7EA",
  89. "> c #E4C76B",
  90. ", c #E3C76B",
  91. "' c #E6CD79",
  92. ") c #E5CA74",
  93. "! c #DAAF35",
  94. "~ c #FEFCF7",
  95. "{ c #F8E48E",
  96. "] c #F5DE91",
  97. "^ c #F5E09F",
  98. "/ c #F6E1AC",
  99. "( c #FEFBEF",
  100. "_ c #FEFDF4",
  101. ": c #FEFCF3",
  102. "< c #FEFCF1",
  103. "[ c #FEFBEE",
  104. "} c #FFFDFA",
  105. "| c #DAAF36",
  106. "1 c #DAAA36",
  107. "2 c #FDFAF1",
  108. "3 c #F5DE94",
  109. "4 c #F4DC93",
  110. "5 c #F2D581",
  111. "6 c #EDCA6A",
  112. "7 c #EACB6C",
  113. "8 c #EFD385",
  114. "9 c #EFD280",
  115. "0 c #EFD07A",
  116. "a c #EECF76",
  117. "b c #EECF72",
  118. "c c #FBF7E9",
  119. "d c #DAAE34",
  120. "e c #DAAB35",
  121. "f c #FBF6E8",
  122. "g c #EFD494",
  123. "h c #EECE88",
  124. "i c #E9C173",
  125. "j c #F6E9C9",
  126. "k c #FEFCF2",
  127. "l c #FEFCF0",
  128. "m c #DAAB36",
  129. "n c #DAA637",
  130. "o c #FFFDF8",
  131. "p c #FFFDF6",
  132. "q c #FFFCF5",
  133. "r c #FCF6D8",
  134. "s c #F8E694",
  135. "t c #F7E385",
  136. "u c #F6DF76",
  137. "v c #F5DB68",
  138. "w c #F4D85C",
  139. "x c #FCF4D7",
  140. "y c #DAA435",
  141. "z c #DAA136",
  142. "A c #FEFCF6",
  143. "B c #FCF2C8",
  144. "C c #FBEFB9",
  145. "D c #FAECAC",
  146. "E c #F9E89C",
  147. "F c #F7E38B",
  148. "G c #F6E07C",
  149. "H c #F6DC6C",
  150. "I c #F5D95D",
  151. "J c #F4D64F",
  152. "K c #F3D344",
  153. "L c #FCF3D0",
  154. "M c #DA9F35",
  155. "N c #DA9A36",
  156. "O c #FDFAF2",
  157. "P c #FAEDB3",
  158. "Q c #F9E9A4",
  159. "R c #F8E695",
  160. "S c #F7E285",
  161. "T c #F6DE76",
  162. "U c #F5DB65",
  163. "V c #F4D757",
  164. "W c #F3D449",
  165. "X c #F2D13B",
  166. "Y c #F1CE30",
  167. "Z c #FBF2CC",
  168. "` c #DA9835",
  169. " . c #DA9435",
  170. ".. c #FEFAEF",
  171. "+. c #F9E9A1",
  172. "@. c #F8E591",
  173. "#. c #F7E181",
  174. "$. c #F6DE72",
  175. "%. c #F5DA63",
  176. "&. c #F4D754",
  177. "*. c #F3D347",
  178. "=. c #F2D039",
  179. "-. c #F1CD2E",
  180. ";. c #F0CB26",
  181. ">. c #FBF2CA",
  182. ",. c #D98E33",
  183. "'. c #FAF0DC",
  184. "). c #F4DDA7",
  185. "!. c #F4DB9E",
  186. "~. c #F3DA96",
  187. "{. c #F3D88E",
  188. "]. c #F3D786",
  189. "^. c #F2D47F",
  190. "/. c #F2D379",
  191. "(. c #F1D272",
  192. "_. c #F1D06C",
  193. ":. c #F1CF69",
  194. "<. c #F8EAC2",
  195. "[. c #D8882D",
  196. "}. c #D8872D",
  197. "|. c #D8862C",
  198. " ",
  199. " ",
  200. " ",
  201. " . + @ @ @ # $ ",
  202. " % & * = - * ; > , , , ' ) ",
  203. " ! ~ { ] ^ / ( _ : < ( [ } | ",
  204. " 1 2 3 4 5 6 7 8 9 0 a b c d ",
  205. " e f g h i j k : k l ( [ * m ",
  206. " n * o p q : r s t u v w x y ",
  207. " z A B C D E F G H I J K L M ",
  208. " N O P Q R S T U V W X Y Z ` ",
  209. " ...+.@.#.$.%.&.*.=.-.;.>. . ",
  210. " ,.'.).!.~.{.].^./.(._.:.<.,. ",
  211. " [.}.[.[.[.[.[.[.[.[.}.[.|. ",
  212. " ",
  213. " "};
  214. /* image for file and folder */
  215. static rtgui_image_t *file_image, *folder_image;
  216. static struct rtgui_listbox_item items[] =
  217. {
  218. #ifdef RTGUI_USING_FONTHZ
  219. {"打开文件夹", RT_NULL},
  220. {"选择文件夹", RT_NULL},
  221. {"退出", RT_NULL}
  222. #else
  223. {"Open folder", RT_NULL},
  224. {"Select folder", RT_NULL},
  225. {"Cancel", RT_NULL}
  226. #endif
  227. };
  228. static void rtgui_filelist_view_clear(rtgui_filelist_view_t* view);
  229. static void rtgui_filelist_view_on_folder_item(rtgui_widget_t* widget, struct rtgui_event* event)
  230. {
  231. rtgui_win_t *menu;
  232. rtgui_listbox_t *listbox;
  233. rtgui_filelist_view_t *view;
  234. listbox = RTGUI_LISTBOX(widget);
  235. menu = RTGUI_WIN(rtgui_widget_get_toplevel(widget));
  236. view = RTGUI_FILELIST_VIEW(menu->user_data);
  237. /* hide window */
  238. rtgui_win_hiden(menu);
  239. switch (listbox->current_item)
  240. {
  241. case 0:
  242. {
  243. char* dir_ptr;
  244. /* destroy menu window */
  245. rtgui_win_destroy(menu);
  246. dir_ptr = (char*) rtgui_malloc (256);
  247. rtgui_filelist_view_get_fullpath(view, dir_ptr, 256);
  248. rtgui_filelist_view_set_directory(view, dir_ptr);
  249. rt_free(dir_ptr);
  250. }
  251. break;
  252. case 1:
  253. /* destroy menu window */
  254. rtgui_win_destroy(menu);
  255. if (RTGUI_VIEW(view)->modal_show == RT_TRUE)
  256. {
  257. rtgui_view_end_modal(RTGUI_VIEW(view), RTGUI_MODAL_OK);
  258. }
  259. break;
  260. default:
  261. /* destroy menu window */
  262. rtgui_win_destroy(menu);
  263. break;
  264. }
  265. }
  266. static rt_bool_t rtgui_filelist_view_on_menu_deactivate(rtgui_widget_t* widget, struct rtgui_event* event)
  267. {
  268. rtgui_win_t *menu;
  269. menu = RTGUI_WIN(rtgui_widget_get_toplevel(widget));
  270. /* destroy menu window */
  271. rtgui_win_destroy(menu);
  272. return RT_TRUE;
  273. }
  274. static void rtgui_filelist_view_menu_pop(rtgui_widget_t *parent)
  275. {
  276. rtgui_win_t *menu;
  277. rtgui_listbox_t *listbox;
  278. rtgui_rect_t screen, rect = {0, 0, 140, 85};
  279. rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), &screen);
  280. rtgui_rect_moveto_align(&screen, &rect, RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL);
  281. menu = rtgui_win_create(RTGUI_TOPLEVEL(rtgui_widget_get_toplevel(parent)),
  282. "Folder Menu", &rect, RTGUI_WIN_STYLE_DEFAULT);
  283. if (menu != RT_NULL)
  284. {
  285. /* set user data on menu window */
  286. menu->user_data = (rt_uint32_t)parent;
  287. rtgui_win_set_ondeactivate(menu, rtgui_filelist_view_on_menu_deactivate);
  288. listbox = rtgui_listbox_create(items, sizeof(items)/sizeof(items[0]), &rect);
  289. rtgui_listbox_set_onitem(listbox, rtgui_filelist_view_on_folder_item);
  290. rtgui_container_add_child(RTGUI_CONTAINER(menu), RTGUI_WIDGET(listbox));
  291. rtgui_win_show(menu, RT_FALSE);
  292. rtgui_widget_focus(RTGUI_WIDGET(listbox));
  293. rtgui_listbox_set_current_item(listbox, 0);
  294. }
  295. }
  296. static void _rtgui_filelist_view_constructor(struct rtgui_filelist_view *view)
  297. {
  298. /* default rect */
  299. struct rtgui_rect rect = {0, 0, 200, 200};
  300. /* set default widget rect and set event handler */
  301. rtgui_widget_set_event_handler(RTGUI_WIDGET(view), rtgui_filelist_view_event_handler);
  302. rtgui_widget_set_rect(RTGUI_WIDGET(view), &rect);
  303. RTGUI_WIDGET(view)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
  304. view->current_item = 0;
  305. view->items_count = 0;
  306. view->page_items = 0;
  307. view->current_directory = RT_NULL;
  308. view->pattern = RT_NULL;
  309. RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(view)) = white;
  310. RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(view)) = RTGUI_ALIGN_CENTER_VERTICAL;
  311. file_image = rtgui_image_create_from_mem("xpm",
  312. (rt_uint8_t*)file_xpm, sizeof(file_xpm), RT_TRUE);
  313. folder_image = rtgui_image_create_from_mem("xpm",
  314. (rt_uint8_t*)folder_xpm, sizeof(folder_xpm), RT_TRUE);
  315. }
  316. static void _rtgui_filelist_view_destructor(struct rtgui_filelist_view *view)
  317. {
  318. /* delete all file items */
  319. rtgui_filelist_view_clear(view);
  320. /* delete current directory and pattern */
  321. rtgui_free(view->current_directory); view->current_directory = RT_NULL;
  322. rtgui_free(view->pattern); view->pattern = RT_NULL;
  323. /* delete image */
  324. rtgui_image_destroy(file_image);
  325. rtgui_image_destroy(folder_image);
  326. }
  327. DEFINE_CLASS_TYPE(filelist, "filelist",
  328. RTGUI_VIEW_TYPE,
  329. _rtgui_filelist_view_constructor,
  330. _rtgui_filelist_view_destructor,
  331. sizeof(struct rtgui_filelist_view));
  332. void rtgui_filelist_view_ondraw(struct rtgui_filelist_view* view)
  333. {
  334. struct rtgui_dc* dc;
  335. rt_uint16_t page_index, index;
  336. struct rtgui_file_item* item;
  337. struct rtgui_rect rect, item_rect, image_rect;
  338. dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view));
  339. if (dc == RT_NULL) return;
  340. rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
  341. rtgui_dc_fill_rect(dc, &rect);
  342. /* get item base rect */
  343. item_rect = rect;
  344. item_rect.y1 += 1;
  345. item_rect.y2 = item_rect.y1 + (1 + rtgui_theme_get_selected_height());
  346. /* get image base rect */
  347. image_rect.x1 = RTGUI_FILELIST_MARGIN; image_rect.y1 = 0;
  348. image_rect.x2 = RTGUI_FILELIST_MARGIN + file_image->w; image_rect.y2 = file_image->h;
  349. rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
  350. /* get current page */
  351. page_index = (view->current_item / view->page_items) * view->page_items;
  352. for (index = 0; index < view->page_items; index ++)
  353. {
  354. if (page_index + index >= view->items_count) break;
  355. item = &(view->items[page_index + index]);
  356. if (page_index + index == view->current_item)
  357. {
  358. rtgui_theme_draw_selected(dc, &item_rect);
  359. }
  360. else
  361. {
  362. /* draw background */
  363. rtgui_dc_fill_rect(dc, &item_rect);
  364. }
  365. /* draw item */
  366. if (item->type == RTGUI_FITEM_FILE)
  367. rtgui_image_blit(file_image, dc, &image_rect);
  368. else
  369. rtgui_image_blit(folder_image, dc, &image_rect);
  370. /* draw text */
  371. item_rect.x1 += RTGUI_FILELIST_MARGIN + file_image->w + 2;
  372. rtgui_dc_draw_text(dc, item->name, &item_rect);
  373. item_rect.x1 -= RTGUI_FILELIST_MARGIN + file_image->w + 2;
  374. /* move to next item position */
  375. item_rect.y1 += (rtgui_theme_get_selected_height() + 1);
  376. item_rect.y2 += (rtgui_theme_get_selected_height() + 1);
  377. image_rect.y1 += (rtgui_theme_get_selected_height() + 1);
  378. image_rect.y2 += (rtgui_theme_get_selected_height() + 1);
  379. }
  380. rtgui_dc_end_drawing(dc);
  381. }
  382. void rtgui_filelist_view_update_current(struct rtgui_filelist_view* view, rt_uint16_t old_item)
  383. {
  384. struct rtgui_dc* dc;
  385. struct rtgui_file_item* item;
  386. rtgui_rect_t rect, item_rect, image_rect;
  387. if (old_item/view->page_items != view->current_item/view->page_items)
  388. {
  389. /* it's not a same page, update all */
  390. rtgui_widget_update(RTGUI_WIDGET(view));
  391. return;
  392. }
  393. dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view));
  394. if (dc == RT_NULL) return;
  395. rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
  396. /* get old item rect */
  397. item_rect = rect;
  398. item_rect.y1 += 1;
  399. item_rect.y1 += (old_item % view->page_items) * (1 + rtgui_theme_get_selected_height());
  400. item_rect.y2 = item_rect.y1 + (1 + rtgui_theme_get_selected_height());
  401. /* get image rect */
  402. image_rect.x1 = RTGUI_FILELIST_MARGIN; image_rect.y1 = 0;
  403. image_rect.x2 = RTGUI_FILELIST_MARGIN + file_image->w; image_rect.y2 = file_image->h;
  404. rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
  405. /* draw old item */
  406. rtgui_dc_fill_rect(dc, &item_rect);
  407. item = &(view->items[old_item]);
  408. if (item->type == RTGUI_FITEM_FILE) /* draw item image */
  409. rtgui_image_blit(file_image, dc, &image_rect);
  410. else
  411. rtgui_image_blit(folder_image, dc, &image_rect);
  412. item_rect.x1 += RTGUI_FILELIST_MARGIN + file_image->w + 2;
  413. rtgui_dc_draw_text(dc, item->name, &item_rect);
  414. /* draw current item */
  415. item_rect = rect;
  416. item_rect.y1 += 1;
  417. item_rect.y1 += (view->current_item % view->page_items) * (1 + rtgui_theme_get_selected_height());
  418. item_rect.y2 = item_rect.y1 + (1 + rtgui_theme_get_selected_height());
  419. rtgui_theme_draw_selected(dc, &item_rect);
  420. /* get image base rect */
  421. image_rect.x1 = RTGUI_FILELIST_MARGIN; image_rect.y1 = 0;
  422. image_rect.x2 = RTGUI_FILELIST_MARGIN + file_image->w; image_rect.y2 = file_image->h;
  423. rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
  424. item = &(view->items[view->current_item]);
  425. if (item->type == RTGUI_FITEM_FILE) /* draw item image */
  426. rtgui_image_blit(file_image, dc, &image_rect);
  427. else
  428. rtgui_image_blit(folder_image, dc, &image_rect);
  429. item_rect.x1 += RTGUI_FILELIST_MARGIN + file_image->w + 2;
  430. rtgui_dc_draw_text(dc, item->name, &item_rect);
  431. rtgui_dc_end_drawing(dc);
  432. }
  433. static void rtgui_filelist_view_onenturn(struct rtgui_filelist_view* view)
  434. {
  435. if (view->items[view->current_item].type == RTGUI_FITEM_DIR)
  436. {
  437. char new_path[64];
  438. if (strcmp(view->items[view->current_item].name, ".") == 0) return ;
  439. if (strcmp(view->items[view->current_item].name, "..") == 0)
  440. {
  441. char *ptr;
  442. ptr = strrchr(view->current_directory, PATH_SEPARATOR);
  443. if (ptr == RT_NULL) return ;
  444. if (ptr == &(view->current_directory[0]))
  445. {
  446. /* it's root directory */
  447. new_path[0] = PATH_SEPARATOR;
  448. new_path[1] = '\0';
  449. }
  450. else
  451. {
  452. strncpy(new_path, view->current_directory, ptr - view->current_directory + 1);
  453. new_path[ptr - view->current_directory] = '\0';
  454. }
  455. }
  456. else if (view->current_item == 0 &&
  457. #ifdef _WIN32
  458. (view->current_directory[1] == ':') && (view->current_directory[2] == '\\'))
  459. #else
  460. (view->current_directory[0] == '/') && (view->current_directory[1] == '\0'))
  461. #endif
  462. {
  463. if (RTGUI_VIEW(view)->modal_show == RT_TRUE)
  464. {
  465. rtgui_view_end_modal(RTGUI_VIEW(view), RTGUI_MODAL_CANCEL);
  466. }
  467. else
  468. {
  469. rtgui_filelist_view_destroy(view);
  470. }
  471. return ;
  472. }
  473. else
  474. {
  475. rtgui_filelist_view_menu_pop(RTGUI_WIDGET(view));
  476. return ;
  477. }
  478. rtgui_filelist_view_set_directory(view, new_path);
  479. }
  480. else
  481. {
  482. if (RTGUI_VIEW(view)->modal_show == RT_TRUE)
  483. {
  484. rtgui_view_end_modal(RTGUI_VIEW(view), RTGUI_MODAL_OK);
  485. }
  486. }
  487. }
  488. rt_bool_t rtgui_filelist_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
  489. {
  490. struct rtgui_filelist_view* view = RT_NULL;
  491. view = RTGUI_FILELIST_VIEW(widget);
  492. switch (event->type)
  493. {
  494. case RTGUI_EVENT_PAINT:
  495. rtgui_filelist_view_ondraw(view);
  496. return RT_FALSE;
  497. case RTGUI_EVENT_RESIZE:
  498. {
  499. struct rtgui_event_resize* resize;
  500. resize = (struct rtgui_event_resize*)event;
  501. /* recalculate page items */
  502. if (file_image != RT_NULL)
  503. view->page_items = resize->h / (1 + rtgui_theme_get_selected_height());
  504. else
  505. view->page_items = resize->h / (2 + 14);
  506. }
  507. break;
  508. case RTGUI_EVENT_MOUSE_BUTTON:
  509. {
  510. rtgui_rect_t rect;
  511. struct rtgui_event_mouse* emouse;
  512. emouse = (struct rtgui_event_mouse*)event;
  513. /* calculate selected item */
  514. /* get physical extent information */
  515. rtgui_widget_get_rect(widget, &rect);
  516. rtgui_widget_rect_to_device(widget, &rect);
  517. if (rtgui_rect_contains_point(&rect, emouse->x, emouse->y) == RT_EOK)
  518. {
  519. rt_uint16_t index;
  520. rt_uint16_t current_page;
  521. rt_uint16_t old_item;
  522. index = (emouse->y - rect.y1) / (2 + rtgui_theme_get_selected_height());
  523. /* get current page */
  524. current_page = view->current_item/view->page_items;
  525. old_item = view->current_item;
  526. if (index + current_page * view->page_items < view->items_count)
  527. {
  528. /* set selected item */
  529. view->current_item = index + current_page * view->page_items;
  530. if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN)
  531. {
  532. rtgui_filelist_view_update_current(view, old_item);
  533. }
  534. else
  535. {
  536. /* up event */
  537. rtgui_filelist_view_onenturn(view);
  538. }
  539. }
  540. return RT_TRUE;
  541. }
  542. }
  543. break;
  544. case RTGUI_EVENT_KBD:
  545. {
  546. struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
  547. if (ekbd->type == RTGUI_KEYDOWN)
  548. {
  549. rt_uint16_t old_item;
  550. old_item = view->current_item;
  551. switch (ekbd->key)
  552. {
  553. case RTGUIK_UP:
  554. if (view->current_item > 0)
  555. view->current_item --;
  556. rtgui_filelist_view_update_current(view, old_item);
  557. return RT_TRUE;
  558. case RTGUIK_DOWN:
  559. if (view->current_item < view->items_count - 1)
  560. view->current_item ++;
  561. rtgui_filelist_view_update_current(view, old_item);
  562. return RT_TRUE;
  563. case RTGUIK_LEFT:
  564. if (view->current_item - view->page_items >= 0)
  565. view->current_item -= view->page_items;
  566. rtgui_filelist_view_update_current(view, old_item);
  567. return RT_TRUE;
  568. case RTGUIK_RIGHT:
  569. if (view->current_item + view->page_items < view->items_count - 1)
  570. view->current_item += view->page_items;
  571. rtgui_filelist_view_update_current(view, old_item);
  572. return RT_TRUE;
  573. case RTGUIK_RETURN:
  574. rtgui_filelist_view_onenturn(view);
  575. return RT_TRUE;
  576. default:
  577. break;
  578. }
  579. }
  580. }
  581. return RT_FALSE;
  582. }
  583. /* use view event handler */
  584. return rtgui_view_event_handler(widget, event);
  585. }
  586. rtgui_filelist_view_t* rtgui_filelist_view_create(rtgui_workbench_t* workbench,
  587. const char* directory, const char* pattern, const rtgui_rect_t* rect)
  588. {
  589. struct rtgui_filelist_view* view = RT_NULL;
  590. /* create a new view */
  591. view = (struct rtgui_filelist_view*) rtgui_widget_create(RTGUI_FILELIST_VIEW_TYPE);
  592. if (view != RT_NULL)
  593. {
  594. view->items = RT_NULL;
  595. view->pattern = rt_strdup(pattern);
  596. view->page_items = rtgui_rect_height(*rect) / (1 + rtgui_theme_get_selected_height());
  597. rtgui_filelist_view_set_directory(view, directory);
  598. rtgui_workbench_add_view(workbench, RTGUI_VIEW(view));
  599. }
  600. return view;
  601. }
  602. void rtgui_filelist_view_destroy(rtgui_filelist_view_t* view)
  603. {
  604. /* destroy view */
  605. rtgui_widget_destroy(RTGUI_WIDGET(view));
  606. }
  607. /* clear all file items */
  608. static void rtgui_filelist_view_clear(rtgui_filelist_view_t* view)
  609. {
  610. rt_uint32_t index;
  611. struct rtgui_file_item* item;
  612. for (index = 0; index < view->items_count; index ++)
  613. {
  614. item = &(view->items[index]);
  615. /* release item name */
  616. rt_free(item->name);
  617. item->name = RT_NULL;
  618. }
  619. /* release items */
  620. rtgui_free(view->items);
  621. view->items = RT_NULL;
  622. view->items_count = 0;
  623. view->current_item = 0;
  624. }
  625. void rtgui_filelist_view_set_directory(rtgui_filelist_view_t* view, const char* directory)
  626. {
  627. struct rtgui_file_item *item;
  628. RT_ASSERT(view != RT_NULL);
  629. /* clear file items firstly */
  630. rtgui_filelist_view_clear(view);
  631. if (directory != RT_NULL)
  632. {
  633. DIR* dir;
  634. struct stat s;
  635. char* fullpath;
  636. rt_uint32_t index;
  637. struct dirent* dirent;
  638. view->items_count = 0;
  639. dir = opendir(directory);
  640. if (dir == RT_NULL) goto __return;
  641. /* current directory exists, set it */
  642. if (view->current_directory != RT_NULL) rt_free(view->current_directory);
  643. view->current_directory = rt_strdup(directory);
  644. do
  645. {
  646. dirent = readdir(dir);
  647. if (dirent == RT_NULL) break;
  648. if (strcmp(dirent->d_name, ".") == 0) continue;
  649. if (strcmp(dirent->d_name, "..") == 0) continue;
  650. view->items_count ++;
  651. } while (dirent != RT_NULL);
  652. closedir(dir);
  653. view->items_count ++; /* root directory for [x] exit, others for .. */
  654. view->items = (struct rtgui_file_item*) rtgui_malloc(sizeof(struct rtgui_file_item) * view->items_count);
  655. if (view->items == RT_NULL) return; /* no memory */
  656. index = 0;
  657. if (directory[0] == '/' && directory[1] != '\0')
  658. {
  659. item = &(view->items[0]);
  660. /* add .. directory */
  661. item->name = rt_strdup("..");
  662. item->type = RTGUI_FITEM_DIR;
  663. item->size = 0;
  664. index ++;
  665. }
  666. else
  667. {
  668. item = &(view->items[0]);
  669. /* add .. directory */
  670. item->name = rt_strdup("退出文件浏览");
  671. item->type = RTGUI_FITEM_DIR;
  672. item->size = 0;
  673. index ++;
  674. }
  675. /* reopen directory */
  676. dir = opendir(directory);
  677. fullpath = rtgui_malloc(256);
  678. while (index < view->items_count)
  679. {
  680. dirent = readdir(dir);
  681. if (dirent == RT_NULL) break;
  682. if (strcmp(dirent->d_name, ".") == 0) continue;
  683. if (strcmp(dirent->d_name, "..") == 0) continue;
  684. item = &(view->items[index]);
  685. item->name = rt_strdup(dirent->d_name);
  686. rt_memset(&s, 0, sizeof(struct stat));
  687. /* build full path for the file */
  688. if (directory[strlen(directory) - 1] != PATH_SEPARATOR)
  689. rt_snprintf(fullpath, 256, "%s%c%s", directory, PATH_SEPARATOR, dirent->d_name);
  690. else
  691. rt_snprintf(fullpath, 256, "%s%s", directory, dirent->d_name);
  692. stat(fullpath, &s);
  693. if ( s.st_mode & S_IFDIR )
  694. {
  695. item->type = RTGUI_FITEM_DIR;
  696. item->size = 0;
  697. }
  698. else
  699. {
  700. item->type = RTGUI_FITEM_FILE;
  701. item->size = s.st_size;
  702. }
  703. index ++;
  704. }
  705. rtgui_free(fullpath);
  706. closedir(dir);
  707. }
  708. view->current_item = 0;
  709. __return:
  710. /* update view */
  711. rtgui_widget_update(RTGUI_WIDGET(view));
  712. }
  713. void rtgui_filelist_view_get_fullpath(rtgui_filelist_view_t* view, char* path, rt_size_t len)
  714. {
  715. RT_ASSERT(view != RT_NULL);
  716. if (view->current_directory[strlen(view->current_directory) - 1] != PATH_SEPARATOR)
  717. rt_snprintf(path, len, "%s%c%s",view->current_directory, PATH_SEPARATOR,
  718. view->items[view->current_item].name);
  719. else
  720. rt_snprintf(path, len, "%s%s",view->current_directory,
  721. view->items[view->current_item].name);
  722. }
  723. #endif