scrollbar.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. /*
  2. * File : scrollbar.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006 - 2009, 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-08-09 Bernard first version
  13. */
  14. #include <rtgui/dc.h>
  15. #include <rtgui/widgets/scrollbar.h>
  16. static void _rtgui_scrollbar_constructor(rtgui_scrollbar_t *bar)
  17. {
  18. struct rtgui_rect rect = {0, 0, RTGUI_DEFAULT_SB_WIDTH, RTGUI_DEFAULT_SB_HEIGHT};
  19. /* set event handler */
  20. rtgui_widget_set_event_handler(RTGUI_WIDGET(bar), rtgui_scrollbar_event_handler);
  21. rtgui_scrollbar_set_range(bar, 0, 100);
  22. rtgui_scrollbar_set_page_step(bar, 20);
  23. rtgui_scrollbar_set_line_step(bar, 10);
  24. bar->status = 0;
  25. bar->thumb_position = 0;
  26. bar->thumb_size = 16;
  27. bar->on_scroll = RT_NULL;
  28. bar->orient = RTGUI_HORIZONTAL;
  29. rtgui_widget_set_rect(RTGUI_WIDGET(bar), &rect);
  30. /* set gc */
  31. RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(bar)) = RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL;
  32. }
  33. rt_inline rt_uint32_t _rtgui_scrollbar_get_length(rtgui_scrollbar_t *bar)
  34. {
  35. struct rtgui_rect rect;
  36. rtgui_widget_get_rect(RTGUI_WIDGET(bar), &rect);
  37. if (bar->orient & RTGUI_VERTICAL)
  38. return rect.y2 - 2 * (rect.x2 - rect.x1);
  39. return rect.x2 - 2 * (rect.y2 - rect.y1);
  40. }
  41. rt_inline rt_uint32_t _rtgui_scrollbar_get_thumb_position(rtgui_scrollbar_t* bar)
  42. {
  43. rt_uint32_t thumb_position;
  44. /* calculate thumb position */
  45. thumb_position = (rtgui_scrollbar_get_value(bar) - bar->min_position) * _rtgui_scrollbar_get_length(bar) /
  46. (bar->max_position - bar->min_position);
  47. return thumb_position;
  48. }
  49. void rtgui_scrollbar_get_thumb_rect(rtgui_scrollbar_t *bar, rtgui_rect_t *rect)
  50. {
  51. struct rtgui_rect scrollbar_rect;
  52. rtgui_widget_get_rect(RTGUI_WIDGET(bar), &scrollbar_rect);
  53. if (bar->orient & RTGUI_VERTICAL)
  54. {
  55. rt_uint32_t btn_width = scrollbar_rect.x2 - scrollbar_rect.x1;
  56. /* vertical scroll bar */
  57. rect->x1 = scrollbar_rect.x1;
  58. rect->x2 = scrollbar_rect.x2;
  59. rect->y1 = scrollbar_rect.y1 + btn_width + _rtgui_scrollbar_get_thumb_position(bar);
  60. rect->y2 = rect->y1 + btn_width;
  61. }
  62. else
  63. {
  64. rt_uint32_t btn_height = scrollbar_rect.y2 - scrollbar_rect.y1;
  65. /* horizontal scroll bar */
  66. rect->x1 = scrollbar_rect.x1 + btn_height + _rtgui_scrollbar_get_thumb_position(bar);
  67. rect->x2 = rect->x1 + btn_height;
  68. rect->y1 = scrollbar_rect.y1;
  69. rect->y2 = scrollbar_rect.y2;
  70. }
  71. }
  72. rtgui_type_t *rtgui_scrollbar_type_get(void)
  73. {
  74. static rtgui_type_t *scrollbar_type = RT_NULL;
  75. if (!scrollbar_type)
  76. {
  77. scrollbar_type = rtgui_type_create("scrollbar", RTGUI_WIDGET_TYPE,
  78. sizeof(rtgui_scrollbar_t), RTGUI_CONSTRUCTOR(_rtgui_scrollbar_constructor), RT_NULL);
  79. }
  80. return scrollbar_type;
  81. }
  82. static void _rtgui_scrollbar_on_mouseclick(struct rtgui_widget * widget, struct rtgui_event * event)
  83. {
  84. rtgui_rect_t rect, btn_rect, bar_rect;
  85. rt_uint32_t thumb_size, thumb_position;
  86. struct rtgui_scrollbar* bar = (struct rtgui_scrollbar*)widget;
  87. struct rtgui_event_mouse* mouse = (struct rtgui_event_mouse*)event;
  88. /* get the thumb size and position */
  89. thumb_size = bar->thumb_size * (bar->max_position - bar->min_position) / _rtgui_scrollbar_get_length(bar);
  90. thumb_position = _rtgui_scrollbar_get_thumb_position(bar);
  91. if (bar->orient == RTGUI_VERTICAL)
  92. {
  93. /* get up arrow button rect */
  94. btn_rect.x1 = widget->extent.x1;
  95. btn_rect.x2 = widget->extent.x2;
  96. btn_rect.y1 = widget->extent.y1;
  97. btn_rect.y2 = widget->extent.y1 + (widget->extent.x2 - widget->extent.x1);
  98. if (rtgui_rect_contains_point(&btn_rect, mouse->x, mouse->y) == RT_EOK)
  99. {
  100. if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) ==
  101. (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN))
  102. {
  103. bar->status |= SBS_UPARROW;
  104. /* line step */
  105. bar->thumb_position -= bar->line_step;
  106. if (bar->thumb_position < bar->min_position) bar->thumb_position = bar->min_position;
  107. }
  108. else if (mouse->button & RTGUI_MOUSE_BUTTON_UP)
  109. {
  110. bar->status = 0;
  111. }
  112. goto __exit;
  113. }
  114. /* get bar rect */
  115. bar_rect.x1 = widget->extent.x1;
  116. bar_rect.x2 = widget->extent.x2;
  117. bar_rect.y1 = widget->extent.y1 + (widget->extent.x2 - widget->extent.x1);
  118. bar_rect.y2 = widget->extent.y2 - (widget->extent.x2 - widget->extent.x1);
  119. if (rtgui_rect_contains_point(&bar_rect, mouse->x, mouse->y) == RT_EOK)
  120. {
  121. if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) ==
  122. (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN))
  123. {
  124. /* page step */
  125. if (mouse->y < bar_rect.y1 + thumb_position)
  126. {
  127. bar->thumb_position -= bar->page_step;
  128. if (bar->thumb_position < bar->min_position)
  129. bar->thumb_position = bar->min_position;
  130. }
  131. else if (mouse->y > thumb_position + bar->thumb_size)
  132. {
  133. bar->thumb_position += bar->page_step;
  134. if (bar->thumb_position > bar->max_position - thumb_size)
  135. bar->thumb_position = bar->max_position - thumb_size;
  136. }
  137. }
  138. goto __exit;
  139. }
  140. /* get down arrow button rect */
  141. btn_rect.y1 = widget->extent.y2 - (widget->extent.x2 - widget->extent.x1);
  142. btn_rect.y2 = widget->extent.y2;
  143. bar_rect.y1 = widget->extent.y1 + ((widget->extent.y2 - widget->extent.y1)/2);
  144. bar_rect.y2 = widget->extent.y2 - (widget->extent.x2 - widget->extent.x1);
  145. if (rtgui_rect_contains_point(&btn_rect, mouse->x, mouse->y) == RT_EOK)
  146. {
  147. if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) ==
  148. (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN))
  149. {
  150. bar->status |= SBS_DOWNARROW;
  151. /* line step */
  152. bar->thumb_position += bar->line_step;
  153. if (bar->thumb_position > bar->max_position - thumb_size)
  154. bar->thumb_position = bar->max_position - thumb_size;
  155. }
  156. else if (mouse->button & RTGUI_MOUSE_BUTTON_UP)
  157. bar->status = 0;
  158. }
  159. }
  160. else
  161. {
  162. /* get left arrow button rect */
  163. btn_rect.x1 = widget->extent.x1;
  164. btn_rect.x2 = widget->extent.x1 + (widget->extent.y2 - widget->extent.y1);
  165. btn_rect.y1 = widget->extent.y1;
  166. btn_rect.y2 = widget->extent.y2;
  167. if (rtgui_rect_contains_point(&btn_rect, mouse->x, mouse->y) == RT_EOK)
  168. {
  169. if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) ==
  170. (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN))
  171. {
  172. bar->status |= SBS_LEFTARROW;
  173. /* line step */
  174. bar->thumb_position -= bar->line_step;
  175. if (bar->thumb_position < bar->min_position) bar->thumb_position = bar->min_position;
  176. }
  177. else if (mouse->button & RTGUI_MOUSE_BUTTON_UP)
  178. bar->status = 0;
  179. goto __exit;
  180. }
  181. /* get bar rect */
  182. bar_rect.x1 = widget->extent.x1 + (widget->extent.y2 - widget->extent.y1);
  183. bar_rect.x2 = widget->extent.x2 - (widget->extent.y2 - widget->extent.y1);
  184. bar_rect.y1 = widget->extent.y1;
  185. bar_rect.y2 = widget->extent.y2;
  186. if (rtgui_rect_contains_point(&bar_rect, mouse->x, mouse->y) == RT_EOK)
  187. {
  188. if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) ==
  189. (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN))
  190. {
  191. /* page step */
  192. if (mouse->x < bar_rect.x1 + thumb_position)
  193. {
  194. bar->thumb_position -= bar->page_step;
  195. if (bar->thumb_position < bar->min_position)
  196. bar->thumb_position = bar->min_position;
  197. }
  198. else if (mouse->x > thumb_position + bar->thumb_size)
  199. {
  200. bar->thumb_position += bar->page_step;
  201. if (bar->thumb_position > bar->max_position - thumb_size)
  202. bar->thumb_position = bar->max_position - thumb_size;
  203. }
  204. }
  205. goto __exit;
  206. }
  207. /* get right arrow button rect */
  208. btn_rect.x1 = widget->extent.x2 - (widget->extent.y2 - widget->extent.y1);
  209. btn_rect.x2 = widget->extent.x2;
  210. bar_rect.x1 = widget->extent.x1 + ((widget->extent.x2 - widget->extent.x1)/2);
  211. bar_rect.x2 = widget->extent.x2 - (widget->extent.y2 - widget->extent.y1);
  212. if (rtgui_rect_contains_point(&btn_rect,
  213. mouse->x, mouse->y) == RT_EOK)
  214. {
  215. if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) ==
  216. (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN))
  217. {
  218. bar->status |= SBS_RIGHTARROW;
  219. /* line step */
  220. bar->thumb_position += bar->line_step;
  221. if (bar->thumb_position > bar->max_position - bar->line_step)
  222. bar->thumb_position = bar->max_position - bar->line_step;
  223. }
  224. else if (mouse->button & RTGUI_MOUSE_BUTTON_UP)
  225. bar->status = 0;
  226. }
  227. }
  228. __exit:
  229. rtgui_theme_draw_scrollbar(bar);
  230. if ((mouse->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN)) ==
  231. (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_DOWN))
  232. {
  233. if (bar->on_scroll != RT_NULL) bar->on_scroll(widget, RT_NULL);
  234. }
  235. }
  236. rt_bool_t rtgui_scrollbar_event_handler(struct rtgui_widget * widget,
  237. struct rtgui_event * event)
  238. {
  239. struct rtgui_scrollbar* bar = (struct rtgui_scrollbar*)widget;
  240. switch (event->type)
  241. {
  242. case RTGUI_EVENT_PAINT:
  243. #ifndef RTGUI_USING_SMALL_SIZE
  244. if (widget->on_draw != RT_NULL) widget->on_draw(widget, event);
  245. else
  246. #endif
  247. {
  248. rtgui_theme_draw_scrollbar(bar);
  249. }
  250. break;
  251. case RTGUI_EVENT_MOUSE_BUTTON:
  252. if (RTGUI_WIDGET_IS_ENABLE(widget) && !RTGUI_WIDGET_IS_HIDE(widget))
  253. {
  254. #ifndef RTGUI_USING_SMALL_SIZE
  255. if (widget->on_mouseclick != RT_NULL)
  256. {
  257. widget->on_mouseclick(widget, event);
  258. }
  259. else
  260. #endif
  261. {
  262. _rtgui_scrollbar_on_mouseclick(widget, event);
  263. }
  264. }
  265. break;
  266. default:
  267. break;
  268. }
  269. return RT_FALSE;
  270. }
  271. struct rtgui_scrollbar* rtgui_scrollbar_create(int orient, rtgui_rect_t* r)
  272. {
  273. struct rtgui_scrollbar* bar;
  274. bar = (struct rtgui_scrollbar*) rtgui_widget_create (RTGUI_SCROLLBAR_TYPE);
  275. if (bar != RT_NULL)
  276. {
  277. if (r != RT_NULL)
  278. {
  279. rtgui_widget_set_rect(RTGUI_WIDGET(bar), r);
  280. if (orient == RTGUI_VERTICAL)
  281. bar->thumb_size = (r->x2 - r->x1);
  282. else
  283. bar->thumb_size = (r->y2 - r->y1);
  284. }
  285. bar->orient = orient;
  286. }
  287. return bar;
  288. }
  289. void rtgui_scrollbar_destroy(struct rtgui_scrollbar* bar)
  290. {
  291. rtgui_widget_destroy(RTGUI_WIDGET(bar));
  292. }
  293. void rtgui_scrollbar_set_orientation(rtgui_scrollbar_t* bar, int orientation)
  294. {
  295. RT_ASSERT(bar != RT_NULL);
  296. bar->orient = orientation;
  297. #ifndef RTGUI_USING_SMALL_SIZE
  298. if (bar->orient == RTGUI_HORIZONTAL)
  299. {
  300. /* horizontal */
  301. rtgui_widget_set_miniwidth(RTGUI_WIDGET(bar), RTGUI_DEFAULT_SB_WIDTH);
  302. rtgui_widget_set_miniheight(RTGUI_WIDGET(bar), RTGUI_DEFAULT_SB_HEIGHT);
  303. }
  304. else
  305. {
  306. /* vertical */
  307. rtgui_widget_set_miniwidth(RTGUI_WIDGET(bar), RTGUI_DEFAULT_SB_HEIGHT);
  308. rtgui_widget_set_miniheight(RTGUI_WIDGET(bar), RTGUI_DEFAULT_SB_WIDTH);
  309. }
  310. #endif
  311. }
  312. void rtgui_scrollbar_set_range(struct rtgui_scrollbar* bar, int min, int max)
  313. {
  314. RT_ASSERT(bar != RT_NULL);
  315. if (min >= max )
  316. {
  317. RTGUI_WIDGET_DISABLE(RTGUI_WIDGET(bar));
  318. return;
  319. }
  320. bar->min_position = (rt_int16_t)min;
  321. bar->max_position = (rt_int16_t)max;
  322. }
  323. void rtgui_scrollbar_set_page_step(struct rtgui_scrollbar* bar, int step)
  324. {
  325. RT_ASSERT(bar != RT_NULL);
  326. bar->page_step = step;
  327. /* disable or enable scrollbar */
  328. if (bar->page_step > (bar->max_position - bar->min_position))
  329. {
  330. /* disable bar */
  331. RTGUI_WIDGET_DISABLE(RTGUI_WIDGET(bar));
  332. }
  333. else
  334. {
  335. /* enable bar */
  336. RTGUI_WIDGET_ENABLE(RTGUI_WIDGET(bar));
  337. }
  338. }
  339. void rtgui_scrollbar_set_line_step(struct rtgui_scrollbar* bar, int step)
  340. {
  341. RT_ASSERT(bar != RT_NULL);
  342. bar->line_step = step;
  343. }
  344. rt_int16_t rtgui_scrollbar_get_value(struct rtgui_scrollbar* bar)
  345. {
  346. RT_ASSERT(bar != RT_NULL);
  347. return bar->thumb_position;
  348. }
  349. void rtgui_scrollbar_set_value(struct rtgui_scrollbar* bar, rt_int16_t position)
  350. {
  351. RT_ASSERT(bar != RT_NULL);
  352. bar->thumb_position = position;
  353. rtgui_widget_update(RTGUI_WIDGET(bar));
  354. }
  355. void rtgui_scrollbar_set_onscroll(struct rtgui_scrollbar* bar,
  356. rtgui_event_handler_ptr handler)
  357. {
  358. if (bar == RT_NULL || handler == RT_NULL) return;
  359. bar->on_scroll = handler;
  360. }