The official µGFX library repository.

gwin_checkbox.c 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /*
  2. * This file is subject to the terms of the GFX License. If a copy of
  3. * the license was not distributed with this file, you can obtain one at:
  4. *
  5. * http://ugfx.org/license.html
  6. */
  7. /**
  8. * @file src/gwin/gwin_checkbox.c
  9. * @brief GWIN sub-system button code
  10. */
  11. #include "../../gfx.h"
  12. #if (GFX_USE_GWIN && GWIN_NEED_CHECKBOX) || defined(__DOXYGEN__)
  13. #include "gwin_class.h"
  14. // Parameters for button custom draw
  15. #define CHK_TOP_FADE 50 // (CHK_TOP_FADE/255)% fade to white for top of button
  16. #define CHK_BOTTOM_FADE 25 // (CHK_BOTTOM_FADE/255)% fade to black for bottom of button
  17. // Send the checkbox event
  18. static void SendCheckboxEvent(GWidgetObject *gw) {
  19. GSourceListener * psl;
  20. GEvent * pe;
  21. #define pce ((GEventGWinCheckbox *)pe)
  22. // Trigger a GWIN Checkbox Event
  23. psl = 0;
  24. while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
  25. if (!(pe = geventGetEventBuffer(psl)))
  26. continue;
  27. pce->type = GEVENT_GWIN_CHECKBOX;
  28. pce->gwin = &gw->g;
  29. pce->isChecked = (gw->g.flags & GCHECKBOX_FLG_CHECKED) ? TRUE : FALSE;
  30. #if GWIN_WIDGET_TAGS
  31. pce->tag = gw->tag;
  32. #endif
  33. geventSendEvent(psl);
  34. }
  35. #undef pce
  36. }
  37. #if GINPUT_NEED_MOUSE
  38. static void CheckboxMouseDown(GWidgetObject *gw, coord_t x, coord_t y) {
  39. (void) x; (void) y;
  40. gw->g.flags ^= GCHECKBOX_FLG_CHECKED;
  41. _gwinUpdate((GHandle)gw);
  42. SendCheckboxEvent(gw);
  43. }
  44. #endif
  45. #if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
  46. static void CheckboxKeyboard(GWidgetObject* gw, GEventKeyboard* pke)
  47. {
  48. // Only react on KEYDOWN events. Ignore KEYUP events.
  49. if ((pke->keystate & GKEYSTATE_KEYUP))
  50. return;
  51. // ENTER and SPACE keys to check/uncheck the checkbox
  52. if (pke->c[0] == GKEY_ENTER || pke->c[0] == GKEY_SPACE) {
  53. gw->g.flags ^= GCHECKBOX_FLG_CHECKED;
  54. _gwinUpdate((GHandle)gw);
  55. SendCheckboxEvent(gw);
  56. }
  57. }
  58. #endif
  59. #if GINPUT_NEED_TOGGLE
  60. static void CheckboxToggleOn(GWidgetObject *gw, uint16_t role) {
  61. (void) role;
  62. gw->g.flags ^= GCHECKBOX_FLG_CHECKED;
  63. _gwinUpdate((GHandle)gw);
  64. SendCheckboxEvent(gw);
  65. }
  66. static void CheckboxToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
  67. (void) role;
  68. ((GCheckboxObject *)gw)->toggle = instance;
  69. }
  70. static uint16_t CheckboxToggleGet(GWidgetObject *gw, uint16_t role) {
  71. (void) role;
  72. return ((GCheckboxObject *)gw)->toggle;
  73. }
  74. #endif
  75. // The checkbox VMT table
  76. static const gwidgetVMT checkboxVMT = {
  77. {
  78. "Checkbox", // The classname
  79. sizeof(GCheckboxObject),// The object size
  80. _gwidgetDestroy, // The destroy routine
  81. _gwidgetRedraw, // The redraw routine
  82. 0, // The after-clear routine
  83. },
  84. gwinCheckboxDraw_CheckOnLeft, // The default drawing routine
  85. #if GINPUT_NEED_MOUSE
  86. {
  87. CheckboxMouseDown, // Process mouse down events
  88. 0, // Process mouse up events (NOT USED)
  89. 0, // Process mouse move events (NOT USED)
  90. },
  91. #endif
  92. #if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
  93. {
  94. CheckboxKeyboard // Process keyboard events
  95. },
  96. #endif
  97. #if GINPUT_NEED_TOGGLE
  98. {
  99. 1, // 1 toggle role
  100. CheckboxToggleAssign, // Assign Toggles
  101. CheckboxToggleGet, // Get Toggles
  102. 0, // Process toggle off events (NOT USED)
  103. CheckboxToggleOn, // Process toggle on events
  104. },
  105. #endif
  106. #if GINPUT_NEED_DIAL
  107. {
  108. 0, // No dial roles
  109. 0, // Assign Dials (NOT USED)
  110. 0, // Get Dials (NOT USED)
  111. 0, // Process dial move events (NOT USED)
  112. },
  113. #endif
  114. };
  115. GHandle gwinGCheckboxCreate(GDisplay *g, GCheckboxObject *gb, const GWidgetInit *pInit) {
  116. if (!(gb = (GCheckboxObject *)_gwidgetCreate(g, &gb->w, pInit, &checkboxVMT)))
  117. return 0;
  118. #if GINPUT_NEED_TOGGLE
  119. gb->toggle = GWIDGET_NO_INSTANCE;
  120. #endif
  121. gwinSetVisible((GHandle)gb, pInit->g.show);
  122. return (GHandle)gb;
  123. }
  124. void gwinCheckboxCheck(GHandle gh, bool_t isChecked) {
  125. if (gh->vmt != (gwinVMT *)&checkboxVMT)
  126. return;
  127. if (isChecked) {
  128. if ((gh->flags & GCHECKBOX_FLG_CHECKED)) return;
  129. gh->flags |= GCHECKBOX_FLG_CHECKED;
  130. } else {
  131. if (!(gh->flags & GCHECKBOX_FLG_CHECKED)) return;
  132. gh->flags &= ~GCHECKBOX_FLG_CHECKED;
  133. }
  134. _gwinUpdate(gh);
  135. SendCheckboxEvent((GWidgetObject *)gh);
  136. }
  137. bool_t gwinCheckboxIsChecked(GHandle gh) {
  138. if (gh->vmt != (gwinVMT *)&checkboxVMT)
  139. return FALSE;
  140. return (gh->flags & GCHECKBOX_FLG_CHECKED) ? TRUE : FALSE;
  141. }
  142. /*----------------------------------------------------------
  143. * Custom Draw Routines
  144. *----------------------------------------------------------*/
  145. static const GColorSet *getCheckboxColors(GWidgetObject *gw) {
  146. if (!(gw->g.flags & GWIN_FLG_SYSENABLED)) return &gw->pstyle->disabled;
  147. if ((gw->g.flags & GCHECKBOX_FLG_CHECKED)) return &gw->pstyle->pressed;
  148. return &gw->pstyle->enabled;
  149. }
  150. void gwinCheckboxDraw_CheckOnLeft(GWidgetObject *gw, void *param) {
  151. #define gcw ((GCheckboxObject *)gw)
  152. coord_t ld, df;
  153. const GColorSet * pcol;
  154. (void) param;
  155. if (gw->g.vmt != (gwinVMT *)&checkboxVMT) return;
  156. pcol = getCheckboxColors(gw);
  157. // Get the dimension of the check box (sans text)
  158. ld = gw->g.width < gw->g.height ? gw->g.width : gw->g.height;
  159. // Draw the empty check box
  160. gdispGFillArea(gw->g.display, gw->g.x+1, gw->g.y+1, ld, ld-2, gw->pstyle->background);
  161. gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, ld, ld, pcol->edge);
  162. // Draw the check
  163. df = ld < 4 ? 1 : 2;
  164. if (gw->g.flags & GCHECKBOX_FLG_CHECKED)
  165. gdispGFillArea(gw->g.display, gw->g.x+df, gw->g.y+df, ld-2*df, ld-2*df, pcol->fill);
  166. // Render highlighted border if focused
  167. _gwidgetDrawFocusRect(gw, 1, 1, ld-2, ld-2);
  168. // Draw the text
  169. gdispGFillStringBox(gw->g.display, gw->g.x+ld+1, gw->g.y, gw->g.width-ld-1, gw->g.height, gw->text, gw->g.font, pcol->text, gw->pstyle->background, justifyLeft);
  170. #undef gcw
  171. }
  172. void gwinCheckboxDraw_CheckOnRight(GWidgetObject *gw, void *param) {
  173. #define gcw ((GCheckboxObject *)gw)
  174. coord_t ep, ld, df;
  175. const GColorSet * pcol;
  176. (void) param;
  177. if (gw->g.vmt != (gwinVMT *)&checkboxVMT) return;
  178. pcol = getCheckboxColors(gw);
  179. // Get the dimension of the check box (sans text)
  180. ld = gw->g.width < gw->g.height ? gw->g.width : gw->g.height;
  181. // Get the position of the check box
  182. ep = gw->g.width-ld;
  183. // Draw the empty check box
  184. gdispGFillArea(gw->g.display, gw->g.x+ep-1, gw->g.y+1, ld, ld-2, gw->pstyle->background);
  185. gdispGDrawBox(gw->g.display, gw->g.x+ep, gw->g.y, ld, ld, pcol->edge);
  186. // Draw the check
  187. df = ld < 4 ? 1 : 2;
  188. if (gw->g.flags & GCHECKBOX_FLG_CHECKED)
  189. gdispGFillArea(gw->g.display, gw->g.x+ep+df, gw->g.y+df, ld-2*df, ld-2*df, pcol->fill);
  190. // Render highlighted border if focused
  191. _gwidgetDrawFocusRect(gw, ep+1, 1, ld-2, ld-2);
  192. // Draw the text
  193. gdispGFillStringBox(gw->g.display, gw->g.x, gw->g.y, ep-1, gw->g.height, gw->text, gw->g.font, pcol->text, gw->pstyle->background, justifyRight);
  194. #undef gcw
  195. }
  196. #if GWIN_FLAT_STYLING
  197. void gwinCheckboxDraw_Button(GWidgetObject *gw, void *param) {
  198. const GColorSet * pcol;
  199. (void) param;
  200. if (gw->g.vmt != (gwinVMT *)&checkboxVMT) return;
  201. pcol = getCheckboxColors(gw);
  202. #if GWIN_NEED_FLASHING
  203. // Flash the on and off state.
  204. pcol = _gwinGetFlashedColor(gw, pcol, TRUE);
  205. #endif
  206. gdispGFillStringBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width-1, gw->g.height-1, gw->text, gw->g.font, pcol->text, pcol->fill, justifyCenter);
  207. gdispGDrawLine(gw->g.display, gw->g.x+gw->g.width-1, gw->g.y, gw->g.x+gw->g.width-1, gw->g.y+gw->g.height-1, pcol->edge);
  208. gdispGDrawLine(gw->g.display, gw->g.x, gw->g.y+gw->g.height-1, gw->g.x+gw->g.width-2, gw->g.y+gw->g.height-1, pcol->edge);
  209. }
  210. #else
  211. void gwinCheckboxDraw_Button(GWidgetObject *gw, void *param) {
  212. const GColorSet * pcol;
  213. fixed alpha;
  214. fixed dalpha;
  215. coord_t i;
  216. color_t tcol, bcol;
  217. (void) param;
  218. if (gw->g.vmt != (gwinVMT *)&checkboxVMT) return;
  219. pcol = getCheckboxColors(gw);
  220. #if GWIN_NEED_FLASHING
  221. // Flash the on and off state.
  222. pcol = _gwinGetFlashedColor(gw, pcol, TRUE);
  223. #endif
  224. /* Fill the box blended from variants of the fill color */
  225. tcol = gdispBlendColor(White, pcol->fill, CHK_TOP_FADE);
  226. bcol = gdispBlendColor(Black, pcol->fill, CHK_BOTTOM_FADE);
  227. dalpha = FIXED(255)/gw->g.height;
  228. for(alpha = 0, i = 0; i < gw->g.height; i++, alpha += dalpha)
  229. gdispGDrawLine(gw->g.display, gw->g.x, gw->g.y+i, gw->g.x+gw->g.width-2, gw->g.y+i, gdispBlendColor(bcol, tcol, NONFIXED(alpha)));
  230. gdispGDrawStringBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width-1, gw->g.height-1, gw->text, gw->g.font, pcol->text, justifyCenter);
  231. gdispGDrawLine(gw->g.display, gw->g.x+gw->g.width-1, gw->g.y, gw->g.x+gw->g.width-1, gw->g.y+gw->g.height-1, pcol->edge);
  232. gdispGDrawLine(gw->g.display, gw->g.x, gw->g.y+gw->g.height-1, gw->g.x+gw->g.width-2, gw->g.y+gw->g.height-1, pcol->edge);
  233. }
  234. #endif
  235. #endif /* (GFX_USE_GWIN && GWIN_NEED_CHECKBOX) */