listview.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. #include "listview.h"
  2. #include <rtgui/rtgui_theme.h>
  3. #define LIST_MARGIN 5
  4. static void _list_view_constructor(struct list_view *view)
  5. {
  6. /* default rect */
  7. struct rtgui_rect rect = {0, 0, 200, 200};
  8. /* set default widget rect and set event handler */
  9. rtgui_widget_set_event_handler(RTGUI_WIDGET(view),list_view_event_handler);
  10. rtgui_widget_set_rect(RTGUI_WIDGET(view), &rect);
  11. RTGUI_WIDGET(view)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
  12. view->current_item = 0;
  13. view->items_count = 0;
  14. view->page_items = 0;
  15. RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(view)) = white;
  16. RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(view)) = RTGUI_ALIGN_CENTER_VERTICAL;
  17. }
  18. rtgui_type_t *list_view_type_get(void)
  19. {
  20. static rtgui_type_t *list_view_type = RT_NULL;
  21. if (!list_view_type)
  22. {
  23. list_view_type = rtgui_type_create("listview", RTGUI_VIEW_TYPE,
  24. sizeof(list_view_t), RTGUI_CONSTRUCTOR(_list_view_constructor), RT_NULL);
  25. }
  26. return list_view_type;
  27. }
  28. void list_view_ondraw(struct list_view* view)
  29. {
  30. struct rtgui_rect rect, item_rect;
  31. struct rtgui_dc* dc;
  32. rt_uint16_t page_index, index;
  33. struct list_item* item;
  34. dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view));
  35. if (dc == RT_NULL) return;
  36. rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
  37. rtgui_dc_fill_rect(dc, &rect);
  38. /* get item base rect */
  39. item_rect = rect;
  40. item_rect.y1 += 2;
  41. item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height());
  42. /* get current page */
  43. page_index = (view->current_item / view->page_items) * view->page_items;
  44. for (index = 0; index < view->page_items; index ++)
  45. {
  46. if (page_index + index >= view->items_count) break;
  47. item = &(view->items[page_index + index]);
  48. if (page_index + index == view->current_item)
  49. {
  50. rtgui_theme_draw_selected(dc, &item_rect);
  51. }
  52. item_rect.x1 += LIST_MARGIN;
  53. if (item->image != RT_NULL)
  54. {
  55. rtgui_image_blit(item->image, dc, &item_rect);
  56. item_rect.x1 += item->image->w + 2;
  57. }
  58. /* draw text */
  59. rtgui_dc_draw_text(dc, item->name, &item_rect);
  60. if (item->image != RT_NULL)
  61. item_rect.x1 -= (item->image->w + 2);
  62. item_rect.x1 -= LIST_MARGIN;
  63. /* move to next item position */
  64. item_rect.y1 += (rtgui_theme_get_selected_height() + 2);
  65. item_rect.y2 += (rtgui_theme_get_selected_height() + 2);
  66. }
  67. rtgui_dc_end_drawing(dc);
  68. }
  69. void list_view_update_current(struct list_view* view, rt_uint16_t old_item)
  70. {
  71. struct rtgui_dc* dc;
  72. struct list_item* item;
  73. rtgui_rect_t rect, item_rect;
  74. if (old_item/view->page_items != view->current_item/view->page_items)
  75. {
  76. /* it's not a same page, update all */
  77. rtgui_widget_update(RTGUI_WIDGET(view));
  78. return;
  79. }
  80. dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(view));
  81. if (dc == RT_NULL) return;
  82. rtgui_widget_get_rect(RTGUI_WIDGET(view), &rect);
  83. item_rect = rect;
  84. /* get old item's rect */
  85. item_rect.y1 += 2;
  86. item_rect.y1 += (old_item % view->page_items) * (2 + rtgui_theme_get_selected_height());
  87. item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height());
  88. /* draw old item */
  89. rtgui_dc_fill_rect(dc, &item_rect);
  90. item_rect.x1 += LIST_MARGIN;
  91. item = &(view->items[old_item]);
  92. if (item->image != RT_NULL)
  93. {
  94. rtgui_image_blit(item->image, dc, &item_rect);
  95. item_rect.x1 += item->image->w + 2;
  96. }
  97. rtgui_dc_draw_text(dc, item->name, &item_rect);
  98. /* draw current item */
  99. item_rect = rect;
  100. /* get current item's rect */
  101. item_rect.y1 += 2;
  102. item_rect.y1 += (view->current_item % view->page_items) * (2 + rtgui_theme_get_selected_height());
  103. item_rect.y2 = item_rect.y1 + (2 + rtgui_theme_get_selected_height());
  104. /* draw current item */
  105. rtgui_theme_draw_selected(dc, &item_rect);
  106. item_rect.x1 += LIST_MARGIN;
  107. item = &(view->items[view->current_item]);
  108. if (item->image != RT_NULL)
  109. {
  110. rtgui_image_blit(item->image, dc, &item_rect);
  111. item_rect.x1 += (item->image->w + 2);
  112. }
  113. rtgui_dc_draw_text(dc, item->name, &item_rect);
  114. rtgui_dc_end_drawing(dc);
  115. }
  116. rt_bool_t list_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
  117. {
  118. struct list_view* view = RT_NULL;
  119. view = LIST_VIEW(widget);
  120. switch (event->type)
  121. {
  122. case RTGUI_EVENT_PAINT:
  123. list_view_ondraw(view);
  124. return RT_FALSE;
  125. case RTGUI_EVENT_RESIZE:
  126. {
  127. struct rtgui_event_resize* resize;
  128. resize = (struct rtgui_event_resize*)event;
  129. /* recalculate page items */
  130. view->page_items = resize->h / (2 + rtgui_theme_get_selected_height());
  131. }
  132. break;
  133. case RTGUI_EVENT_KBD:
  134. {
  135. struct rtgui_event_kbd* ekbd = (struct rtgui_event_kbd*)event;
  136. if (ekbd->type == RTGUI_KEYDOWN)
  137. {
  138. rt_uint16_t old_item;
  139. old_item = view->current_item;
  140. switch (ekbd->key)
  141. {
  142. case RTGUIK_LEFT:
  143. if (view->current_item - view->page_items >= 0)
  144. view->current_item -= view->page_items;
  145. list_view_update_current(view, old_item);
  146. return RT_FALSE;
  147. case RTGUIK_UP:
  148. if (view->current_item > 0)
  149. view->current_item --;
  150. list_view_update_current(view, old_item);
  151. return RT_FALSE;
  152. case RTGUIK_RIGHT:
  153. if (view->current_item + view->page_items < view->items_count - 1)
  154. view->current_item += view->page_items;
  155. list_view_update_current(view, old_item);
  156. return RT_FALSE;
  157. case RTGUIK_DOWN:
  158. if (view->current_item < view->items_count - 1)
  159. view->current_item ++;
  160. list_view_update_current(view, old_item);
  161. return RT_FALSE;
  162. case RTGUIK_RETURN:
  163. if (view->items[view->current_item].action != RT_NULL)
  164. {
  165. view->items[view->current_item].action(view->items[view->current_item].parameter);
  166. }
  167. return RT_FALSE;
  168. default:
  169. break;
  170. }
  171. }
  172. }
  173. return RT_FALSE;
  174. }
  175. /* use view event handler */
  176. return rtgui_view_event_handler(widget, event);
  177. }
  178. list_view_t* list_view_create(struct list_item* items, rt_uint16_t count, rtgui_rect_t *rect)
  179. {
  180. struct list_view* view = RT_NULL;
  181. view = (struct list_view*) rtgui_widget_create(LIST_VIEW_TYPE);
  182. if (view != RT_NULL)
  183. {
  184. view->items = items;
  185. view->items_count = count;
  186. view->page_items = rtgui_rect_height(*rect) / (2 + rtgui_theme_get_selected_height());
  187. }
  188. return view;
  189. }
  190. void list_view_destroy(list_view_t* view)
  191. {
  192. /* destroy view */
  193. rtgui_widget_destroy(RTGUI_WIDGET(view));
  194. }