version 2.8
gwin_radio.c
Go to the documentation of this file.
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 /**
9  * @file src/gwin/gwin_radio.c
10  * @brief GWIN sub-system radio button code
11  */
12 
13 #include "../../gfx.h"
14 
15 #if GFX_USE_GWIN && GWIN_NEED_RADIO
16 
17 #include "gwin_class.h"
18 
19 #define GRADIO_TAB_CNR 8 // Diagonal corner on active tab
20 #define GRADIO_TOP_FADE 50 // (GRADIO_TOP_FADE/255)% fade to white for top of tab/button
21 #define GRADIO_BOTTOM_FADE 25 // (GRADIO_BOTTOM_FADE/255)% fade to black for bottom of tab/button
22 #define GRADIO_OUTLINE_FADE 128 // (GRADIO_OUTLINE_FADE/255)% fade to background for active tab edge
23 
24 // Send the button event
25 static void SendRadioEvent(GWidgetObject *gw) {
26  GSourceListener * psl;
27  GEvent * pe;
28  #define pbe ((GEventGWinRadio *)pe)
29 
30  // Trigger a GWIN Button Event
31  psl = 0;
32  while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
33  if (!(pe = geventGetEventBuffer(psl)))
34  continue;
35  pbe->type = GEVENT_GWIN_RADIO;
36  pbe->gwin = (GHandle)gw;
37  pbe->group = ((GRadioObject *)gw)->group;
38  #if GWIN_WIDGET_TAGS
39  pbe->tag = gw->tag;
40  #endif
41  geventSendEvent(psl);
42  }
43 
44  #undef pbe
45 }
46 
47 #if GINPUT_NEED_MOUSE
48  // A mouse down has occurred over the button
49  static void RadioMouseDown(GWidgetObject *gw, coord_t x, coord_t y) {
50  (void) x; (void) y;
51 
53  }
54 #endif
55 
56 #if GINPUT_NEED_TOGGLE
57  // A toggle on has occurred
58  static void RadioToggleOn(GWidgetObject *gw, uint16_t role) {
59  (void) role;
60 
62  }
63 
64  static void RadioToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
65  (void) role;
66  ((GRadioObject *)gw)->toggle = instance;
67  }
68 
69  static uint16_t RadioToggleGet(GWidgetObject *gw, uint16_t role) {
70  (void) role;
71  return ((GRadioObject *)gw)->toggle;
72  }
73 #endif
74 
75 // The radio button VMT table
76 static const gwidgetVMT radioVMT = {
77  {
78  "Radio", // The classname
79  sizeof(GRadioObject), // The object size
80  _gwidgetDestroy, // The destroy routine
81  _gwidgetRedraw, // The redraw routine
82  0, // The after-clear routine
83  },
84  gwinRadioDraw_Radio, // The default drawing routine
86  {
87  RadioMouseDown, // 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  0 // Process keyboard events
95  },
96  #endif
97  #if GINPUT_NEED_TOGGLE
98  {
99  1, // 1 toggle role
100  RadioToggleAssign, // Assign Toggles
101  RadioToggleGet, // Get Toggles
102  0, // Process toggle off events (NOT USED)
103  RadioToggleOn, // 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 
116 GHandle gwinGRadioCreate(GDisplay *g, GRadioObject *gw, const GWidgetInit *pInit, uint16_t group) {
117  if (!(gw = (GRadioObject *)_gwidgetCreate(g, &gw->w, pInit, &radioVMT)))
118  return 0;
119 
120  #if GINPUT_NEED_TOGGLE
121  gw->toggle = GWIDGET_NO_INSTANCE;
122  #endif
123  gw->group = group;
124  gwinSetVisible((GHandle)gw, pInit->g.show);
125  return (GHandle)gw;
126 }
127 
128 void gwinRadioPress(GHandle gh) {
129  GHandle gx;
130 
131  if (gh->vmt != (gwinVMT *)&radioVMT || (gh->flags & GRADIO_FLG_PRESSED))
132  return;
133 
134  if ((gx = gwinRadioGetActive(((GRadioObject *)gh)->group))) {
135  gx->flags &= ~GRADIO_FLG_PRESSED;
136  _gwinUpdate(gx);
137  }
138  gh->flags |= GRADIO_FLG_PRESSED;
139  _gwinUpdate(gh);
140  SendRadioEvent((GWidgetObject *)gh);
141 }
142 
143 bool_t gwinRadioIsPressed(GHandle gh) {
144  if (gh->vmt != (gwinVMT *)&radioVMT)
145  return FALSE;
146 
147  return (gh->flags & GRADIO_FLG_PRESSED) ? TRUE : FALSE;
148 }
149 
150 GHandle gwinRadioGetActive(uint16_t group) {
151  GHandle gh;
152 
153  for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
154  if (gh->vmt == (gwinVMT *)&radioVMT && ((GRadioObject *)gh)->group == group && (gh->flags & GRADIO_FLG_PRESSED))
155  return gh;
156  }
157  return 0;
158 }
159 
160 /*----------------------------------------------------------
161  * Custom Draw Routines
162  *----------------------------------------------------------*/
163 
164 static const GColorSet *getDrawColors(GWidgetObject *gw) {
165  if (!(gw->g.flags & GWIN_FLG_SYSENABLED)) return &gw->pstyle->disabled;
166  if ((gw->g.flags & GRADIO_FLG_PRESSED)) return &gw->pstyle->pressed;
167  return &gw->pstyle->enabled;
168 }
169 
170 void gwinRadioDraw_Radio(GWidgetObject *gw, void *param) {
171  #define gcw ((GRadioObject *)gw)
172  coord_t ld, df;
173  const GColorSet * pcol;
174  (void) param;
175 
176  if (gw->g.vmt != (gwinVMT *)&radioVMT) return;
177  pcol = getDrawColors(gw);
178 
179  ld = gw->g.width < gw->g.height ? gw->g.width : gw->g.height;
180 
181  #if GDISP_NEED_CIRCLE
182  df = (ld-1)/2;
183  gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, ld, ld, gw->pstyle->background);
184  gdispGDrawCircle(gw->g.display, gw->g.x+df, gw->g.y+df, df, pcol->edge);
185 
186  if (gw->g.flags & GRADIO_FLG_PRESSED)
187  gdispGFillCircle(gw->g.display, gw->g.x+df, gw->g.y+df, df <= 2 ? 1 : (df-2), pcol->fill);
188  #else
189  gdispGFillArea(gw->g.display, gw->g.x+1, gw->g.y+1, ld, ld-2, gw->pstyle->background);
190  gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, ld, ld, pcol->edge);
191 
192  df = ld < 4 ? 1 : 2;
193  if (gw->g.flags & GRADIO_FLG_PRESSED)
194  gdispGFillArea(gw->g.display, gw->g.x+df, gw->g.y+df, ld-2*df, ld-2*df, pcol->fill);
195  #endif
196 
197  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);
198  #undef gcw
199 }
200 
201 #if GWIN_FLAT_STYLING
202  void gwinRadioDraw_Button(GWidgetObject *gw, void *param) {
203  const GColorSet * pcol;
204  (void) param;
205 
206  if (gw->g.vmt != (gwinVMT *)&radioVMT) return;
207  pcol = getDrawColors(gw);
208 
209  #if GWIN_NEED_FLASHING
210  // Flash only the on state.
211  pcol = _gwinGetFlashedColor(gw, pcol, FALSE);
212  #endif
213 
214  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);
215  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);
216  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);
217  }
218  void gwinRadioDraw_Tab(GWidgetObject *gw, void *param) {
219  const GColorSet * pcol;
220  (void) param;
221 
222  if (gw->g.vmt != (gwinVMT *)&radioVMT) return;
223  pcol = getDrawColors(gw);
224 
225  #if GWIN_NEED_FLASHING
226  // Flash only the on state.
227  pcol = _gwinGetFlashedColor(gw, pcol, FALSE);
228  #endif
229 
230  if ((gw->g.flags & GRADIO_FLG_PRESSED)) {
231  gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge);
232  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);
233  } else {
234  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);
235  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);
236  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);
237  }
238  }
239 #else
240  void gwinRadioDraw_Button(GWidgetObject *gw, void *param) {
241  const GColorSet * pcol;
242  fixed alpha;
243  fixed dalpha;
244  coord_t i;
245  color_t tcol, bcol;
246  (void) param;
247 
248  if (gw->g.vmt != (gwinVMT *)&radioVMT) return;
249  pcol = getDrawColors(gw);
250 
251  /* Fill the box blended from variants of the fill color */
252  tcol = gdispBlendColor(White, pcol->fill, GRADIO_TOP_FADE);
253  bcol = gdispBlendColor(Black, pcol->fill, GRADIO_BOTTOM_FADE);
254  dalpha = FIXED(255)/gw->g.height;
255  for(alpha = 0, i = 0; i < gw->g.height; i++, alpha += dalpha)
256  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)));
257 
258  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);
259  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);
260  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);
261  }
262  void gwinRadioDraw_Tab(GWidgetObject *gw, void *param) {
263  const GColorSet * pcol;
264  fixed alpha;
265  fixed dalpha;
266  coord_t i;
267  color_t tcol, bcol;
268  (void) param;
269 
270  if (gw->g.vmt != (gwinVMT *)&radioVMT) return;
271  pcol = getDrawColors(gw);
272 
273  if ((gw->g.flags & GRADIO_FLG_PRESSED)) {
274  tcol = gdispBlendColor(pcol->edge, gw->pstyle->background, GRADIO_OUTLINE_FADE);
275  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);
276  gdispGDrawLine(gw->g.display, gw->g.x, gw->g.y, gw->g.x+gw->g.width-(GRADIO_TAB_CNR+1), gw->g.y, tcol);
277  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);
278  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);
279  } else {
280  /* Fill the box blended from variants of the fill color */
281  tcol = gdispBlendColor(White, pcol->fill, GRADIO_TOP_FADE);
282  bcol = gdispBlendColor(Black, pcol->fill, GRADIO_BOTTOM_FADE);
283  dalpha = FIXED(255)/gw->g.height;
284  for(alpha = 0, i = 0; i < gw->g.height; i++, alpha += dalpha)
285  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)));
286  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);
287  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);
288  }
289  }
290 #endif
291 
292 #endif /* GFX_USE_GWIN && GWIN_NEED_BUTTON */
void gdispGFillStringBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, const char *str, font_t font, color_t color, color_t bgColor, justify_t justify)
Draw a text string vertically centered within the specified box. The box background is filled with th...
#define GRADIO_FLG_PRESSED
The internal radio button object flags.
Definition: gwin_radio.h:53
color_t gdispBlendColor(color_t fg, color_t bg, uint8_t alpha)
Blend 2 colors according to the alpha.
const struct gwinVMT * vmt
Definition: gwin.h:45
GEvent * geventGetEventBuffer(GSourceListener *psl)
Get the event buffer from the GSourceListener.
Definition: gevent.c:187
GHandle gwinGetNextWindow(GHandle gh)
Get the next window in the z-order.
uint32_t flags
Definition: gwin.h:53
int16_t coord_t
The type for a coordinate or length on the screen.
Definition: gdisp.h:39
The structure to initialise a widget.
Definition: gwin_widget.h:97
color_t background
Definition: gwin_widget.h:53
coord_t y
Definition: gwin.h:48
coord_t x
Definition: gwin.h:47
int32_t fixed
The type for a fixed point type.
Definition: gmisc.h:60
color_t text
Definition: gwin_widget.h:38
GWindowInit g
Definition: gwin_widget.h:98
#define GINPUT_NEED_MOUSE
Should mouse/touch functions be included.
The GColorSet structure.
Definition: gwin_widget.h:37
void gwinRadioDraw_Radio(GWidgetObject *gw, void *param)
The default rendering function for the radiobutton widget.
GWindowObject g
Definition: gwin_widget.h:119
#define FALSE
Generic &#39;false&#39; boolean constant.
Definition: gfx.h:31
void gdispGDrawCircle(GDisplay *g, coord_t x, coord_t y, coord_t radius, color_t color)
Draw a circle.
struct GRadioObject GRadioObject
The radio button widget structure.
void gdispGDrawLine(GDisplay *g, coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color)
Draw a line.
GColorSet pressed
Definition: gwin_widget.h:57
GColorSet disabled
Definition: gwin_widget.h:56
void gdispGFillArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color)
Fill an area with a color.
GColorSet enabled
Definition: gwin_widget.h:55
const char * text
Definition: gwin_widget.h:120
void gwinSetVisible(GHandle gh, bool_t visible)
Sets whether a window is visible or not.
const GWidgetStyle * pstyle
Definition: gwin_widget.h:123
The GWIN Widget structure.
Definition: gwin_widget.h:118
bool_t show
Definition: gwin.h:80
WidgetTag tag
Definition: gwin_widget.h:125
void gdispGFillCircle(GDisplay *g, coord_t x, coord_t y, coord_t radius, color_t color)
Draw a filled circle.
color_t bgcolor
Definition: gwin.h:52
GDisplay * display
Definition: gwin.h:46
bool_t gwinRadioIsPressed(GHandle gh)
Is the radio button currently pressed.
void gdispGDrawStringBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, const char *str, font_t font, color_t color, justify_t justify)
Draw a text string vertically centered within the specified box.
void gwinRadioDraw_Tab(GWidgetObject *gw, void *param)
Used to render tabbed menus.
coord_t height
Definition: gwin.h:50
void geventSendEvent(GSourceListener *psl)
Called by a source to indicate the listener&#39;s event buffer has been filled.
Definition: gevent.c:200
void gwinRadioDraw_Button(GWidgetObject *gw, void *param)
Renders the radiobutton in form of a regular rectangular button.
The Virtual Method Table for a widget.
Definition: gwin_class.h:85
#define FIXED(x)
Macros to convert to and from a fixed point.
Definition: gmisc.h:66
coord_t width
Definition: gwin.h:49
void gwinRadioPress(GHandle gh)
Press this radio button (and by definition unset any others in the group)
void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color)
Draw a rectangular box.
color_t fill
Definition: gwin_widget.h:40
The Virtual Method Table for a GWIN window.
Definition: gwin_class.h:55
A window object structure.
Definition: gwin.h:40
#define GEVENT_GWIN_RADIO
The Event Type for a Radio Event.
Definition: gwin_radio.h:33
COLOR_TYPE color_t
The color type definition.
Definition: gdisp_colors.h:412
GHandle gwinGRadioCreate(GDisplay *g, GRadioObject *gb, const GWidgetInit *pInit, uint16_t group)
Create a radio widget.
The radio button widget structure.
Definition: gwin_radio.h:60
#define TRUE
Generic &#39;true&#39; boolean constant.
Definition: gfx.h:38
GHandle gwinRadioGetActive(uint16_t group)
Find the currently pressed radio button in the specified group.
color_t edge
Definition: gwin_widget.h:39
GSourceListener * geventGetSourceListener(GSourceHandle gsh, GSourceListener *lastlr)
Called by a source with a possible event to get a listener record.
Definition: gevent.c:163