listbox.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  1. /*
  2. * File : listbox.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_theme.h>
  15. #include <rtgui/widgets/listbox.h>
  16. #define RTGUI_WIDGET_DEFAULT_MARGIN 3
  17. static rt_bool_t rtgui_listbox_unfocus(PVOID wdt, rtgui_event_t* event);
  18. static rt_bool_t rtgui_listbox_sbar_handle(PVOID wdt, rtgui_event_t* event);
  19. static rt_uint32_t rtgui_listbox_get_item_count(rtgui_listbox_t* box);
  20. static void rtgui_listbox_add_item(rtgui_listbox_t* box,rtgui_listbox_item_t* item);
  21. static void _rtgui_listbox_constructor(rtgui_listbox_t *box)
  22. {
  23. /* set default widget rect and set event handler */
  24. rtgui_widget_set_event_handler(box,rtgui_listbox_event_handler);
  25. rtgui_widget_set_onunfocus(box, rtgui_listbox_unfocus);
  26. RTGUI_WIDGET_FLAG(box) |= RTGUI_WIDGET_FLAG_FOCUSABLE;
  27. box->frist_aloc = 0;
  28. box->now_aloc = 0;
  29. box->old_aloc = 0;
  30. box->item_count = 0;
  31. box->item_size = SELECTED_HEIGHT;
  32. box->item_per_page = 0;
  33. box->ispopup = RT_FALSE;
  34. box->widgetlnk = RT_NULL;
  35. RTGUI_WIDGET_BACKGROUND(box) = white;
  36. RTGUI_WIDGET_TEXTALIGN(box) = RTGUI_ALIGN_LEFT|RTGUI_ALIGN_CENTER_VERTICAL;
  37. box->items = RT_NULL;
  38. box->sbar = RT_NULL;
  39. box->on_item = RT_NULL;
  40. box->get_count = rtgui_listbox_get_item_count;
  41. box->add_item = rtgui_listbox_add_item;
  42. }
  43. static void _rtgui_listbox_destructor(rtgui_listbox_t *box)
  44. {
  45. }
  46. rtgui_type_t *rtgui_listbox_type_get(void)
  47. {
  48. static rtgui_type_t *listbox_type = RT_NULL;
  49. if(!listbox_type)
  50. {
  51. listbox_type = rtgui_type_create("listbox", RTGUI_CONTAINER_TYPE,
  52. sizeof(rtgui_listbox_t),
  53. RTGUI_CONSTRUCTOR(_rtgui_listbox_constructor),
  54. RTGUI_DESTRUCTOR(_rtgui_listbox_destructor));
  55. }
  56. return listbox_type;
  57. }
  58. rtgui_listbox_t* rtgui_listbox_create(PVOID parent, int left,int top,int w,int h,rt_uint32_t style)
  59. {
  60. rtgui_listbox_t* box = RT_NULL;
  61. RT_ASSERT(parent != RT_NULL);
  62. box = rtgui_widget_create(RTGUI_LISTBOX_TYPE);
  63. if(box != RT_NULL)
  64. {
  65. rtgui_rect_t rect;
  66. rtgui_widget_get_rect(parent,&rect);
  67. rtgui_widget_rect_to_device(parent, &rect);
  68. rect.x1 += left;
  69. rect.y1 += top;
  70. rect.x2 = rect.x1+w;
  71. rect.y2 = rect.y1+h;
  72. rtgui_widget_set_rect(box,&rect);
  73. rtgui_container_add_child(parent, box);
  74. rtgui_widget_set_style(box,style);
  75. if(box->sbar == RT_NULL)
  76. {//创建卷标控件
  77. rt_uint32_t sLeft,sTop,sWidth=RTGUI_DEFAULT_SB_WIDTH,sLen;
  78. sLeft = rtgui_rect_width(rect)-RTGUI_WIDGET_BORDER(box)-sWidth;
  79. sTop = RTGUI_WIDGET_BORDER(box);
  80. sLen = rtgui_rect_height(rect)-RTGUI_WIDGET_BORDER(box)*2;
  81. box->sbar = rtgui_scrollbar_create(box,sLeft,sTop,sWidth,sLen,RTGUI_VERTICAL);
  82. if(box->sbar != RT_NULL)
  83. {
  84. box->sbar->widgetlnk = (PVOID)box;
  85. box->sbar->on_scroll = rtgui_listbox_sbar_handle;
  86. RTGUI_WIDGET_HIDE(box->sbar);//默认隐藏滚动条
  87. }
  88. }
  89. }
  90. return box;
  91. }
  92. void rtgui_listbox_set_items(rtgui_listbox_t* box, rtgui_listbox_item_t* items, rt_uint32_t count)
  93. {
  94. rtgui_rect_t rect;
  95. rt_uint32_t i,h;;
  96. RT_ASSERT(box != RT_NULL);
  97. if(box->items != RT_NULL)
  98. {
  99. rt_free(box->items);
  100. box->items = RT_NULL;
  101. }
  102. //支持增加/删除项目,动态空间
  103. box->items = (rtgui_listbox_item_t*) rt_malloc(sizeof(rtgui_listbox_item_t)*count);
  104. if(box->items == RT_NULL) return;
  105. for(i=0;i<count;i++)
  106. {
  107. box->items[i].name = rt_strdup(items[i].name);
  108. box->items[i].image = items[i].image;
  109. }
  110. box->item_count = count;
  111. box->now_aloc = 0;
  112. box->old_aloc = 0;
  113. rtgui_widget_get_rect(box, &rect);
  114. box->item_per_page = rtgui_rect_height(rect) / (box->item_size+2);
  115. if(box->ispopup)//弹出式下拉列表,例如点击combo控件之后
  116. {
  117. if(box->item_count < 5)
  118. box->item_per_page = count;
  119. else
  120. box->item_per_page = 5;
  121. h = 2+(box->item_size+2)*box->item_per_page;
  122. rect.y2 = rect.y1+h;
  123. rtgui_widget_rect_to_device(box,&rect);
  124. rtgui_widget_set_rect(box,&rect);//更新box的大小
  125. if(box->sbar != RT_NULL) //更新sbar的extent
  126. {
  127. rtgui_widget_get_rect(box->sbar,&rect);
  128. rect.y2 = rect.y1+h-RTGUI_WIDGET_BORDER(box)*2;
  129. rtgui_widget_rect_to_device(box->sbar,&rect);
  130. rtgui_widget_set_rect(box->sbar,&rect);
  131. }
  132. }
  133. if(box->sbar != RT_NULL)//更新sbar的参数
  134. {
  135. if(box->item_count > box->item_per_page)
  136. {
  137. RTGUI_WIDGET_UNHIDE(box->sbar);
  138. rtgui_scrollbar_set_line_step(box->sbar, 1);
  139. rtgui_scrollbar_set_page_step(box->sbar, box->item_per_page);
  140. rtgui_scrollbar_set_range(box->sbar, box->item_count);
  141. }
  142. else
  143. {
  144. RTGUI_WIDGET_HIDE(box->sbar);
  145. }
  146. rtgui_widget_update_clip(box);
  147. }
  148. }
  149. void rtgui_listbox_destroy(rtgui_listbox_t* box)
  150. {
  151. /* destroy box */
  152. rtgui_widget_destroy(box);
  153. }
  154. //绘制ListBox界面,绘制所有行
  155. void rtgui_listbox_ondraw(rtgui_listbox_t* box)
  156. {
  157. rtgui_rect_t rect, item_rect, image_rect;
  158. rt_uint16_t frist, i;
  159. const rtgui_listbox_item_t* item;
  160. rtgui_dc_t* dc;
  161. RT_ASSERT(box != RT_NULL);
  162. /* begin drawing */
  163. dc = rtgui_dc_begin_drawing(box);
  164. if(dc == RT_NULL)return;
  165. rtgui_widget_get_rect(box, &rect);
  166. //绘制边框
  167. rtgui_dc_draw_border(dc, &rect,RTGUI_WIDGET_BORDER_STYLE(box));
  168. rtgui_rect_inflate(&rect,-RTGUI_WIDGET_BORDER(box));
  169. RTGUI_DC_BC(dc) = white;
  170. rtgui_dc_fill_rect(dc, &rect);
  171. rtgui_rect_inflate(&rect,RTGUI_WIDGET_BORDER(box));
  172. if(box->items==RT_NULL)return;//没有项目,则不再绘制内容
  173. if(box->sbar && !RTGUI_WIDGET_IS_HIDE(box->sbar))
  174. {
  175. rect.x2 -= rtgui_rect_width(box->sbar->parent.extent);
  176. }
  177. /* get item base rect */
  178. item_rect = rect;
  179. item_rect.x1 += RTGUI_WIDGET_BORDER(box);
  180. item_rect.x2 -= RTGUI_WIDGET_BORDER(box);
  181. item_rect.y1 += RTGUI_WIDGET_BORDER(box);
  182. item_rect.y2 = item_rect.y1 + (2+box->item_size);
  183. /* get frist aloc */
  184. frist = box->frist_aloc;
  185. for(i = 0; i < box->item_per_page; i ++)
  186. {
  187. if(frist + i >= box->item_count) break;
  188. item = &(box->items[frist + i]);
  189. if(frist + i == box->now_aloc)
  190. {//draw current item
  191. if(RTGUI_WIDGET_IS_FOCUSED(box))
  192. {
  193. RTGUI_DC_BC(dc) = selected_color;
  194. RTGUI_DC_FC(dc) = white;
  195. rtgui_dc_fill_rect(dc, &item_rect);
  196. rtgui_dc_draw_focus_rect(dc, &item_rect); //绘制焦点框
  197. }
  198. else
  199. {
  200. RTGUI_DC_BC(dc) = dark_grey;
  201. RTGUI_DC_FC(dc) = black;
  202. rtgui_dc_fill_rect(dc, &item_rect);
  203. }
  204. }
  205. item_rect.x1 += RTGUI_WIDGET_DEFAULT_MARGIN;
  206. if(item->image != RT_NULL)
  207. {
  208. /* get image base rect */
  209. image_rect.x1 = 0;
  210. image_rect.y1 = 0;
  211. image_rect.x2 = item->image->w;
  212. image_rect.y2 = item->image->h;
  213. rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
  214. rtgui_image_paste(item->image, dc, &image_rect, white);
  215. item_rect.x1 += item->image->w + 2;
  216. }
  217. /* draw text */
  218. if(frist + i == box->now_aloc && RTGUI_WIDGET_IS_FOCUSED(box))
  219. {
  220. RTGUI_DC_FC(dc) = white;
  221. rtgui_dc_draw_text(dc, item->name, &item_rect);
  222. }
  223. else
  224. {
  225. RTGUI_DC_FC(dc) = black;
  226. rtgui_dc_draw_text(dc, item->name, &item_rect);
  227. }
  228. if(item->image != RT_NULL)
  229. item_rect.x1 -= (item->image->w + 2);
  230. item_rect.x1 -= RTGUI_WIDGET_DEFAULT_MARGIN;
  231. /* move to next item position */
  232. item_rect.y1 += (box->item_size + 2);
  233. item_rect.y2 += (box->item_size + 2);
  234. }
  235. if(box->sbar && !RTGUI_WIDGET_IS_HIDE(box->sbar))
  236. {
  237. rtgui_theme_draw_scrollbar(box->sbar);
  238. }
  239. rtgui_dc_end_drawing(dc);
  240. }
  241. //更新ListBox界面,只处理新旧焦点行
  242. void rtgui_listbox_update(rtgui_listbox_t* box)
  243. {
  244. const rtgui_listbox_item_t* item;
  245. rtgui_rect_t rect, item_rect, image_rect;
  246. rtgui_dc_t* dc;
  247. RT_ASSERT(box != RT_NULL);
  248. if(RTGUI_WIDGET_IS_HIDE(box))return;
  249. if(box->items==RT_NULL)return;
  250. /* begin drawing */
  251. dc = rtgui_dc_begin_drawing(box);
  252. if(dc == RT_NULL)return;
  253. rtgui_widget_get_rect(box, &rect);
  254. if(box->sbar && !RTGUI_WIDGET_IS_HIDE(box->sbar))
  255. {
  256. rect.x2 -= rtgui_rect_width(box->sbar->parent.extent);
  257. }
  258. if((box->old_aloc >= box->frist_aloc) && /* 在之后某页中 */
  259. (box->old_aloc < box->frist_aloc+box->item_per_page) && /* 在之前某页中 */
  260. (box->old_aloc != box->now_aloc)) /* 位置没有变化,不需要刷旧行 */
  261. {//这些条件,可以最大限度的减少绘图闪烁现象
  262. item_rect = rect;
  263. /* get old item's rect */
  264. item_rect.x1 += RTGUI_WIDGET_BORDER(box);
  265. item_rect.x2 -= RTGUI_WIDGET_BORDER(box);
  266. item_rect.y1 += RTGUI_WIDGET_BORDER(box);
  267. item_rect.y1 += ((box->old_aloc-box->frist_aloc) % box->item_per_page) * (2 + box->item_size);
  268. item_rect.y2 = item_rect.y1 + (2+box->item_size);
  269. /* draw old item */
  270. RTGUI_DC_BC(dc) = white;
  271. RTGUI_DC_FC(dc) = black;
  272. rtgui_dc_fill_rect(dc,&item_rect);
  273. item_rect.x1 += RTGUI_WIDGET_DEFAULT_MARGIN;
  274. item = &(box->items[box->old_aloc]);
  275. if(item->image != RT_NULL)
  276. {
  277. image_rect.x1 = 0;
  278. image_rect.y1 = 0;
  279. image_rect.x2 = item->image->w;
  280. image_rect.y2 = item->image->h;
  281. rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
  282. rtgui_image_paste(item->image, dc, &image_rect, white);
  283. item_rect.x1 += item->image->w + 2;
  284. }
  285. rtgui_dc_draw_text(dc, item->name, &item_rect);
  286. }
  287. /* draw now item */
  288. item_rect = rect;
  289. /* get now item's rect */
  290. item_rect.x1 += RTGUI_WIDGET_BORDER(box);
  291. item_rect.x2 -= RTGUI_WIDGET_BORDER(box);
  292. item_rect.y1 += RTGUI_WIDGET_BORDER(box);
  293. item_rect.y1 += ((box->now_aloc-box->frist_aloc) % box->item_per_page) * (2 + box->item_size);
  294. item_rect.y2 = item_rect.y1 + (2 + box->item_size);
  295. /* draw current item */
  296. if(RTGUI_WIDGET_IS_FOCUSED(box))
  297. {
  298. RTGUI_DC_BC(dc) = selected_color;
  299. RTGUI_DC_FC(dc) = white;
  300. rtgui_dc_fill_rect(dc, &item_rect);
  301. rtgui_dc_draw_focus_rect(dc, &item_rect); //绘制焦点框
  302. }
  303. else
  304. {
  305. RTGUI_DC_BC(dc) = dark_grey;
  306. RTGUI_DC_FC(dc) = black;
  307. rtgui_dc_fill_rect(dc, &item_rect);
  308. }
  309. item_rect.x1 += RTGUI_WIDGET_DEFAULT_MARGIN;
  310. item = &(box->items[box->now_aloc]);
  311. if(item->image != RT_NULL)
  312. {
  313. image_rect.x1 = 0;
  314. image_rect.y1 = 0;
  315. image_rect.x2 = item->image->w;
  316. image_rect.y2 = item->image->h;
  317. rtgui_rect_moveto_align(&item_rect, &image_rect, RTGUI_ALIGN_CENTER_VERTICAL);
  318. rtgui_image_paste(item->image, dc, &image_rect, white);
  319. item_rect.x1 += (item->image->w + 2);
  320. }
  321. if(RTGUI_WIDGET_IS_FOCUSED(box))
  322. {
  323. RTGUI_DC_FC(dc) = white;
  324. rtgui_dc_draw_text(dc, item->name, &item_rect);
  325. }
  326. else
  327. {
  328. RTGUI_DC_FC(dc) = black;
  329. rtgui_dc_draw_text(dc, item->name, &item_rect);
  330. }
  331. box->old_aloc = box->now_aloc;
  332. rtgui_dc_end_drawing(dc);
  333. }
  334. rt_bool_t rtgui_listbox_event_handler(PVOID wdt, rtgui_event_t* event)
  335. {
  336. rtgui_listbox_t* box = (rtgui_listbox_t*)wdt;
  337. RT_ASSERT(box != RT_NULL);
  338. switch (event->type)
  339. {
  340. case RTGUI_EVENT_PAINT:
  341. {
  342. rtgui_dc_t *dc;
  343. dc = rtgui_dc_begin_drawing(box);
  344. if(dc == RT_NULL)return RT_FALSE;
  345. if(!RTGUI_WIDGET_IS_FOCUSED(box))
  346. {
  347. rtgui_rect_t rect;
  348. rtgui_widget_get_rect(box, &rect);
  349. rtgui_dc_fill_rect(dc,&rect);
  350. }
  351. rtgui_dc_end_drawing(dc);
  352. rtgui_listbox_ondraw(box);
  353. return RT_FALSE;
  354. }
  355. case RTGUI_EVENT_RESIZE:
  356. {
  357. rtgui_event_resize_t* resize;
  358. resize = (rtgui_event_resize_t*)event;
  359. /* recalculate page items */
  360. box->item_per_page = resize->h / (2 + box->item_size);
  361. }
  362. break;
  363. case RTGUI_EVENT_MOUSE_BUTTON:
  364. {
  365. rtgui_rect_t rect;
  366. rtgui_event_mouse_t* emouse;
  367. emouse = (rtgui_event_mouse_t*)event;
  368. /* get physical extent information */
  369. rtgui_widget_get_rect(box, &rect);
  370. if(box->sbar && !RTGUI_WIDGET_IS_HIDE(box->sbar))
  371. rect.x2 -= rtgui_rect_width(box->sbar->parent.extent);
  372. if((rtgui_region_contains_point(&RTGUI_WIDGET_CLIP(box), emouse->x, emouse->y,&rect) == RT_EOK) && (box->item_count > 0))
  373. {
  374. rt_uint16_t i;
  375. i = (emouse->y - rect.y1) / (2 + box->item_size);
  376. /* set focus */
  377. rtgui_widget_focus(box);
  378. if((i < box->item_count) && (i < box->item_per_page))
  379. {
  380. if(emouse->button & RTGUI_MOUSE_BUTTON_DOWN)
  381. {
  382. box->old_aloc = box->now_aloc;
  383. /* set selected item */
  384. box->now_aloc = box->frist_aloc + i;
  385. if(box->on_item != RT_NULL)
  386. {
  387. box->on_item(box, RT_NULL);
  388. }
  389. /* down event */
  390. rtgui_listbox_update(box);
  391. }
  392. else if(emouse->button & RTGUI_MOUSE_BUTTON_UP)
  393. {
  394. rtgui_listbox_update(box);
  395. if(box->ispopup && !RTGUI_WIDGET_IS_HIDE(box))
  396. {
  397. RTGUI_WIDGET_HIDE(box);
  398. box->frist_aloc=0;
  399. box->now_aloc = 0;
  400. rtgui_widget_update_clip(RTGUI_WIDGET_PARENT(box));
  401. rtgui_widget_update(RTGUI_WIDGET_PARENT(box));
  402. return RT_TRUE;
  403. }
  404. }
  405. if(box->sbar && !RTGUI_WIDGET_IS_HIDE(box))
  406. {
  407. if(!RTGUI_WIDGET_IS_HIDE(box->sbar))
  408. rtgui_scrollbar_set_value(box->sbar,box->frist_aloc);
  409. }
  410. }
  411. }
  412. }
  413. break;
  414. case RTGUI_EVENT_KBD:
  415. {
  416. rtgui_event_kbd_t* ekbd = (rtgui_event_kbd_t*)event;
  417. if((RTGUI_KBD_IS_DOWN(ekbd)) && (box->item_count > 0))
  418. {
  419. switch (ekbd->key)
  420. {
  421. case RTGUIK_UP:
  422. if(box->now_aloc > 0)
  423. {
  424. box->old_aloc = box->now_aloc;
  425. box->now_aloc --;
  426. if(box->now_aloc < box->frist_aloc)
  427. {
  428. if(box->frist_aloc)box->frist_aloc--;
  429. rtgui_listbox_ondraw(box);
  430. }
  431. else
  432. {
  433. rtgui_listbox_update(box);
  434. }
  435. if(box->sbar && !RTGUI_WIDGET_IS_HIDE(box))
  436. {
  437. if(!RTGUI_WIDGET_IS_HIDE(box->sbar))
  438. rtgui_scrollbar_set_value(box->sbar,box->frist_aloc);
  439. }
  440. if(box->on_item != RT_NULL)
  441. {
  442. box->on_item(box, RT_NULL);
  443. }
  444. }
  445. break;
  446. case RTGUIK_DOWN:
  447. if(box->now_aloc < box->item_count - 1)
  448. {
  449. box->old_aloc = box->now_aloc;
  450. box->now_aloc ++;
  451. if(box->now_aloc >= box->frist_aloc+box->item_per_page)
  452. {
  453. box->frist_aloc++;
  454. rtgui_listbox_ondraw(box);
  455. }
  456. else
  457. {
  458. rtgui_listbox_update(box);
  459. }
  460. if(box->sbar && !RTGUI_WIDGET_IS_HIDE(box))
  461. {
  462. if(!RTGUI_WIDGET_IS_HIDE(box->sbar))
  463. rtgui_scrollbar_set_value(box->sbar,box->frist_aloc);
  464. }
  465. if(box->on_item != RT_NULL)
  466. {
  467. box->on_item(box, RT_NULL);
  468. }
  469. }
  470. break;
  471. case RTGUIK_RETURN:
  472. if(box->on_item != RT_NULL)
  473. {
  474. box->on_item(box, RT_NULL);
  475. }
  476. if(box->ispopup && !RTGUI_WIDGET_IS_HIDE(box))
  477. {
  478. RTGUI_WIDGET_HIDE(box);
  479. box->frist_aloc=0;
  480. box->now_aloc = 0;
  481. rtgui_widget_update_clip(RTGUI_WIDGET_PARENT(box));
  482. rtgui_widget_update(RTGUI_WIDGET_PARENT(box));
  483. }
  484. break;
  485. default:
  486. break;
  487. }
  488. }
  489. return RT_FALSE;
  490. }
  491. default:
  492. return rtgui_container_event_handler(box, event);
  493. }
  494. /* use box event handler */
  495. return rtgui_container_event_handler(box, event);
  496. }
  497. void rtgui_listbox_set_onitem(rtgui_listbox_t* box, rtgui_event_handler_ptr func)
  498. {
  499. if(box == RT_NULL) return;
  500. box->on_item = func;
  501. }
  502. void rtgui_listbox_delete_item(rtgui_listbox_t* box, rt_uint32_t item_num)
  503. {
  504. rtgui_listbox_item_t* _items;
  505. rt_base_t i;
  506. if(box == RT_NULL) return;
  507. for(i=item_num;i<box->item_count-1;i++)
  508. {
  509. if(box->items[i].name != RT_NULL)
  510. {
  511. rt_free(box->items[i].name);
  512. box->items[i].name = RT_NULL;
  513. }
  514. box->items[i].name = box->items[i+1].name;
  515. box->items[i].image = box->items[i+1].image;
  516. }
  517. box->item_count -= 1;
  518. _items = rt_realloc(box->items,sizeof(rtgui_listbox_item_t)*(box->item_count));
  519. if(_items != RT_NULL)
  520. {
  521. box->items = _items;
  522. }
  523. rtgui_listbox_ondraw(box);
  524. }
  525. static void rtgui_listbox_add_item(rtgui_listbox_t* box,rtgui_listbox_item_t* item)
  526. {
  527. rtgui_listbox_item_t* _items;
  528. RT_ASSERT(box != RT_NULL);
  529. if(box->item_count==0)
  530. {
  531. _items = rt_malloc(sizeof(rtgui_listbox_item_t)*(box->item_count+1));
  532. }
  533. else
  534. {
  535. _items = rt_realloc(box->items,sizeof(rtgui_listbox_item_t)*(box->item_count+1));
  536. }
  537. if(_items != RT_NULL)
  538. {
  539. box->items = _items;
  540. box->items[box->item_count].name = rt_strdup(item->name);
  541. box->items[box->item_count].image= item->image;
  542. box->item_count += 1;
  543. if(box->sbar != RT_NULL)
  544. {
  545. if(RTGUI_WIDGET_IS_HIDE(box->sbar))
  546. {
  547. if(box->item_count > box->item_per_page)
  548. {
  549. RTGUI_WIDGET_UNHIDE(box->sbar);
  550. rtgui_scrollbar_set_line_step(box->sbar, 1);
  551. rtgui_scrollbar_set_page_step(box->sbar, box->item_per_page);
  552. rtgui_scrollbar_set_range(box->sbar, box->item_count);
  553. }
  554. else
  555. {
  556. RTGUI_WIDGET_HIDE(box->sbar);
  557. }
  558. rtgui_widget_update_clip(box);
  559. }
  560. else
  561. {
  562. rtgui_scrollbar_set_range(box->sbar, box->item_count);
  563. }
  564. }
  565. if(!RTGUI_WIDGET_IS_HIDE(box))
  566. rtgui_listbox_ondraw(box);
  567. }
  568. }
  569. static rt_uint32_t rtgui_listbox_get_item_count(rtgui_listbox_t* box)
  570. {
  571. return box->item_count;
  572. }
  573. static rt_bool_t rtgui_listbox_unfocus(PVOID wdt, rtgui_event_t* event)
  574. {
  575. rtgui_listbox_t *box = (rtgui_listbox_t*)wdt;
  576. if(box == RT_NULL)return RT_FALSE;
  577. if(!RTGUI_WIDGET_IS_FOCUSED(box))
  578. {//清除焦点框
  579. rtgui_listbox_update(RTGUI_LISTBOX(wdt));
  580. }
  581. if(box->ispopup)
  582. {//是弹出列表,说明是挂在一些控件(例如combo)下的
  583. rtgui_win_t *win;
  584. RTGUI_WIDGET_HIDE(box);
  585. box->frist_aloc=0;
  586. box->now_aloc = 0;
  587. //rtgui_widget_update_clip(RTGUI_WIDGET_PARENT(box));
  588. //rtgui_widget_update_clip_pirate(RTGUI_WIDGET_PARENT(box),box);
  589. win = rtgui_win_get_win_by_widget(box);
  590. if(win != RT_NULL)
  591. {//在一个窗口中
  592. if(rtgui_rect_is_intersect(&(RTGUI_WIDGET_EXTENT(win)),
  593. &(RTGUI_WIDGET_EXTENT(box))) == RT_EOK)
  594. {
  595. rtgui_topwin_move(win,RTGUI_WIDGET_EXTENT(win).x1,
  596. RTGUI_WIDGET_EXTENT(win).y1);
  597. }
  598. rtgui_widget_focus(win);
  599. rtgui_widget_update_clip(win);
  600. }
  601. rtgui_panel_redraw(&(RTGUI_WIDGET_EXTENT(box)));
  602. }
  603. return RT_TRUE;
  604. }
  605. static rt_bool_t rtgui_listbox_sbar_handle(PVOID wdt, rtgui_event_t* event)
  606. {
  607. rtgui_listbox_t *box = (rtgui_listbox_t*)wdt;
  608. //拖动时,改变第一行
  609. box->frist_aloc = box->sbar->value;
  610. rtgui_listbox_ondraw(box);
  611. return RT_TRUE;
  612. }