version 2.8
gwin_widget.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_widget.c
10  * @brief GWIN sub-system widget code
11  */
12 
13 #include "../../gfx.h"
14 
15 #if GFX_USE_GWIN && GWIN_NEED_WIDGET
16 
17 #include <string.h>
18 
19 #include "gwin_class.h"
20 
21 // Our listener for events for widgets
22 static GListener gl;
23 
24 #if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD
25  // Our current focus window
26  static GHandle _widgetInFocus;
27 #endif
28 
29 // Our default style - a white background theme
30 const GWidgetStyle WhiteWidgetStyle = {
31  HTML2COLOR(0xFFFFFF), // window background
32  HTML2COLOR(0x2A8FCD), // focused
33 
34  // enabled color set
35  {
36  HTML2COLOR(0x000000), // text
37  HTML2COLOR(0x404040), // edge
38  HTML2COLOR(0xE0E0E0), // fill
39  HTML2COLOR(0x00E000) // progress - active area
40  },
41 
42  // disabled color set
43  {
44  HTML2COLOR(0xC0C0C0), // text
45  HTML2COLOR(0x808080), // edge
46  HTML2COLOR(0xE0E0E0), // fill
47  HTML2COLOR(0xC0E0C0) // progress - active area
48  },
49 
50  // pressed color set
51  {
52  HTML2COLOR(0x404040), // text
53  HTML2COLOR(0x404040), // edge
54  HTML2COLOR(0x808080), // fill
55  HTML2COLOR(0x00E000) // progress - active area
56  }
57 };
58 
59 /* Our black style */
61  HTML2COLOR(0x000000), // window background
62  HTML2COLOR(0x2A8FCD), // focused
63 
64  // enabled color set
65  {
66  HTML2COLOR(0xC0C0C0), // text
67  HTML2COLOR(0xC0C0C0), // edge
68  HTML2COLOR(0x606060), // fill
69  HTML2COLOR(0x008000) // progress - active area
70  },
71 
72  // disabled color set
73  {
74  HTML2COLOR(0x808080), // text
75  HTML2COLOR(0x404040), // edge
76  HTML2COLOR(0x404040), // fill
77  HTML2COLOR(0x004000) // progress - active area
78  },
79 
80  // pressed color set
81  {
82  HTML2COLOR(0xFFFFFF), // text
83  HTML2COLOR(0xC0C0C0), // edge
84  HTML2COLOR(0xE0E0E0), // fill
85  HTML2COLOR(0x008000) // progress - active area
86  }
87 };
88 
89 static const GWidgetStyle * defaultStyle = &BlackWidgetStyle;
90 
91 // We use these everywhere in this file
92 #define gw ((GWidgetObject *)gh)
93 #define wvmt ((gwidgetVMT *)gh->vmt)
94 
95 // Process an event
96 static void gwidgetEvent(void *param, GEvent *pe) {
97  #define pme ((GEventMouse *)pe)
98  #define pke ((GEventKeyboard *)pe)
99  #define pte ((GEventToggle *)pe)
100  #define pde ((GEventDial *)pe)
101 
102  #if GFX_USE_GINPUT
103  #if GINPUT_NEED_MOUSE
104  GHandle h;
105  #endif
106  #if GINPUT_NEED_MOUSE || GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL || GINPUT_NEED_KEYBOARD
107  GHandle gh;
108  #endif
109  #if GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL
110  uint16_t role;
111  #endif
112  #endif
113 
114  (void) param;
115 
116  // Process various events
117  switch (pe->type) {
118 
119  #if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
120  case GEVENT_MOUSE:
121  case GEVENT_TOUCH:
122  // Cycle through all windows
123  for (gh = 0, h = gwinGetNextWindow(0); h; h = gwinGetNextWindow(h)) {
124 
125  // The window must be on this display and visible to be relevant
126  if (h->display != pme->display || !(h->flags & GWIN_FLG_SYSVISIBLE))
127  continue;
128 
129  // Is the mouse currently captured by this widget?
130  if ((h->flags & (GWIN_FLG_WIDGET|GWIN_FLG_MOUSECAPTURE)) == (GWIN_FLG_WIDGET|GWIN_FLG_MOUSECAPTURE)) {
131  gh = h;
132  if ((pme->buttons & GMETA_MOUSE_UP)) {
133  gh->flags &= ~GWIN_FLG_MOUSECAPTURE;
134  if (wvmt->MouseUp)
135  wvmt->MouseUp(gw, pme->x - gh->x, pme->y - gh->y);
136  } else if (wvmt->MouseMove)
137  wvmt->MouseMove(gw, pme->x - gh->x, pme->y - gh->y);
138 
139  // There is only ever one captured mouse. Prevent normal mouse processing if there is a captured mouse
140  gh = 0;
141 
142  break;
143  }
144 
145  // Save the highest z-order window that the mouse is over
146  if (pme->x >= h->x && pme->x < h->x + h->width && pme->y >= h->y && pme->y < h->y + h->height)
147  gh = h;
148  }
149 
150  // Process any mouse down over the highest order window if it is an enabled widget
151  if (gh && (gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED)) == (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED)) {
152  if ((pme->buttons & GMETA_MOUSE_DOWN)) {
153  gh->flags |= GWIN_FLG_MOUSECAPTURE;
154 
155  #if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD
156  // We should try and capture the focus on this window.
157  // If we can't then we don't change the focus
158  gwinSetFocus(gh);
159  #endif
160 
161  if (wvmt->MouseDown)
162  wvmt->MouseDown(gw, pme->x - gh->x, pme->y - gh->y);
163  }
164  }
165  break;
166  #endif
167 
168  #if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD
169  case GEVENT_KEYBOARD:
170  // If Tab key pressed then set focus to next widget
171  if (pke->bytecount == 1 && pke->c[0] == GKEY_TAB) {
172  if (!(pke->keystate & GKEYSTATE_KEYUP))
173  _gwinMoveFocus();
174  break;
175  }
176 
177  // Otherwise, send keyboard events only to widget in focus
178  if (_widgetInFocus)
179  ((gwidgetVMT*)_widgetInFocus->vmt)->KeyboardEvent((GWidgetObject*)_widgetInFocus, pke);
180  break;
181  #endif
182 
183  #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
184  case GEVENT_TOGGLE:
185  // Cycle through all windows
186  for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
187 
188  // check if it a widget that is enabled and visible
189  if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE))
190  continue;
191 
192  for(role = 0; role < wvmt->toggleroles; role++) {
193  if (wvmt->ToggleGet(gw, role) == pte->instance) {
194  if (pte->on) {
195  if (wvmt->ToggleOn)
196  wvmt->ToggleOn(gw, role);
197  } else {
198  if (wvmt->ToggleOff)
199  wvmt->ToggleOff(gw, role);
200  }
201  }
202  }
203  }
204  break;
205  #endif
206 
207  #if GFX_USE_GINPUT && GINPUT_NEED_DIAL
208  case GEVENT_DIAL:
209  // Cycle through all windows
210  for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
211 
212  // check if it a widget that is enabled and visible
213  if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE))
214  continue;
215 
216  for(role = 0; role < wvmt->dialroles; role++) {
217  if (wvmt->DialGet(gw, role) == pte->instance) {
218  if (wvmt->DialMove)
219  wvmt->DialMove(gw, role, pde->value, pde->maxvalue);
220  }
221  }
222  }
223  break;
224  #endif
225 
226  default:
227  break;
228  }
229 
230  #undef pme
231  #undef pte
232  #undef pke
233  #undef pde
234 }
235 
236 #if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD
237  GHandle gwinGetFocus(void) {
238  return _widgetInFocus;
239  }
240 
241  bool_t gwinSetFocus(GHandle gh) {
242  GHandle oldFocus;
243 
244  // Do we already have the focus?
245  if (gh == _widgetInFocus)
246  return TRUE;
247 
248  // The new window must be NULLL or a visible enabled widget with a keyboard handler
249  if (!gh || ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)
250  && ((gwidgetVMT*)gh->vmt)->KeyboardEvent)) {
251  // Move the current focus
252  oldFocus = _widgetInFocus;
253  _widgetInFocus = gh;
254  if (oldFocus) _gwinUpdate(oldFocus);
255  if (gh) _gwinUpdate(gh);
256  return TRUE;
257  }
258  return FALSE;
259  }
260 
261  void _gwinMoveFocus(void) {
262  GHandle gh;
263  bool_t looponce;
264 
265  // Find a new focus window (one may or may not exist).
266  looponce = FALSE;
267  for(gh = gwinGetNextWindow(_widgetInFocus); ; gh = gwinGetNextWindow(gh)) {
268  if (!gh && !looponce) {
269  looponce = TRUE;
270  gh = gwinGetNextWindow(0);
271  }
272  if (gwinSetFocus(gh))
273  break;
274  }
275  }
276 
277  void _gwinFixFocus(GHandle gh) {
278  GHandle oldFocus;
279 
280  if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)
281  && ((gwidgetVMT*)gh->vmt)->KeyboardEvent) {
282 
283  // We are a candidate to be able to claim the focus
284 
285  // Claim the focus if no-one else has
286  if (!_widgetInFocus)
287  _widgetInFocus = gh;
288 
289  return;
290  }
291 
292  // We have lost any right to the focus
293 
294  // Did we have the focus
295  if (gh != _widgetInFocus)
296  return;
297 
298  // We did - we need to find a new focus window
299  oldFocus = _widgetInFocus;
300  for(gh = gwinGetNextWindow(oldFocus); gh && gh != oldFocus; gh = gwinGetNextWindow(gh)) {
301 
302  // Must be a visible enabled widget with a keyboard handler
303  if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)
304  && ((gwidgetVMT*)gh->vmt)->KeyboardEvent) {
305 
306  // Grab the focus for the new window
307  _widgetInFocus = gh;
308 
309  // This new window still needs to be marked for redraw (but don't actually do it yet).
310  gh->flags |= GWIN_FLG_NEEDREDRAW;
311  // RedrawPending |= DOREDRAW_VISIBLES; - FIX LATER
312  return;
313  }
314  }
315 
316  // No-one has the right to the focus
317  _widgetInFocus = 0;
318  }
319 
320  void _gwidgetDrawFocusRect(GWidgetObject *gx, coord_t x, coord_t y, coord_t cx, coord_t cy) {
321  coord_t i;
322 
323  // Don't do anything if we don't have the focus
324  if (&gx->g != _widgetInFocus)
325  return;
326 
327  // Use the very simplest possible focus rectangle for now
328  for (i = 0; i < GWIN_FOCUS_HIGHLIGHT_WIDTH; i++) {
329  gdispGDrawBox(gx->g.display, gx->g.x+x+i, gx->g.y+y+i, cx-2*i, cy-2*i, gx->pstyle->focus);
330  }
331  }
332 
333 #endif
334 
335 #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
336  static GHandle FindToggleUser(uint16_t instance) {
337  GHandle gh;
338  uint16_t role;
339 
340  for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
341  if (!(gh->flags & GWIN_FLG_WIDGET)) // check if it a widget
342  continue;
343 
344  for(role = 0; role < wvmt->toggleroles; role++) {
345  if (wvmt->ToggleGet(gw, role) == instance)
346  return gh;
347  }
348  }
349  return 0;
350  }
351 #endif
352 
353 #if GFX_USE_GINPUT && GINPUT_NEED_DIAL
354  static GHandle FindDialUser(uint16_t instance) {
355  GHandle gh;
356  uint16_t role;
357 
358  for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
359  if (!(gh->flags & GWIN_FLG_WIDGET)) // check if it a widget
360  continue;
361 
362  for(role = 0; role < wvmt->dialroles; role++) {
363  if (wvmt->DialGet(gw, role) == instance)
364  return gh;
365  }
366  }
367  return 0;
368  }
369 #endif
370 
371 void _gwidgetInit(void)
372 {
373  geventListenerInit(&gl);
374  geventRegisterCallback(&gl, gwidgetEvent, 0);
375  #if GINPUT_NEED_MOUSE
376  geventAttachSource(&gl, ginputGetMouse(GMOUSE_ALL_INSTANCES), GLISTEN_MOUSEMETA|GLISTEN_MOUSEDOWNMOVES);
377  #endif
378  #if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
379  geventAttachSource(&gl, ginputGetKeyboard(GKEYBOARD_ALL_INSTANCES), GLISTEN_KEYUP);
380  #endif
381 }
382 
383 void _gwidgetDeinit(void)
384 {
385  /* ToDo */
386 }
387 
388 GHandle _gwidgetCreate(GDisplay *g, GWidgetObject *pgw, const GWidgetInit *pInit, const gwidgetVMT *vmt) {
389  if (!(pgw = (GWidgetObject *)_gwindowCreate(g, &pgw->g, &pInit->g, &vmt->g, GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED)))
390  return 0;
391 
392  #if GWIN_NEED_CONTAINERS
393  // This window can't be system enabled if the parent is not enabled
394  if (pgw->g.parent && !(pgw->g.parent->flags & GWIN_FLG_SYSENABLED))
395  pgw->g.flags &= ~GWIN_FLG_SYSENABLED;
396  #endif
397  pgw->text = pInit->text ? pInit->text : "";
398  pgw->fnDraw = pInit->customDraw ? pInit->customDraw : vmt->DefaultDraw;
399  pgw->fnParam = pInit->customParam;
400  pgw->pstyle = pInit->customStyle ? pInit->customStyle : defaultStyle;
401  #if GWIN_WIDGET_TAGS
402  pgw->tag = pInit->tag;
403  #endif
404 
405  return &pgw->g;
406 }
407 
408 void _gwidgetDestroy(GHandle gh) {
409  #if GFX_USE_GINPUT && (GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL)
410  uint16_t role, instance;
411  #endif
412 
413  // Make the window is invisible so it is not eligible for focus
414  gh->flags &= ~GWIN_FLG_VISIBLE;
415  _gwinFixFocus(gh);
416 
417  // Deallocate the text (if necessary)
418  if ((gh->flags & GWIN_FLG_ALLOCTXT)) {
419  gh->flags &= ~GWIN_FLG_ALLOCTXT;
420  gfxFree((void *)gw->text);
421  }
422 
423  #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
424  // Detach any toggles from this object
425  for(role = 0; role < wvmt->toggleroles; role++) {
426  instance = wvmt->ToggleGet(gw, role);
427  if (instance != GWIDGET_NO_INSTANCE) {
428  wvmt->ToggleAssign(gw, role, GWIDGET_NO_INSTANCE);
429  if (!FindToggleUser(instance))
430  geventDetachSource(&gl, ginputGetToggle(instance));
431  }
432  }
433  #endif
434 
435  #if GFX_USE_GINPUT && GINPUT_NEED_DIAL
436  // Detach any dials from this object
437  for(role = 0; role < wvmt->dialroles; role++) {
438  instance = wvmt->DialGet(gw, role);
439  if (instance != GWIDGET_NO_INSTANCE) {
440  wvmt->DialAssign(gw, role, GWIDGET_NO_INSTANCE);
441  if (!FindDialUser(instance))
442  geventDetachSource(&gl, ginputGetDial(instance));
443  }
444  }
445  #endif
446 
447  // Remove any listeners on this object.
448  geventDetachSourceListeners((GSourceHandle)gh);
449 }
450 
451 void _gwidgetRedraw(GHandle gh) {
452  if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
453  return;
454 
455  gw->fnDraw(gw, gw->fnParam);
456 }
457 
458 void _gwinSendEvent(GHandle gh, GEventType type) {
459  GSourceListener * psl;
460  GEventGWin * pge;
461 
462  // Trigger a GWIN Event
463  psl = 0;
464  while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
465  if (!(pge = (GEventGWin *)geventGetEventBuffer(psl)))
466  continue;
467  pge->type = type;
468  pge->gwin = gh;
469  #if GWIN_WIDGET_TAGS
470  pge->tag = (gh->flags & GWIN_FLG_WIDGET) ? ((GWidgetObject *)gh)->tag : 0;
471  #endif
472  geventSendEvent(psl);
473  }
474 }
475 
476 void gwinWidgetClearInit(GWidgetInit *pwi) {
477  char *p;
478  unsigned len;
479 
480  for(p = (char *)pwi, len = sizeof(GWidgetInit); len; len--)
481  *p++ = 0;
482 }
483 
484 void gwinSetDefaultStyle(const GWidgetStyle *pstyle, bool_t updateAll) {
485  if (!pstyle)
486  pstyle = &BlackWidgetStyle;
487 
488  if (updateAll) {
489  GHandle gh;
490 
491  for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
492  if ((gh->flags & GWIN_FLG_WIDGET) && ((GWidgetObject *)gh)->pstyle == defaultStyle)
493  gwinSetStyle(gh, pstyle);
494  else
495  gwinRedraw(gh);
496  }
497  }
499  defaultStyle = pstyle;
500 }
501 
502 /**
503  * @brief Get the current default style.
504  *
505  * @api
506  */
507 const GWidgetStyle *gwinGetDefaultStyle(void) {
508  return defaultStyle;
509 }
510 
511 void gwinSetText(GHandle gh, const char *text, bool_t useAlloc) {
512  if (!(gh->flags & GWIN_FLG_WIDGET))
513  return;
514 
515  // Dispose of the old string
516  if ((gh->flags & GWIN_FLG_ALLOCTXT)) {
517  gh->flags &= ~GWIN_FLG_ALLOCTXT;
518  if (gw->text) {
519  gfxFree((void *)gw->text);
520  gw->text = "";
521  }
522  }
523 
524  // Alloc the new text if required
525  if (!text || !*text)
526  gw->text = "";
527  else if (useAlloc) {
528  char *str;
529 
530  if ((str = gfxAlloc(strlen(text)+1))) {
531  gh->flags |= GWIN_FLG_ALLOCTXT;
532  strcpy(str, text);
533  }
534  gw->text = (const char *)str;
535  } else
536  gw->text = text;
537  _gwinUpdate(gh);
538 }
539 
540 #if GFX_USE_GFILE && GFILE_NEED_PRINTG && GFILE_NEED_STRINGS
541  #include <stdarg.h>
542 
543  void gwinPrintg(GHandle gh, const char * fmt, ...) {
544  char *str;
545  va_list va;
546  int size;
547 
548  if (!(gh->flags & GWIN_FLG_WIDGET))
549  return;
550 
551  // Dispose of the old string
552  if ((gh->flags & GWIN_FLG_ALLOCTXT)) {
553  gh->flags &= ~GWIN_FLG_ALLOCTXT;
554  if (gw->text) {
555  gfxFree((void *)gw->text);
556  gw->text = "";
557  }
558  }
559 
560  // Alloc the new text
561  va_start (va, fmt);
562 
563  size = vsnprintg(0, 0, fmt, va) + 1; //determine the buffer size required
564 
565  if ((str = gfxAlloc(size))) {
566  gh->flags |= GWIN_FLG_ALLOCTXT;
567  vsnprintg(str, size, fmt, va);
568  gw->text = (const char *)str;
569  } else
570  gw->text = "";
571 
572  va_end (va);
573 
574  _gwinUpdate(gh);
575  }
576 #endif
577 
578 const char *gwinGetText(GHandle gh) {
579  if (!(gh->flags & GWIN_FLG_WIDGET))
580  return 0;
581 
582  return gw->text;
583 }
584 
585 bool_t gwinIsWidget(GHandle gh) {
586  if (gh->flags & GWIN_FLG_WIDGET) {
587  return TRUE;
588  }
589 
590  return FALSE;
591 }
592 
593 void gwinSetStyle(GHandle gh, const GWidgetStyle *pstyle) {
594  if (!(gh->flags & GWIN_FLG_WIDGET))
595  return;
596 
597  gw->pstyle = pstyle ? pstyle : defaultStyle;
598  gh->bgcolor = gw->pstyle->background;
599  gh->color = gw->pstyle->enabled.text;
600 
601  _gwinUpdate(gh);
602 }
603 
604 const GWidgetStyle *gwinGetStyle(GHandle gh) {
605  if (!(gh->flags & GWIN_FLG_WIDGET))
606  return 0;
607 
608  return gw->pstyle;
609 }
610 
611 void gwinSetCustomDraw(GHandle gh, CustomWidgetDrawFunction fn, void *param) {
612  if (!(gh->flags & GWIN_FLG_WIDGET))
613  return;
614 
615  gw->fnDraw = fn ? fn : wvmt->DefaultDraw;
616  gw->fnParam = param;
617  _gwinUpdate(gh);
618 }
619 
620 bool_t gwinAttachListener(GListener *pl) {
621  return geventAttachSource(pl, GWIDGET_SOURCE, 0);
622 }
623 
624 #if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
625  bool_t DEPRECATED("This call can now be removed. Attaching the mouse to GWIN is now automatic.") gwinAttachMouse(uint16_t instance) {
626  // This is now a NULL event because we automatically attach to all mice in the system.
627  (void) instance;
628  return TRUE;
629  }
630 #endif
631 
632 #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
633  bool_t gwinAttachToggle(GHandle gh, uint16_t role, uint16_t instance) {
634  GSourceHandle gsh;
635  uint16_t oi;
636 
637  // Is this a widget
638  if (!(gh->flags & GWIN_FLG_WIDGET))
639  return FALSE;
640 
641  // Is the role valid
642  if (role >= wvmt->toggleroles)
643  return FALSE;
644 
645  // Is this a valid device
646  if (!(gsh = ginputGetToggle(instance)))
647  return FALSE;
648 
649  // Is this already done?
650  oi = wvmt->ToggleGet(gw, role);
651  if (instance == oi)
652  return TRUE;
653 
654  // Remove the old instance
655  if (oi != GWIDGET_NO_INSTANCE) {
656  wvmt->ToggleAssign(gw, role, GWIDGET_NO_INSTANCE);
657  if (!FindToggleUser(oi))
659  }
660 
661  // Assign the new
662  wvmt->ToggleAssign(gw, role, instance);
663  return geventAttachSource(&gl, gsh, GLISTEN_TOGGLE_ON|GLISTEN_TOGGLE_OFF);
664  }
665 
666  bool_t gwinDetachToggle(GHandle gh, uint16_t role) {
667  uint16_t oi;
668 
669  // Is this a widget
670  if (!(gh->flags & GWIN_FLG_WIDGET))
671  return FALSE;
672 
673  // Is the role valid
674  if (role >= ((gwidgetVMT *)gh->vmt)->toggleroles)
675  return FALSE;
676 
677  oi = ((gwidgetVMT *)gh->vmt)->ToggleGet(gw, role);
678 
679  // Remove the instance
680  if (oi != GWIDGET_NO_INSTANCE) {
681  ((gwidgetVMT *)gh->vmt)->ToggleAssign(gw, role, GWIDGET_NO_INSTANCE);
682  if (!FindToggleUser(oi))
684  }
685  return TRUE;
686  }
687 
688 #endif
689 
690 #if GFX_USE_GINPUT && GINPUT_NEED_DIAL
691  bool_t gwinAttachDial(GHandle gh, uint16_t role, uint16_t instance) {
692  GSourceHandle gsh;
693  uint16_t oi;
694 
695  if (!(gh->flags & GWIN_FLG_WIDGET))
696  return FALSE;
697 
698  // Is the role valid
699  if (role >= wvmt->dialroles)
700  return FALSE;
701 
702  // Is this a valid device
703  if (!(gsh = ginputGetDial(instance)))
704  return FALSE;
705 
706  // Is this already done?
707  oi = wvmt->DialGet(gw, role);
708  if (instance == oi)
709  return TRUE;
710 
711  // Remove the old instance
712  if (oi != GWIDGET_NO_INSTANCE) {
713  wvmt->DialAssign(gw, role, GWIDGET_NO_INSTANCE);
714  if (!FindDialUser(oi))
716  }
717 
718  // Assign the new
719  wvmt->DialAssign(gw, role, instance);
720  return geventAttachSource(&gl, gsh, 0);
721  }
722 #endif
723 
724 #if GWIN_WIDGET_TAGS
725  void gwinSetTag(GHandle gh, WidgetTag tag) {
726  if ((gh->flags & GWIN_FLG_WIDGET))
727  gw->tag = tag;
728  }
729 
731  return ((gh->flags & GWIN_FLG_WIDGET)) ? gw->tag : 0;
732  }
733 #endif
734 
735 #undef gw
736 #undef wvmt
737 #endif /* GFX_USE_GWIN && GWIN_NEED_WIDGET */
738 /** @} */
const char * text
Definition: gwin_widget.h:99
bool_t geventAttachSource(GListener *pl, GSourceHandle gsh, uint32_t flags)
Attach a source to a listener.
Definition: gevent.c:71
const struct gwinVMT * vmt
Definition: gwin.h:45
void gwinRedraw(GHandle gh)
Redraw a window.
#define GWIN_FOCUS_HIGHLIGHT_WIDTH
The width of the rectangle that highlights a widget that is focused.
Definition: gwin_options.h:52
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.
#define DEPRECATED(msg)
Mark a function as deprecated.
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
bool_t gwinSetFocus(GHandle gh)
Set the keyboard focus to a specific window.
The GWidgetStyle structure.
Definition: gwin_widget.h:52
color_t background
Definition: gwin_widget.h:53
void geventListenerInit(GListener *pl)
Create a Listener.
Definition: gevent.c:64
coord_t y
Definition: gwin.h:48
coord_t x
Definition: gwin.h:47
const GWidgetStyle BlackWidgetStyle
We define a couple of GWidgetStyle&#39;s that you can use in your application. The Black style is the def...
WidgetTag gwinGetTag(GHandle gh)
Get the tag of a widget.
void(* CustomWidgetDrawFunction)(struct GWidgetObject *gw, void *param)
Defines a custom drawing function for a widget.
Definition: gwin_widget.h:76
WidgetTag tag
Definition: gwin_widget.h:104
bool_t gwinAttachListener(GListener *pl)
Attach a Listener to listen for widget events.
void(* DefaultDraw)(GWidgetObject *gw, void *param)
Definition: gwin_class.h:87
GWindowInit g
Definition: gwin_widget.h:98
struct gwinVMT g
Definition: gwin_class.h:86
GWindowObject g
Definition: gwin_widget.h:119
void gwinSetCustomDraw(GHandle gh, CustomWidgetDrawFunction fn, void *param)
Set the routine to perform a custom widget drawing.
#define FALSE
Generic &#39;false&#39; boolean constant.
Definition: gfx.h:31
const char * gwinGetText(GHandle gh)
Get the text of a widget.
void gwinWidgetClearInit(GWidgetInit *pwi)
Clear a GWidgetInit structure to all zero&#39;s.
void gwinSetDefaultStyle(const GWidgetStyle *pstyle, bool_t updateAll)
Set the default style for widgets created hereafter.
void * gfxAlloc(size_t sz)
Allocate memory.
GEventType type
Definition: gwin_widget.h:150
const char * text
Definition: gwin_widget.h:120
GSourceHandle ginputGetMouse(unsigned instance)
Get the Source handler for a mouse using the instance number.
const GWidgetStyle * pstyle
Definition: gwin_widget.h:123
CustomWidgetDrawFunction fnDraw
Definition: gwin_widget.h:121
The GWIN Widget structure.
Definition: gwin_widget.h:118
GHandle gwinGetFocus(void)
Get the widget that is currently in focus.
const GWidgetStyle * customStyle
Definition: gwin_widget.h:102
WidgetTag tag
Definition: gwin_widget.h:125
color_t bgcolor
Definition: gwin.h:52
GDisplay * display
Definition: gwin.h:46
GSourceHandle ginputGetDial(uint16_t instance)
Create a dial input instance.
const GWidgetStyle * gwinGetStyle(GHandle gh)
Get the style of a widget.
GSourceHandle ginputGetToggle(uint16_t instance)
Create a toggle input instance.
Definition: ginput_toggle.c:95
color_t focus
Definition: gwin_widget.h:54
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 gwinSetStyle(GHandle gh, const GWidgetStyle *pstyle)
Set the style of a widget.
void gfxFree(void *ptr)
Free memory.
The Virtual Method Table for a widget.
Definition: gwin_class.h:85
#define HTML2COLOR(h)
Convert a 6 digit HTML code (hex) into a color value.
Definition: gdisp_colors.h:176
void geventDetachSource(GListener *pl, GSourceHandle gsh)
Detach a source from a listener.
Definition: gevent.c:108
coord_t width
Definition: gwin.h:49
uint16_t WidgetTag
Defines a the type of a tag on a widget.
Definition: gwin_widget.h:81
void * customParam
Definition: gwin_widget.h:101
void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color)
Draw a rectangular box.
void geventDetachSourceListeners(GSourceHandle gsh)
Detach any listener that has this source attached.
Definition: gevent.c:220
void gwinPrintg(GHandle gh, const char *fmt,...)
Set the text of a widget using a printf style format.
bool_t gwinAttachToggle(GHandle gh, uint16_t role, uint16_t instance)
Attach a toggle to a widget.
const GWidgetStyle * gwinGetDefaultStyle(void)
Get the current default style.
A window object structure.
Definition: gwin.h:40
void gwinSetTag(GHandle gh, WidgetTag tag)
Set the tag of a widget.
void * fnParam
Definition: gwin_widget.h:122
bool_t gwinAttachDial(GHandle gh, uint16_t role, uint16_t instance)
Attach a toggle to a widget.
GHandle gwin
Definition: gwin_widget.h:151
color_t color
Definition: gwin.h:51
bool_t gwinIsWidget(GHandle gh)
Check whether a handles is a widget handle or not.
CustomWidgetDrawFunction customDraw
Definition: gwin_widget.h:100
GSourceHandle ginputGetKeyboard(unsigned instance)
Create a keyboard input instance.
#define TRUE
Generic &#39;true&#39; boolean constant.
Definition: gfx.h:38
void gwinSetDefaultBgColor(color_t bgclr)
Set the default background color for all new GWIN windows.
bool_t gwinDetachToggle(GHandle gh, uint16_t role)
Detach a toggle from a widget.
A Generic GWIN Event.
Definition: gwin_widget.h:149
GSourceListener * geventGetSourceListener(GSourceHandle gsh, GSourceListener *lastlr)
Called by a source with a possible event to get a listener record.
Definition: gevent.c:163
void gwinSetText(GHandle gh, const char *text, bool_t useAlloc)
Set the text of a widget.