pushbutton.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. //*****************************************************************************
  2. //
  3. // pushbutton.c - Various types of push buttons.
  4. //
  5. // Copyright (c) 2008-2010 Texas Instruments Incorporated. All rights reserved.
  6. // Software License Agreement
  7. //
  8. // Texas Instruments (TI) is supplying this software for use solely and
  9. // exclusively on TI's microcontroller products. The software is owned by
  10. // TI and/or its suppliers, and is protected under applicable copyright
  11. // laws. You may not combine this software with "viral" open-source
  12. // software in order to form a larger program.
  13. //
  14. // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
  15. // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
  16. // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  17. // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
  18. // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
  19. // DAMAGES, FOR ANY REASON WHATSOEVER.
  20. //
  21. // This is part of revision 6288 of the Stellaris Graphics Library.
  22. //
  23. //*****************************************************************************
  24. #include "debug.h"
  25. #include "grlib.h"
  26. #include "widget.h"
  27. #include "pushbutton.h"
  28. //*****************************************************************************
  29. //
  30. //! \addtogroup pushbutton_api
  31. //! @{
  32. //
  33. //*****************************************************************************
  34. //*****************************************************************************
  35. //
  36. //! Draws a rectangular push button.
  37. //!
  38. //! \param pWidget is a pointer to the push button widget to be drawn.
  39. //!
  40. //! This function draws a rectangular push button on the display. This is
  41. //! called in response to a \b #WIDGET_MSG_PAINT message.
  42. //!
  43. //! \return None.
  44. //
  45. //*****************************************************************************
  46. static void
  47. RectangularButtonPaint(tWidget *pWidget)
  48. {
  49. const unsigned char *pucImage;
  50. tPushButtonWidget *pPush;
  51. tContext sCtx;
  52. int lX, lY;
  53. //
  54. // Check the arguments.
  55. //
  56. ASSERT(pWidget);
  57. //
  58. // Convert the generic widget pointer into a push button widget pointer.
  59. //
  60. pPush = (tPushButtonWidget *)pWidget;
  61. //
  62. // Initialize a drawing context.
  63. //
  64. GrContextInit(&sCtx, pWidget->pDisplay);
  65. //
  66. // Initialize the clipping region based on the extents of this rectangular
  67. // push button.
  68. //
  69. GrContextClipRegionSet(&sCtx, &(pWidget->sPosition));
  70. //
  71. // See if the push button fill style is selected.
  72. //
  73. if(pPush->ulStyle & PB_STYLE_FILL)
  74. {
  75. //
  76. // Fill the push button with the fill color.
  77. //
  78. GrContextForegroundSet(&sCtx, ((pPush->ulStyle & PB_STYLE_PRESSED) ?
  79. pPush->ulPressFillColor :
  80. pPush->ulFillColor));
  81. GrRectFill(&sCtx, &(pWidget->sPosition));
  82. }
  83. //
  84. // See if the push button outline style is selected.
  85. //
  86. if(pPush->ulStyle & PB_STYLE_OUTLINE)
  87. {
  88. //
  89. // Outline the push button with the outline color.
  90. //
  91. GrContextForegroundSet(&sCtx, pPush->ulOutlineColor);
  92. GrRectDraw(&sCtx, &(pWidget->sPosition));
  93. }
  94. //
  95. // See if the push button text or image style is selected.
  96. //
  97. if(pPush->ulStyle & (PB_STYLE_TEXT | PB_STYLE_IMG))
  98. {
  99. //
  100. // Compute the center of the push button.
  101. //
  102. lX = (pWidget->sPosition.sXMin +
  103. ((pWidget->sPosition.sXMax - pWidget->sPosition.sXMin + 1) / 2));
  104. lY = (pWidget->sPosition.sYMin +
  105. ((pWidget->sPosition.sYMax - pWidget->sPosition.sYMin + 1) / 2));
  106. //
  107. // If the push button outline style is selected then shrink the
  108. // clipping region by one pixel on each side so that the outline is not
  109. // overwritten by the text or image.
  110. //
  111. if(pPush->ulStyle & PB_STYLE_OUTLINE)
  112. {
  113. sCtx.sClipRegion.sXMin++;
  114. sCtx.sClipRegion.sYMin++;
  115. sCtx.sClipRegion.sXMax--;
  116. sCtx.sClipRegion.sYMax--;
  117. }
  118. //
  119. // See if the push button image style is selected.
  120. //
  121. if(pPush->ulStyle & PB_STYLE_IMG)
  122. {
  123. //
  124. // Set the foreground and background colors to use for 1 BPP
  125. // images.
  126. //
  127. GrContextForegroundSet(&sCtx, pPush->ulTextColor);
  128. GrContextBackgroundSet(&sCtx,
  129. ((pPush->ulStyle & PB_STYLE_PRESSED) ?
  130. pPush->ulPressFillColor :
  131. pPush->ulFillColor));
  132. //
  133. // Get the image to be drawn.
  134. //
  135. pucImage = (((pPush->ulStyle & PB_STYLE_PRESSED) &&
  136. pPush->pucPressImage) ?
  137. pPush->pucPressImage : pPush->pucImage);
  138. //
  139. // Draw the image centered in the push button.
  140. //
  141. GrImageDraw(&sCtx, pucImage, pWidget->sPosition.sXMin, pWidget->sPosition.sYMin);
  142. }
  143. //
  144. // See if the push button text style is selected.
  145. //
  146. if(pPush->ulStyle & PB_STYLE_TEXT)
  147. {
  148. //
  149. // Draw the text centered in the middle of the push button.
  150. //
  151. GrContextFontSet(&sCtx, pPush->pFont);
  152. GrContextForegroundSet(&sCtx, pPush->ulTextColor);
  153. GrContextBackgroundSet(&sCtx,
  154. ((pPush->ulStyle & PB_STYLE_PRESSED) ?
  155. pPush->ulPressFillColor :
  156. pPush->ulFillColor));
  157. GrStringDrawCentered(&sCtx, pPush->pcText, -1, lX, lY,
  158. pPush->ulStyle & PB_STYLE_TEXT_OPAQUE);
  159. }
  160. }
  161. }
  162. //*****************************************************************************
  163. //
  164. //! Handles pointer events for a rectangular push button.
  165. //!
  166. //! \param pWidget is a pointer to the push button widget.
  167. //! \param ulMsg is the pointer event message.
  168. //! \param lX is the X coordinate of the pointer event.
  169. //! \param lY is the Y coordinate of the pointer event.
  170. //!
  171. //! This function processes pointer event messages for a rectangular push
  172. //! button. This is called in response to a \b #WIDGET_MSG_PTR_DOWN,
  173. //! \b #WIDGET_MSG_PTR_MOVE, and \b #WIDGET_MSG_PTR_UP messages.
  174. //!
  175. //! If the \b #WIDGET_MSG_PTR_UP message is received with a position within the
  176. //! extents of the push button, the push button's OnClick callback function is
  177. //! called.
  178. //!
  179. //! \return Returns 1 if the coordinates are within the extents of the push
  180. //! button and 0 otherwise.
  181. //
  182. //*****************************************************************************
  183. static int
  184. RectangularButtonClick(tWidget *pWidget, unsigned int ulMsg, int lX, int lY)
  185. {
  186. tPushButtonWidget *pPush;
  187. //
  188. // Check the arguments.
  189. //
  190. ASSERT(pWidget);
  191. //
  192. // Convert the generic widget pointer into a push button widget pointer.
  193. //
  194. pPush = (tPushButtonWidget *)pWidget;
  195. //
  196. // See if this is a pointer up message.
  197. //
  198. if(ulMsg == WIDGET_MSG_PTR_UP)
  199. {
  200. //
  201. // Indicate that this push button is no longer pressed.
  202. //
  203. pPush->ulStyle &= ~(PB_STYLE_PRESSED);
  204. //
  205. // If filling is enabled for this push button, or if an image is being
  206. // used and a pressed button image is provided, then redraw the push
  207. // button to show it in its non-pressed state.
  208. //
  209. if((pPush->ulStyle & PB_STYLE_FILL) ||
  210. ((pPush->ulStyle & PB_STYLE_IMG) && pPush->pucPressImage))
  211. {
  212. RectangularButtonPaint(pWidget);
  213. }
  214. //
  215. // If the pointer is still within the button bounds, and it is a
  216. // release notify button, call the notification function here.
  217. //
  218. if(GrRectContainsPoint(&pWidget->sPosition, lX, lY) &&
  219. (pPush->ulStyle & PB_STYLE_RELEASE_NOTIFY) && pPush->pfnOnClick)
  220. {
  221. pPush->pfnOnClick(pWidget);
  222. }
  223. }
  224. //
  225. // See if the given coordinates are within the extents of the push button.
  226. //
  227. if(GrRectContainsPoint(&pWidget->sPosition, lX, lY))
  228. {
  229. //
  230. // See if this is a pointer down message.
  231. //
  232. if(ulMsg == WIDGET_MSG_PTR_DOWN)
  233. {
  234. //
  235. // Indicate that this push button is pressed.
  236. //
  237. pPush->ulStyle |= PB_STYLE_PRESSED;
  238. //
  239. // If filling is enabled for this push button, or if an image is
  240. // being used and a pressed button image is provided, then redraw
  241. // the push button to show it in its pressed state.
  242. //
  243. if((pPush->ulStyle & PB_STYLE_FILL) ||
  244. ((pPush->ulStyle & PB_STYLE_IMG) && pPush->pucPressImage))
  245. {
  246. RectangularButtonPaint(pWidget);
  247. }
  248. }
  249. //
  250. // See if there is an OnClick callback for this widget.
  251. //
  252. if(pPush->pfnOnClick)
  253. {
  254. //
  255. // If the pointer was just pressed then call the callback.
  256. //
  257. if((ulMsg == WIDGET_MSG_PTR_DOWN) &&
  258. !(pPush->ulStyle & PB_STYLE_RELEASE_NOTIFY))
  259. {
  260. pPush->pfnOnClick(pWidget);
  261. }
  262. //
  263. // See if auto-repeat is enabled for this widget.
  264. //
  265. if(pPush->ulStyle & PB_STYLE_AUTO_REPEAT)
  266. {
  267. //
  268. // If the pointer was just pressed, reset the auto-repeat
  269. // count.
  270. //
  271. if(ulMsg == WIDGET_MSG_PTR_DOWN)
  272. {
  273. pPush->ulAutoRepeatCount = 0;
  274. }
  275. //
  276. // See if the pointer was moved.
  277. //
  278. else if(ulMsg == WIDGET_MSG_PTR_MOVE)
  279. {
  280. //
  281. // Increment the auto-repeat count.
  282. //
  283. pPush->ulAutoRepeatCount++;
  284. //
  285. // If the auto-repeat count exceeds the auto-repeat delay,
  286. // and it is a multiple of the auto-repeat rate, then
  287. // call the callback.
  288. //
  289. if((pPush->ulAutoRepeatCount >=
  290. pPush->usAutoRepeatDelay) &&
  291. (((pPush->ulAutoRepeatCount -
  292. pPush->usAutoRepeatDelay) %
  293. pPush->usAutoRepeatRate) == 0))
  294. {
  295. pPush->pfnOnClick(pWidget);
  296. }
  297. }
  298. }
  299. }
  300. //
  301. // These coordinates are within the extents of the push button widget.
  302. //
  303. return(1);
  304. }
  305. //
  306. // These coordinates are not within the extents of the push button widget.
  307. //
  308. return(0);
  309. }
  310. //*****************************************************************************
  311. //
  312. //! Handles messages for a rectangular push button widget.
  313. //!
  314. //! \param pWidget is a pointer to the push button widget.
  315. //! \param ulMsg is the message.
  316. //! \param ulParam1 is the first parameter to the message.
  317. //! \param ulParam2 is the second parameter to the message.
  318. //!
  319. //! This function receives messages intended for this push button widget and
  320. //! processes them accordingly. The processing of the message varies based on
  321. //! the message in question.
  322. //!
  323. //! Unrecognized messages are handled by calling WidgetDefaultMsgProc().
  324. //!
  325. //! \return Returns a value appropriate to the supplied message.
  326. //
  327. //*****************************************************************************
  328. int
  329. RectangularButtonMsgProc(tWidget *pWidget, unsigned int ulMsg,
  330. unsigned int ulParam1, unsigned int ulParam2)
  331. {
  332. //
  333. // Check the arguments.
  334. //
  335. ASSERT(pWidget);
  336. //
  337. // Determine which message is being sent.
  338. //
  339. switch(ulMsg)
  340. {
  341. //
  342. // The widget paint request has been sent.
  343. //
  344. case WIDGET_MSG_PAINT:
  345. {
  346. //
  347. // Handle the widget paint request.
  348. //
  349. RectangularButtonPaint(pWidget);
  350. //
  351. // Return one to indicate that the message was successfully
  352. // processed.
  353. //
  354. return(1);
  355. }
  356. //
  357. // One of the pointer requests has been sent.
  358. //
  359. case WIDGET_MSG_PTR_DOWN:
  360. case WIDGET_MSG_PTR_MOVE:
  361. case WIDGET_MSG_PTR_UP:
  362. {
  363. //
  364. // Handle the pointer request, returning the appropriate value.
  365. //
  366. return(RectangularButtonClick(pWidget, ulMsg, ulParam1, ulParam2));
  367. }
  368. //
  369. // An unknown request has been sent.
  370. //
  371. default:
  372. {
  373. //
  374. // Let the default message handler process this message.
  375. //
  376. return(WidgetDefaultMsgProc(pWidget, ulMsg, ulParam1, ulParam2));
  377. }
  378. }
  379. }
  380. //*****************************************************************************
  381. //
  382. //! Initializes a rectangular push button widget.
  383. //!
  384. //! \param pWidget is a pointer to the push button widget to initialize.
  385. //! \param pDisplay is a pointer to the display on which to draw the push
  386. //! button.
  387. //! \param lX is the X coordinate of the upper left corner of the push button.
  388. //! \param lY is the Y coordinate of the upper left corner of the push button.
  389. //! \param lWidth is the width of the push button.
  390. //! \param lHeight is the height of the push button.
  391. //!
  392. //! This function initializes the provided push button widget so that it will
  393. //! be a rectangular push button.
  394. //!
  395. //! \return None.
  396. //
  397. //*****************************************************************************
  398. void
  399. RectangularButtonInit(tPushButtonWidget *pWidget, const tDisplay *pDisplay,
  400. int lX, int lY, int lWidth, int lHeight)
  401. {
  402. unsigned int ulIdx;
  403. //
  404. // Check the arguments.
  405. //
  406. ASSERT(pWidget);
  407. ASSERT(pDisplay);
  408. //
  409. // Clear out the widget structure.
  410. //
  411. for(ulIdx = 0; ulIdx < sizeof(tPushButtonWidget); ulIdx += 4)
  412. {
  413. ((unsigned int *)pWidget)[ulIdx / 4] = 0;
  414. }
  415. //
  416. // Set the size of the push button widget structure.
  417. //
  418. pWidget->sBase.lSize = sizeof(tPushButtonWidget);
  419. //
  420. // Mark this widget as fully disconnected.
  421. //
  422. pWidget->sBase.pParent = 0;
  423. pWidget->sBase.pNext = 0;
  424. pWidget->sBase.pChild = 0;
  425. //
  426. // Save the display pointer.
  427. //
  428. pWidget->sBase.pDisplay = pDisplay;
  429. //
  430. // Set the extents of this rectangular push button.
  431. //
  432. pWidget->sBase.sPosition.sXMin = lX;
  433. pWidget->sBase.sPosition.sYMin = lY;
  434. pWidget->sBase.sPosition.sXMax = lX + lWidth - 1;
  435. pWidget->sBase.sPosition.sYMax = lY + lHeight - 1;
  436. //
  437. // Use the rectangular push button message handler to process messages to
  438. // this push button.
  439. //
  440. pWidget->sBase.pfnMsgProc = RectangularButtonMsgProc;
  441. }
  442. //*****************************************************************************
  443. //
  444. //! Draws a circular push button.
  445. //!
  446. //! \param pWidget is a pointer to the push button widget to be drawn.
  447. //!
  448. //! This function draws a circular push button on the display. This is called
  449. //! in response to a \b #WIDGET_MSG_PAINT message.
  450. //!
  451. //! \return None.
  452. //
  453. //*****************************************************************************
  454. static void
  455. CircularButtonPaint(tWidget *pWidget)
  456. {
  457. const unsigned char *pucImage;
  458. tPushButtonWidget *pPush;
  459. tContext sCtx;
  460. int lX, lY, lR;
  461. //
  462. // Check the arguments.
  463. //
  464. ASSERT(pWidget);
  465. //
  466. // Convert the generic widget pointer into a push button widget pointer.
  467. //
  468. pPush = (tPushButtonWidget *)pWidget;
  469. //
  470. // Initialize a drawing context.
  471. //
  472. GrContextInit(&sCtx, pWidget->pDisplay);
  473. //
  474. // Initialize the clipping region based on the extents of this circular
  475. // push button.
  476. //
  477. GrContextClipRegionSet(&sCtx, &(pWidget->sPosition));
  478. //
  479. // Get the radius of the circular push button, along with the X and Y
  480. // coordinates for its center.
  481. //
  482. lR = (pWidget->sPosition.sXMax - pWidget->sPosition.sXMin + 1) / 2;
  483. lX = pWidget->sPosition.sXMin + lR;
  484. lY = pWidget->sPosition.sYMin + lR;
  485. //
  486. // See if the push button fill style is selected.
  487. //
  488. if(pPush->ulStyle & PB_STYLE_FILL)
  489. {
  490. //
  491. // Fill the push button with the fill color.
  492. //
  493. GrContextForegroundSet(&sCtx, ((pPush->ulStyle & PB_STYLE_PRESSED) ?
  494. pPush->ulPressFillColor :
  495. pPush->ulFillColor));
  496. GrCircleFill(&sCtx, lX, lY, lR);
  497. }
  498. //
  499. // See if the push button outline style is selected.
  500. //
  501. if(pPush->ulStyle & PB_STYLE_OUTLINE)
  502. {
  503. //
  504. // Outline the push button with the outline color.
  505. //
  506. GrContextForegroundSet(&sCtx, pPush->ulOutlineColor);
  507. GrCircleDraw(&sCtx, lX, lY, lR);
  508. }
  509. //
  510. // See if the push button text or image style is selected.
  511. //
  512. if(pPush->ulStyle & (PB_STYLE_TEXT | PB_STYLE_IMG))
  513. {
  514. //
  515. // If the push button outline style is selected then shrink the
  516. // clipping region by one pixel on each side so that the outline is not
  517. // overwritten by the text or image.
  518. //
  519. if(pPush->ulStyle & PB_STYLE_OUTLINE)
  520. {
  521. sCtx.sClipRegion.sXMin++;
  522. sCtx.sClipRegion.sYMin++;
  523. sCtx.sClipRegion.sXMax--;
  524. sCtx.sClipRegion.sYMax--;
  525. }
  526. //
  527. // See if the push button image style is selected.
  528. //
  529. if(pPush->ulStyle & PB_STYLE_IMG)
  530. {
  531. //
  532. // Set the foreground and background colors to use for 1 BPP
  533. // images.
  534. //
  535. GrContextForegroundSet(&sCtx, pPush->ulTextColor);
  536. GrContextBackgroundSet(&sCtx,
  537. ((pPush->ulStyle & PB_STYLE_PRESSED) ?
  538. pPush->ulPressFillColor :
  539. pPush->ulFillColor));
  540. //
  541. // Get the image to be drawn.
  542. //
  543. pucImage = (((pPush->ulStyle & PB_STYLE_PRESSED) &&
  544. pPush->pucPressImage) ?
  545. pPush->pucPressImage : pPush->pucImage);
  546. //
  547. // Draw the image centered in the push button.
  548. //
  549. GrImageDraw(&sCtx, pucImage, lX - (GrImageWidthGet(pucImage) / 2),
  550. lY - (GrImageHeightGet(pucImage) / 2));
  551. }
  552. //
  553. // See if the push button text style is selected.
  554. //
  555. if(pPush->ulStyle & PB_STYLE_TEXT)
  556. {
  557. //
  558. // Draw the text centered in the middle of the push button.
  559. //
  560. GrContextFontSet(&sCtx, pPush->pFont);
  561. GrContextForegroundSet(&sCtx, pPush->ulTextColor);
  562. GrContextBackgroundSet(&sCtx,
  563. ((pPush->ulStyle & PB_STYLE_PRESSED) ?
  564. pPush->ulPressFillColor :
  565. pPush->ulFillColor));
  566. GrStringDrawCentered(&sCtx, pPush->pcText, -1, lX, lY,
  567. pPush->ulStyle & PB_STYLE_TEXT_OPAQUE);
  568. }
  569. }
  570. }
  571. //*****************************************************************************
  572. //
  573. //! Handles pointer events for a circular push button.
  574. //!
  575. //! \param pWidget is a pointer to the push button widget.
  576. //! \param ulMsg is the pointer event message.
  577. //! \param lX is the X coordinate of the pointer event.
  578. //! \param lY is the Y coordinate of the pointer event.
  579. //!
  580. //! This function processes pointer event messages for a circular push button.
  581. //! This is called in response to a \b #WIDGET_MSG_PTR_DOWN,
  582. //! \b #WIDGET_MSG_PTR_MOVE, and \b #WIDGET_MSG_PTR_UP messages.
  583. //!
  584. //! If the \b #WIDGET_MSG_PTR_UP message is received with a position within the
  585. //! extents of the push button, the push button's OnClick callback function is
  586. //! called.
  587. //!
  588. //! \return Returns 1 if the coordinates are within the extents of the push
  589. //! button and 0 otherwise.
  590. //
  591. //*****************************************************************************
  592. static int
  593. CircularButtonClick(tWidget *pWidget, unsigned int ulMsg, int lX, int lY)
  594. {
  595. tPushButtonWidget *pPush;
  596. int lXc, lYc, lR;
  597. //
  598. // Check the arguments.
  599. //
  600. ASSERT(pWidget);
  601. //
  602. // Convert the generic widget pointer into a push button widget pointer.
  603. //
  604. pPush = (tPushButtonWidget *)pWidget;
  605. //
  606. // See if this is a pointer up message.
  607. //
  608. if(ulMsg == WIDGET_MSG_PTR_UP)
  609. {
  610. //
  611. // Indicate that this push button is no longer pressed.
  612. //
  613. pPush->ulStyle &= ~(PB_STYLE_PRESSED);
  614. //
  615. // If filling is enabled for this push button, or if an image is being
  616. // used and a pressed button image is provided, then redraw the push
  617. // button to show it in its non-pressed state.
  618. //
  619. if((pPush->ulStyle & PB_STYLE_FILL) ||
  620. ((pPush->ulStyle & PB_STYLE_IMG) && pPush->pucPressImage))
  621. {
  622. CircularButtonPaint(pWidget);
  623. }
  624. }
  625. //
  626. // Get the radius of the circular push button, along with the X and Y
  627. // coordinates for its center.
  628. //
  629. lR = (pWidget->sPosition.sXMax - pWidget->sPosition.sXMin + 1) / 2;
  630. lXc = pWidget->sPosition.sXMin + lR;
  631. lYc = pWidget->sPosition.sYMin + lR;
  632. //
  633. // See if the given coordinates are within the radius of the push button.
  634. //
  635. if((((lX - lXc) * (lX - lXc)) + ((lY - lYc) * (lY - lYc))) <= (lR * lR))
  636. {
  637. //
  638. // See if this is a pointer down message.
  639. //
  640. if(ulMsg == WIDGET_MSG_PTR_DOWN)
  641. {
  642. //
  643. // Indicate that this push button is pressed.
  644. //
  645. pPush->ulStyle |= PB_STYLE_PRESSED;
  646. //
  647. // If filling is enabled for this push button, or if an image is
  648. // being used and a pressed button image is provided, then redraw
  649. // the push button to show it in its pressed state.
  650. //
  651. if((pPush->ulStyle & PB_STYLE_FILL) ||
  652. ((pPush->ulStyle & PB_STYLE_IMG) && pPush->pucPressImage))
  653. {
  654. CircularButtonPaint(pWidget);
  655. }
  656. }
  657. //
  658. // See if there is an OnClick callback for this widget.
  659. //
  660. if(pPush->pfnOnClick)
  661. {
  662. //
  663. // If the pointer was just pressed or if the pointer was released
  664. // and this button is set for release notification then call the
  665. // callback.
  666. //
  667. if(((ulMsg == WIDGET_MSG_PTR_DOWN) &&
  668. !(pPush->ulStyle & PB_STYLE_RELEASE_NOTIFY)) ||
  669. ((ulMsg == WIDGET_MSG_PTR_UP) &&
  670. (pPush->ulStyle & PB_STYLE_RELEASE_NOTIFY)))
  671. {
  672. pPush->pfnOnClick(pWidget);
  673. }
  674. //
  675. // See if auto-repeat is enabled for this widget.
  676. //
  677. if(pPush->ulStyle & PB_STYLE_AUTO_REPEAT)
  678. {
  679. //
  680. // If the pointer was just pressed, reset the auto-repeat
  681. // count.
  682. //
  683. if(ulMsg == WIDGET_MSG_PTR_DOWN)
  684. {
  685. pPush->ulAutoRepeatCount = 0;
  686. }
  687. //
  688. // See if the pointer was moved.
  689. //
  690. else if(ulMsg == WIDGET_MSG_PTR_MOVE)
  691. {
  692. //
  693. // Increment the auto-repeat count.
  694. //
  695. pPush->ulAutoRepeatCount++;
  696. //
  697. // If the auto-repeat count exceeds the auto-repeat delay,
  698. // and it is a multiple of the auto-repeat rate, then
  699. // call the callback.
  700. //
  701. if((pPush->ulAutoRepeatCount >=
  702. pPush->usAutoRepeatDelay) &&
  703. (((pPush->ulAutoRepeatCount -
  704. pPush->usAutoRepeatDelay) %
  705. pPush->usAutoRepeatRate) == 0))
  706. {
  707. pPush->pfnOnClick(pWidget);
  708. }
  709. }
  710. }
  711. }
  712. //
  713. // These coordinates are within the extents of the push button widget.
  714. //
  715. return(1);
  716. }
  717. //
  718. // These coordinates are not within the extents of the push button widget.
  719. //
  720. return(0);
  721. }
  722. //*****************************************************************************
  723. //
  724. //! Handles messages for a circular push button widget.
  725. //!
  726. //! \param pWidget is a pointer to the push button widget.
  727. //! \param ulMsg is the message.
  728. //! \param ulParam1 is the first parameter to the message.
  729. //! \param ulParam2 is the second parameter to the message.
  730. //!
  731. //! This function receives messages intended for this push button widget and
  732. //! processes them accordingly. The processing of the message varies based on
  733. //! the message in question.
  734. //!
  735. //! Unrecognized messages are handled by calling WidgetDefaultMsgProc().
  736. //!
  737. //! \return Returns a value appropriate to the supplied message.
  738. //
  739. //*****************************************************************************
  740. int
  741. CircularButtonMsgProc(tWidget *pWidget, unsigned int ulMsg,
  742. unsigned int ulParam1, unsigned int ulParam2)
  743. {
  744. //
  745. // Check the arguments.
  746. //
  747. ASSERT(pWidget);
  748. //
  749. // Determine which message is being sent.
  750. //
  751. switch(ulMsg)
  752. {
  753. //
  754. // The widget paint request has been sent.
  755. //
  756. case WIDGET_MSG_PAINT:
  757. {
  758. //
  759. // Handle the widget paint request.
  760. //
  761. CircularButtonPaint(pWidget);
  762. //
  763. // Return one to indicate that the message was successfully
  764. // processed.
  765. //
  766. return(1);
  767. }
  768. //
  769. // One of the pointer requests has been sent.
  770. //
  771. case WIDGET_MSG_PTR_DOWN:
  772. case WIDGET_MSG_PTR_MOVE:
  773. case WIDGET_MSG_PTR_UP:
  774. {
  775. //
  776. // Handle the pointer request, returning the appropriate value.
  777. //
  778. return(CircularButtonClick(pWidget, ulMsg, ulParam1, ulParam2));
  779. }
  780. //
  781. // An unknown request has been sent.
  782. //
  783. default:
  784. {
  785. //
  786. // Let the default message handler process this message.
  787. //
  788. return(WidgetDefaultMsgProc(pWidget, ulMsg, ulParam1, ulParam2));
  789. }
  790. }
  791. }
  792. //*****************************************************************************
  793. //
  794. //! Initializes a circular push button widget.
  795. //!
  796. //! \param pWidget is a pointer to the push button widget to initialize.
  797. //! \param pDisplay is a pointer to the display on which to draw the push
  798. //! button.
  799. //! \param lX is the X coordinate of the upper left corner of the push button.
  800. //! \param lY is the Y coordinate of the upper left corner of the push button.
  801. //! \param lR is the radius of the push button.
  802. //!
  803. //! This function initializes the provided push button widget so that it will
  804. //! be a circular push button.
  805. //!
  806. //! \return None.
  807. //
  808. //*****************************************************************************
  809. void
  810. CircularButtonInit(tPushButtonWidget *pWidget, const tDisplay *pDisplay,
  811. int lX, int lY, int lR)
  812. {
  813. unsigned int ulIdx;
  814. //
  815. // Check the arguments.
  816. //
  817. ASSERT(pWidget);
  818. ASSERT(pDisplay);
  819. //
  820. // Clear out the widget structure.
  821. //
  822. for(ulIdx = 0; ulIdx < sizeof(tPushButtonWidget); ulIdx += 4)
  823. {
  824. ((unsigned int *)pWidget)[ulIdx / 4] = 0;
  825. }
  826. //
  827. // Set the size of the push button widget structure.
  828. //
  829. pWidget->sBase.lSize = sizeof(tPushButtonWidget);
  830. //
  831. // Mark this widget as fully disconnected.
  832. //
  833. pWidget->sBase.pParent = 0;
  834. pWidget->sBase.pNext = 0;
  835. pWidget->sBase.pChild = 0;
  836. //
  837. // Save the display pointer.
  838. //
  839. pWidget->sBase.pDisplay = pDisplay;
  840. //
  841. // Set the extents of this circular push button.
  842. //
  843. pWidget->sBase.sPosition.sXMin = lX - lR;
  844. pWidget->sBase.sPosition.sYMin = lY - lR;
  845. pWidget->sBase.sPosition.sXMax = lX + lR;
  846. pWidget->sBase.sPosition.sYMax = lY + lR;
  847. //
  848. // Use the circular push button message handler to processes messages to
  849. // this push button.
  850. //
  851. pWidget->sBase.pfnMsgProc = CircularButtonMsgProc;
  852. }
  853. //*****************************************************************************
  854. //
  855. // Close the Doxygen group.
  856. //! @}
  857. //
  858. //*****************************************************************************