scrollbar.c 13 KB

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