1
0

filelist_view.c 24 KB

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