The official µGFX library repository.

gwin_widget.c 18KB

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