slider.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /*
  2. * File : slider.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006 - 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. * 2009-10-16 Bernard first version
  13. * 2010-09-10 Bernard fix hide issue
  14. */
  15. #include <rtgui/dc.h>
  16. #include <rtgui/rtgui_theme.h>
  17. #include <rtgui/widgets/slider.h>
  18. #define RTGUI_SLIDER_DEFAULT_WIDTH 100
  19. #define RTGUI_SLIDER_DEFAULT_HEIGHT 20
  20. #define RTGUI_SLIDER_DEFAULT_MIN 0
  21. #define RTGUI_SLIDER_DEFAULT_MAX 100
  22. static rt_bool_t rtgui_slider_onunfocus(struct rtgui_object *object, rtgui_event_t *event);
  23. static void _rtgui_slider_constructor(rtgui_slider_t *slider)
  24. {
  25. rtgui_rect_t rect = {0, 0, RTGUI_SLIDER_DEFAULT_WIDTH, RTGUI_SLIDER_DEFAULT_HEIGHT};
  26. /* init widget and set event handler */
  27. RTGUI_WIDGET(slider)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
  28. rtgui_widget_set_rect(RTGUI_WIDGET(slider), &rect);
  29. rtgui_object_set_event_handler(RTGUI_OBJECT(slider), rtgui_slider_event_handler);
  30. rtgui_widget_set_onunfocus(RTGUI_WIDGET(slider), rtgui_slider_onunfocus);
  31. /* set proper of control */
  32. slider->min = RTGUI_SLIDER_DEFAULT_MIN;
  33. slider->max = RTGUI_SLIDER_DEFAULT_MAX;
  34. slider->value = RTGUI_SLIDER_DEFAULT_MIN;
  35. slider->orient = RTGUI_HORIZONTAL;
  36. slider->ticks = 10;
  37. slider->thumb_width = 8;
  38. slider->on_changed = RT_NULL;
  39. }
  40. DEFINE_CLASS_TYPE(slider, "slider",
  41. RTGUI_WIDGET_TYPE,
  42. _rtgui_slider_constructor,
  43. RT_NULL,
  44. sizeof(struct rtgui_slider));
  45. static void rtgui_slider_onmouse(struct rtgui_slider *slider, struct rtgui_event_mouse *event)
  46. {
  47. RT_ASSERT(slider != RT_NULL);
  48. RT_ASSERT(event != RT_NULL);
  49. if (event->button & RTGUI_MOUSE_BUTTON_DOWN &&
  50. event->button & RTGUI_MOUSE_BUTTON_LEFT)
  51. {
  52. int sel;
  53. int range = slider->max - slider->min;
  54. int x0, xsize;
  55. int x;
  56. x0 = 1 + slider->thumb_width / 2;
  57. if (slider->orient == RTGUI_VERTICAL)
  58. {
  59. x = event->y - RTGUI_WIDGET(slider)->extent.y1;
  60. x -= x0;
  61. xsize = rtgui_rect_height(RTGUI_WIDGET(slider)->extent) - 2 * x0;
  62. }
  63. else
  64. {
  65. x = event->x - RTGUI_WIDGET(slider)->extent.x1;
  66. x -= x0;
  67. xsize = rtgui_rect_width(RTGUI_WIDGET(slider)->extent) - 2 * x0;
  68. }
  69. if (x <= 0)
  70. {
  71. sel = slider->min;
  72. }
  73. else if (x >= xsize)
  74. {
  75. sel = slider->max;
  76. }
  77. else
  78. {
  79. sel = ((range * x) + xsize / 2) / xsize;
  80. sel += slider->min;
  81. }
  82. rtgui_widget_focus(RTGUI_WIDGET(slider));
  83. rtgui_slider_set_value(slider, sel);
  84. if (slider->on_changed != RT_NULL) /* invoke callback function */
  85. slider->on_changed(RTGUI_WIDGET(slider), RT_NULL);
  86. }
  87. }
  88. static rt_bool_t rtgui_slider_onkey(struct rtgui_slider *slider, struct rtgui_event_kbd *event)
  89. {
  90. RT_ASSERT(slider != RT_NULL);
  91. RT_ASSERT(event != RT_NULL);
  92. if (!(RTGUI_KBD_IS_UP(event)))
  93. return RT_TRUE;
  94. if (slider->orient == RTGUI_HORIZONTAL)
  95. {
  96. if (event->key == RTGUIK_RIGHT)
  97. {
  98. if (slider->value > slider->min)
  99. slider->value++;
  100. }
  101. else if (event->key == RTGUIK_LEFT)
  102. {
  103. if (slider->value < slider->max)
  104. slider->value--;
  105. }
  106. }
  107. else
  108. {
  109. if (event->key == RTGUIK_UP)
  110. {
  111. if (slider->value > slider->min)
  112. slider->value--;
  113. }
  114. else if (event->key == RTGUIK_DOWN)
  115. {
  116. if (slider->value < slider->max)
  117. slider->value++;
  118. }
  119. }
  120. /* update widget */
  121. rtgui_widget_update(RTGUI_WIDGET(slider));
  122. if (slider->on_changed != RT_NULL) /* invoke callback function */
  123. slider->on_changed(RTGUI_WIDGET(slider), RT_NULL);
  124. return RT_TRUE;
  125. }
  126. rt_bool_t rtgui_slider_event_handler(struct rtgui_object *object, struct rtgui_event *event)
  127. {
  128. struct rtgui_widget *widget;
  129. struct rtgui_slider *slider;
  130. RT_ASSERT(object != RT_NULL);
  131. RT_ASSERT(event != RT_NULL);
  132. widget = RTGUI_WIDGET(object);
  133. slider = RTGUI_SLIDER(object);
  134. switch (event->type)
  135. {
  136. case RTGUI_EVENT_PAINT:
  137. #ifndef RTGUI_USING_SMALL_SIZE
  138. if (widget->on_draw != RT_NULL)
  139. widget->on_draw(RTGUI_OBJECT(widget), event);
  140. else
  141. #endif
  142. {
  143. rtgui_theme_draw_slider(slider);
  144. }
  145. break;
  146. case RTGUI_EVENT_KBD:
  147. if (!RTGUI_WIDGET_IS_ENABLE(widget) || RTGUI_WIDGET_IS_HIDE(widget)) return RT_FALSE;
  148. #ifndef RTGUI_USING_SMALL_SIZE
  149. if (widget->on_key != RT_NULL)
  150. return widget->on_key(RTGUI_OBJECT(widget), event);
  151. else
  152. #endif
  153. return rtgui_slider_onkey(slider, (struct rtgui_event_kbd *)event);
  154. case RTGUI_EVENT_MOUSE_BUTTON:
  155. if (!RTGUI_WIDGET_IS_ENABLE(widget) || RTGUI_WIDGET_IS_HIDE(widget)) return RT_FALSE;
  156. #ifndef RTGUI_USING_SMALL_SIZE
  157. if (widget->on_mouseclick != RT_NULL)
  158. widget->on_mouseclick(RTGUI_OBJECT(widget), event);
  159. else
  160. #endif
  161. {
  162. rtgui_slider_onmouse(slider, (struct rtgui_event_mouse *)event);
  163. }
  164. break;
  165. default:
  166. return rtgui_widget_event_handler(object, event);
  167. }
  168. return RT_FALSE;
  169. }
  170. RTM_EXPORT(rtgui_slider_event_handler);
  171. struct rtgui_slider *rtgui_slider_create(rt_size_t min, rt_size_t max, int orient)
  172. {
  173. struct rtgui_slider *slider;
  174. slider = (struct rtgui_slider *) rtgui_widget_create(RTGUI_SLIDER_TYPE);
  175. if (slider != RT_NULL)
  176. {
  177. /* set proper of control */
  178. slider->min = min;
  179. slider->max = max;
  180. slider->value = min;
  181. slider->ticks = 10;
  182. slider->thumb_width = 8;
  183. rtgui_slider_set_orientation(slider, orient);
  184. }
  185. return slider;
  186. }
  187. RTM_EXPORT(rtgui_slider_create);
  188. void rtgui_slider_set_range(struct rtgui_slider *slider, rt_size_t min, rt_size_t max)
  189. {
  190. RT_ASSERT(slider != RT_NULL);
  191. slider->max = max;
  192. slider->min = min;
  193. }
  194. RTM_EXPORT(rtgui_slider_set_range);
  195. void rtgui_slider_set_value(struct rtgui_slider *slider, rt_size_t value)
  196. {
  197. RT_ASSERT(slider != RT_NULL);
  198. if (RTGUI_WIDGET_IS_ENABLE(slider))
  199. {
  200. if (value < slider->min) value = slider->min;
  201. if (value > slider->max) value = slider->max;
  202. if (slider->value != value)
  203. {
  204. slider->value = value;
  205. rtgui_theme_draw_slider(slider);
  206. }
  207. }
  208. }
  209. RTM_EXPORT(rtgui_slider_set_value);
  210. void rtgui_slider_set_orientation(struct rtgui_slider *slider, int orientation)
  211. {
  212. RT_ASSERT(slider != RT_NULL);
  213. /* set orientation */
  214. slider->orient = orientation;
  215. #ifndef RTGUI_USING_SMALL_SIZE
  216. if (slider->orient == RTGUI_HORIZONTAL)
  217. {
  218. /* HORIZONTAL */
  219. rtgui_widget_set_minheight(RTGUI_WIDGET(slider), RTGUI_SLIDER_DEFAULT_HEIGHT);
  220. rtgui_widget_set_minwidth(RTGUI_WIDGET(slider), RTGUI_SLIDER_DEFAULT_WIDTH);
  221. }
  222. else
  223. {
  224. /* VERTICAL */
  225. rtgui_widget_set_minwidth(RTGUI_WIDGET(slider), RTGUI_SLIDER_DEFAULT_HEIGHT);
  226. rtgui_widget_set_minheight(RTGUI_WIDGET(slider), RTGUI_SLIDER_DEFAULT_WIDTH);
  227. }
  228. #endif
  229. }
  230. RTM_EXPORT(rtgui_slider_set_orientation);
  231. rt_size_t rtgui_slider_get_value(struct rtgui_slider *slider)
  232. {
  233. RT_ASSERT(slider != RT_NULL);
  234. return slider->value;
  235. }
  236. RTM_EXPORT(rtgui_slider_get_value);
  237. static rt_bool_t rtgui_slider_onunfocus(struct rtgui_object *object, rtgui_event_t *event)
  238. {
  239. rtgui_rect_t rect;
  240. rtgui_widget_t *widget;
  241. struct rtgui_dc *dc;
  242. RT_ASSERT(object);
  243. widget = RTGUI_WIDGET(object);
  244. dc = rtgui_dc_begin_drawing(widget);
  245. if (dc == RT_NULL) return RT_FALSE;
  246. rtgui_widget_get_rect(widget, &rect);
  247. if (!RTGUI_WIDGET_IS_FOCUSED(widget))
  248. {
  249. /* only clear focus rect */
  250. rtgui_color_t color = RTGUI_DC_FC(dc);
  251. RTGUI_DC_FC(dc) = RTGUI_DC_BC(dc);
  252. rtgui_dc_draw_focus_rect(dc, &rect);
  253. RTGUI_DC_FC(dc) = color;
  254. }
  255. rtgui_dc_end_drawing(dc);
  256. return RT_TRUE;
  257. }