The official µGFX library repository.

gwin_radio.c 9.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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_radio.c
  9. * @brief GWIN sub-system radio button code
  10. */
  11. #include "../../gfx.h"
  12. #if GFX_USE_GWIN && GWIN_NEED_RADIO
  13. #include "gwin_class.h"
  14. #define GRADIO_TAB_CNR 8 // Diagonal corner on active tab
  15. #define GRADIO_TOP_FADE 50 // (GRADIO_TOP_FADE/255)% fade to white for top of tab/button
  16. #define GRADIO_BOTTOM_FADE 25 // (GRADIO_BOTTOM_FADE/255)% fade to black for bottom of tab/button
  17. #define GRADIO_OUTLINE_FADE 128 // (GRADIO_OUTLINE_FADE/255)% fade to background for active tab edge
  18. // Send the button event
  19. static void SendRadioEvent(GWidgetObject *gw) {
  20. GSourceListener * psl;
  21. GEvent * pe;
  22. #define pbe ((GEventGWinRadio *)pe)
  23. // Trigger a GWIN Button Event
  24. psl = 0;
  25. while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
  26. if (!(pe = geventGetEventBuffer(psl)))
  27. continue;
  28. pbe->type = GEVENT_GWIN_RADIO;
  29. pbe->gwin = (GHandle)gw;
  30. pbe->group = ((GRadioObject *)gw)->group;
  31. #if GWIN_WIDGET_TAGS
  32. pbe->tag = gw->tag;
  33. #endif
  34. geventSendEvent(psl);
  35. }
  36. #undef pbe
  37. }
  38. #if GINPUT_NEED_MOUSE
  39. // A mouse down has occurred over the button
  40. static void RadioMouseDown(GWidgetObject *gw, coord_t x, coord_t y) {
  41. (void) x; (void) y;
  42. gwinRadioPress((GHandle)gw);
  43. }
  44. #endif
  45. #if GINPUT_NEED_TOGGLE
  46. // A toggle on has occurred
  47. static void RadioToggleOn(GWidgetObject *gw, uint16_t role) {
  48. (void) role;
  49. gwinRadioPress((GHandle)gw);
  50. }
  51. static void RadioToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
  52. (void) role;
  53. ((GRadioObject *)gw)->toggle = instance;
  54. }
  55. static uint16_t RadioToggleGet(GWidgetObject *gw, uint16_t role) {
  56. (void) role;
  57. return ((GRadioObject *)gw)->toggle;
  58. }
  59. #endif
  60. // The radio button VMT table
  61. static const gwidgetVMT radioVMT = {
  62. {
  63. "Radio", // The classname
  64. sizeof(GRadioObject), // The object size
  65. _gwidgetDestroy, // The destroy routine
  66. _gwidgetRedraw, // The redraw routine
  67. 0, // The after-clear routine
  68. },
  69. gwinRadioDraw_Radio, // The default drawing routine
  70. #if GINPUT_NEED_MOUSE
  71. {
  72. RadioMouseDown, // Process mouse down events
  73. 0, // Process mouse up events (NOT USED)
  74. 0, // Process mouse move events (NOT USED)
  75. },
  76. #endif
  77. #if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
  78. {
  79. 0 // Process keyboard events
  80. },
  81. #endif
  82. #if GINPUT_NEED_TOGGLE
  83. {
  84. 1, // 1 toggle role
  85. RadioToggleAssign, // Assign Toggles
  86. RadioToggleGet, // Get Toggles
  87. 0, // Process toggle off events (NOT USED)
  88. RadioToggleOn, // Process toggle on events
  89. },
  90. #endif
  91. #if GINPUT_NEED_DIAL
  92. {
  93. 0, // No dial roles
  94. 0, // Assign Dials (NOT USED)
  95. 0, // Get Dials (NOT USED)
  96. 0, // Process dial move events (NOT USED)
  97. },
  98. #endif
  99. };
  100. GHandle gwinGRadioCreate(GDisplay *g, GRadioObject *gw, const GWidgetInit *pInit, uint16_t group) {
  101. if (!(gw = (GRadioObject *)_gwidgetCreate(g, &gw->w, pInit, &radioVMT)))
  102. return 0;
  103. #if GINPUT_NEED_TOGGLE
  104. gw->toggle = GWIDGET_NO_INSTANCE;
  105. #endif
  106. gw->group = group;
  107. gwinSetVisible((GHandle)gw, pInit->g.show);
  108. return (GHandle)gw;
  109. }
  110. void gwinRadioPress(GHandle gh) {
  111. GHandle gx;
  112. if (gh->vmt != (gwinVMT *)&radioVMT || (gh->flags & GRADIO_FLG_PRESSED))
  113. return;
  114. if ((gx = gwinRadioGetActive(((GRadioObject *)gh)->group))) {
  115. gx->flags &= ~GRADIO_FLG_PRESSED;
  116. _gwinUpdate(gx);
  117. }
  118. gh->flags |= GRADIO_FLG_PRESSED;
  119. _gwinUpdate(gh);
  120. SendRadioEvent((GWidgetObject *)gh);
  121. }
  122. bool_t gwinRadioIsPressed(GHandle gh) {
  123. if (gh->vmt != (gwinVMT *)&radioVMT)
  124. return FALSE;
  125. return (gh->flags & GRADIO_FLG_PRESSED) ? TRUE : FALSE;
  126. }
  127. GHandle gwinRadioGetActive(uint16_t group) {
  128. GHandle gh;
  129. for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
  130. if (gh->vmt == (gwinVMT *)&radioVMT && ((GRadioObject *)gh)->group == group && (gh->flags & GRADIO_FLG_PRESSED))
  131. return gh;
  132. }
  133. return 0;
  134. }
  135. /*----------------------------------------------------------
  136. * Custom Draw Routines
  137. *----------------------------------------------------------*/
  138. static const GColorSet *getDrawColors(GWidgetObject *gw) {
  139. if (!(gw->g.flags & GWIN_FLG_SYSENABLED)) return &gw->pstyle->disabled;
  140. if ((gw->g.flags & GRADIO_FLG_PRESSED)) return &gw->pstyle->pressed;
  141. return &gw->pstyle->enabled;
  142. }
  143. void gwinRadioDraw_Radio(GWidgetObject *gw, void *param) {
  144. #define gcw ((GRadioObject *)gw)
  145. coord_t ld, df;
  146. const GColorSet * pcol;
  147. (void) param;
  148. if (gw->g.vmt != (gwinVMT *)&radioVMT) return;
  149. pcol = getDrawColors(gw);
  150. ld = gw->g.width < gw->g.height ? gw->g.width : gw->g.height;
  151. #if GDISP_NEED_CIRCLE
  152. df = (ld-1)/2;
  153. gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, ld, ld, gw->pstyle->background);
  154. gdispGDrawCircle(gw->g.display, gw->g.x+df, gw->g.y+df, df, pcol->edge);
  155. if (gw->g.flags & GRADIO_FLG_PRESSED)
  156. gdispGFillCircle(gw->g.display, gw->g.x+df, gw->g.y+df, df <= 2 ? 1 : (df-2), pcol->fill);
  157. #else
  158. gdispGFillArea(gw->g.display, gw->g.x+1, gw->g.y+1, ld, ld-2, gw->pstyle->background);
  159. gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, ld, ld, pcol->edge);
  160. df = ld < 4 ? 1 : 2;
  161. if (gw->g.flags & GRADIO_FLG_PRESSED)
  162. gdispGFillArea(gw->g.display, gw->g.x+df, gw->g.y+df, ld-2*df, ld-2*df, pcol->fill);
  163. #endif
  164. 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);
  165. #undef gcw
  166. }
  167. #if GWIN_FLAT_STYLING
  168. void gwinRadioDraw_Button(GWidgetObject *gw, void *param) {
  169. const GColorSet * pcol;
  170. (void) param;
  171. if (gw->g.vmt != (gwinVMT *)&radioVMT) return;
  172. pcol = getDrawColors(gw);
  173. #if GWIN_NEED_FLASHING
  174. // Flash only the on state.
  175. pcol = _gwinGetFlashedColor(gw, pcol, FALSE);
  176. #endif
  177. 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);
  178. 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);
  179. 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);
  180. }
  181. void gwinRadioDraw_Tab(GWidgetObject *gw, void *param) {
  182. const GColorSet * pcol;
  183. (void) param;
  184. if (gw->g.vmt != (gwinVMT *)&radioVMT) return;
  185. pcol = getDrawColors(gw);
  186. #if GWIN_NEED_FLASHING
  187. // Flash only the on state.
  188. pcol = _gwinGetFlashedColor(gw, pcol, FALSE);
  189. #endif
  190. if ((gw->g.flags & GRADIO_FLG_PRESSED)) {
  191. gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge);
  192. gdispGFillStringBox(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-1, gw->text, gw->g.font, pcol->text, pcol->fill, justifyCenter);
  193. } else {
  194. 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);
  195. 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);
  196. 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);
  197. }
  198. }
  199. #else
  200. void gwinRadioDraw_Button(GWidgetObject *gw, void *param) {
  201. const GColorSet * pcol;
  202. fixed alpha;
  203. fixed dalpha;
  204. coord_t i;
  205. color_t tcol, bcol;
  206. (void) param;
  207. if (gw->g.vmt != (gwinVMT *)&radioVMT) return;
  208. pcol = getDrawColors(gw);
  209. /* Fill the box blended from variants of the fill color */
  210. tcol = gdispBlendColor(White, pcol->fill, GRADIO_TOP_FADE);
  211. bcol = gdispBlendColor(Black, pcol->fill, GRADIO_BOTTOM_FADE);
  212. dalpha = FIXED(255)/gw->g.height;
  213. for(alpha = 0, i = 0; i < gw->g.height; i++, alpha += dalpha)
  214. 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)));
  215. 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);
  216. 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);
  217. 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);
  218. }
  219. void gwinRadioDraw_Tab(GWidgetObject *gw, void *param) {
  220. const GColorSet * pcol;
  221. fixed alpha;
  222. fixed dalpha;
  223. coord_t i;
  224. color_t tcol, bcol;
  225. (void) param;
  226. if (gw->g.vmt != (gwinVMT *)&radioVMT) return;
  227. pcol = getDrawColors(gw);
  228. if ((gw->g.flags & GRADIO_FLG_PRESSED)) {
  229. tcol = gdispBlendColor(pcol->edge, gw->pstyle->background, GRADIO_OUTLINE_FADE);
  230. gdispGFillStringBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->text, gw->g.font, pcol->text, gw->g.bgcolor, justifyCenter);
  231. gdispGDrawLine(gw->g.display, gw->g.x, gw->g.y, gw->g.x+gw->g.width-(GRADIO_TAB_CNR+1), gw->g.y, tcol);
  232. gdispGDrawLine(gw->g.display, gw->g.x+gw->g.width-(GRADIO_TAB_CNR+1), gw->g.y, gw->g.x+gw->g.width-1, gw->g.y+GRADIO_TAB_CNR, tcol);
  233. gdispGDrawLine(gw->g.display, gw->g.x+gw->g.width-1, gw->g.y+GRADIO_TAB_CNR, gw->g.x+gw->g.width-1, gw->g.y+gw->g.height-1, tcol);
  234. } else {
  235. /* Fill the box blended from variants of the fill color */
  236. tcol = gdispBlendColor(White, pcol->fill, GRADIO_TOP_FADE);
  237. bcol = gdispBlendColor(Black, pcol->fill, GRADIO_BOTTOM_FADE);
  238. dalpha = FIXED(255)/gw->g.height;
  239. for(alpha = 0, i = 0; i < gw->g.height; i++, alpha += dalpha)
  240. 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)));
  241. 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);
  242. gdispGDrawStringBox(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter);
  243. }
  244. }
  245. #endif
  246. #endif /* GFX_USE_GWIN && GWIN_NEED_BUTTON */