?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 32

Line No. Rev Author Line
1 32 kaklik /*****************************************************************************
2 * Module for Microchip Graphics Library
3 * GOL Layer
4 * Button
5 *****************************************************************************
6 * FileName: Button.c
7 * Dependencies: Button.h
8 * Processor: PIC24F, PIC24H, dsPIC, PIC32
9 * Compiler: MPLAB C30 Version 3.00, C32
10 * Linker: MPLAB LINK30, LINK32
11 * Company: Microchip Technology Incorporated
12 *
13 * Software License Agreement
14 *
15 * Copyright © 2008 Microchip Technology Inc. All rights reserved.
16 * Microchip licenses to you the right to use, modify, copy and distribute
17 * Software only when embedded on a Microchip microcontroller or digital
18 * signal controller, which is integrated into your product or third party
19 * product (pursuant to the sublicense terms in the accompanying license
20 * agreement).
21 *
22 * You should refer to the license agreement accompanying this Software
23 * for additional information regarding your rights and obligations.
24 *
25 * SOFTWARE AND DOCUMENTATION ARE PROVIDED “AS IS” WITHOUT WARRANTY OF ANY
26 * KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY
27 * OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR
28 * PURPOSE. IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR
29 * OBLIGATED UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION,
30 * BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT
31 * DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL,
32 * INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA,
33 * COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY
34 * CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
35 * OR OTHER SIMILAR COSTS.
36 *
37 * Author Date Comment
38 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
39 * PAT 11/12/07 Version 1.0 release
40 * PAT 06/26/09 Added message ID BTN_MSG_STILLPRESSED
41 * to signify that a continuous touch on
42 * the button through touch screen.
43 * PAT 06/29/09 Added multi-line text support on buttons
44 * must set USE_BUTTON_MULTI_LINE in
45 * GraphicsConfig.h file.
46 *****************************************************************************/
47 #include "Graphics\Graphics.h"
48  
49 #if defined(USE_BUTTON) || defined(USE_BUTTON_MULTI_LINE)
50  
51 /*********************************************************************
52 * Function: BUTTON *BtnCreate(WORD ID, SHORT left, SHORT top, SHORT right,
53 * SHORT bottom, SHORT radius, void *pBitmap, XCHAR *pText,
54 * GOL_SCHEME *pScheme)
55 *
56 *
57 * Notes: Creates a BUTTON object and adds it to the current active list.
58 * If the creation is successful, the pointer to the created Object
59 * is returned. If not successful, NULL is returned.
60 *
61 ********************************************************************/
62 BUTTON *BtnCreate
63 (
64 WORD ID,
65 SHORT left,
66 SHORT top,
67 SHORT right,
68 SHORT bottom,
69 SHORT radius,
70 WORD state,
71 void *pBitmap,
72 XCHAR *pText,
73 GOL_SCHEME *pScheme
74 )
75 {
76 BUTTON *pB = NULL;
77 pB = (BUTTON *)GFX_malloc(sizeof(BUTTON));
78 if(pB == NULL)
79 return (NULL);
80  
81 pB->hdr.ID = ID; // unique id assigned for referencing
82 pB->hdr.pNxtObj = NULL; // initialize pointer to NULL
83 pB->hdr.type = OBJ_BUTTON; // set object type
84 pB->hdr.left = left; // left position
85 pB->hdr.top = top; // top position
86 pB->hdr.right = right; // right position
87 pB->hdr.bottom = bottom; // bottom position
88 pB->radius = radius; // radius
89 pB->pBitmap = pBitmap; // location of bitmap
90 pB->pText = pText; // location of the text
91 pB->hdr.state = state; // state
92  
93 // Set the color scheme to be used
94 if(pScheme == NULL)
95 pB->hdr.pGolScheme = _pDefaultGolScheme;
96 else
97 pB->hdr.pGolScheme = (GOL_SCHEME *)pScheme;
98  
99 pB->textWidth = 0;
100 pB->textHeight = 0;
101 if(pB->pText != NULL)
102 {
103 BtnSetText(pB, pText);
104 }
105  
106 GOLAddObject((OBJ_HEADER *)pB);
107  
108 #ifdef USE_FOCUS
109 if(GetState(pB, BTN_FOCUSED))
110 GOLSetFocus((OBJ_HEADER *)pB);
111 #endif
112 return (pB);
113 }
114  
115 /*********************************************************************
116 * Function: BtnSetText(BUTTON *pB, XCHAR *pText)
117 *
118 *
119 * Notes: Sets the text used in the button.
120 *
121 ********************************************************************/
122 void BtnSetText(BUTTON *pB, XCHAR *pText)
123 {
124 #ifdef USE_BUTTON_MULTI_LINE
125 int width = 0, chCtr = 0, lineCtr = 1;
126 XCHAR ch, *pParser;
127 #endif
128  
129 pB->pText = pText;
130  
131 #ifdef USE_BUTTON_MULTI_LINE
132  
133 // calculate width and height taking into account the multiple lines of text
134 pParser = pB->pText;
135 ch = *pText;
136  
137 // calculate the width (taken from the longest line)
138 while(1)
139 {
140 if((ch == 0x000A) || (ch == 0x0000))
141 {
142 if(width < GetTextWidth(pParser, pB->hdr.pGolScheme->pFont))
143 {
144 width = GetTextWidth(pParser, pB->hdr.pGolScheme->pFont);
145 }
146  
147 if(ch == 0x000A)
148 {
149 pParser = pText + chCtr + 1;
150 lineCtr++;
151 }
152 else
153 {
154 break;
155 }
156 }
157  
158 chCtr++;
159 ch = *(pText + chCtr);
160 }
161  
162 pB->textWidth = width;
163 pB->textHeight = GetTextHeight(pB->hdr.pGolScheme->pFont) * lineCtr;
164 #else
165 pB->textWidth = GetTextWidth(pText, pB->hdr.pGolScheme->pFont);
166 pB->textHeight = GetTextHeight(pB->hdr.pGolScheme->pFont);
167 #endif // #ifdef USE_BUTTON_MULTI_LINE
168 }
169  
170 /*********************************************************************
171 * Function: BtnMsgDefault(WORD translatedMsg, BUTTON *pB, GOL_MSG* pMsg)
172 *
173 *
174 * Notes: This the default operation to change the state of the button.
175 * Called inside GOLMsg() when GOLMsgCallback() returns a 1.
176 *
177 ********************************************************************/
178 void BtnMsgDefault(WORD translatedMsg, BUTTON *pB, GOL_MSG *pMsg)
179 {
180 #ifdef USE_FOCUS
181 #ifdef USE_TOUCHSCREEN
182 if(pMsg->type == TYPE_TOUCHSCREEN)
183 {
184 if(!GetState(pB, BTN_FOCUSED))
185 {
186 GOLSetFocus((OBJ_HEADER *)pB);
187 }
188 }
189  
190 #endif
191 #endif
192 switch(translatedMsg)
193 {
194 case BTN_MSG_PRESSED:
195 SetState(pB, BTN_PRESSED | BTN_DRAW); // set pressed and redraw
196 break;
197  
198 case BTN_MSG_RELEASED:
199 case BTN_MSG_CANCELPRESS:
200 ClrState(pB, BTN_PRESSED); // reset pressed
201 SetState(pB, BTN_DRAW); // redraw
202 break;
203  
204 default:
205  
206 // catch all for button messages added by users and
207 // behavior defined by users in message callback
208 break;
209 }
210 }
211  
212 /*********************************************************************
213 * Function: WORD BtnTranslateMsg(BUTTON *pB, GOL_MSG *pMsg)
214 *
215 *
216 * Notes: Evaluates the message if the object will be affected by the
217 * message or not.
218 *
219 ********************************************************************/
220 WORD BtnTranslateMsg(BUTTON *pB, GOL_MSG *pMsg)
221 {
222  
223 // Evaluate if the message is for the button
224 // Check if disabled first
225 if(GetState(pB, BTN_DISABLED))
226 return (OBJ_MSG_INVALID);
227  
228 #ifdef USE_TOUCHSCREEN
229 if(pMsg->type == TYPE_TOUCHSCREEN)
230 {
231  
232 // Check if it falls in the button's face
233 if
234 (
235 (pB->hdr.left < pMsg->param1) &&
236 (pB->hdr.right > pMsg->param1) &&
237 (pB->hdr.top < pMsg->param2) &&
238 (pB->hdr.bottom > pMsg->param2)
239 )
240 {
241 if(GetState(pB, BTN_TOGGLE))
242 {
243 if(pMsg->uiEvent == EVENT_RELEASE)
244 {
245 if(GetState(pB, BTN_PRESSED))
246 return (BTN_MSG_RELEASED);
247 else
248 return (BTN_MSG_PRESSED);
249 }
250 }
251 else
252 {
253 if(pMsg->uiEvent == EVENT_RELEASE)
254 return (BTN_MSG_RELEASED);
255 if(pMsg->uiEvent == EVENT_STILLPRESS)
256 {
257 if(GetState(pB, BTN_PRESSED))
258 return (BTN_MSG_STILLPRESSED);
259 }
260  
261 if(!GetState(pB, BTN_PRESSED))
262 return (BTN_MSG_PRESSED);
263 }
264 }
265 else
266 {
267 if(!GetState(pB, BTN_TOGGLE))
268 {
269 if((pMsg->uiEvent == EVENT_MOVE) && (GetState(pB, BTN_PRESSED)))
270 return (BTN_MSG_CANCELPRESS);
271 }
272 }
273  
274 return (OBJ_MSG_INVALID);
275 }
276  
277 #endif
278 #ifdef USE_KEYBOARD
279 if(pMsg->type == TYPE_KEYBOARD)
280 {
281 if(pMsg->param1 == pB->hdr.ID)
282 {
283 if(pMsg->uiEvent == EVENT_KEYSCAN)
284 {
285 if(GetState(pB, BTN_TOGGLE))
286 {
287 if((pMsg->param2 == SCAN_SPACE_RELEASED) || (pMsg->param2 == SCAN_CR_RELEASED))
288 {
289 if(GetState(pB, BTN_PRESSED))
290 return (BTN_MSG_RELEASED);
291 else
292 return (BTN_MSG_PRESSED);
293 }
294 }
295 else
296 {
297 if((pMsg->param2 == SCAN_SPACE_PRESSED) || (pMsg->param2 == SCAN_CR_PRESSED))
298 {
299 return (BTN_MSG_PRESSED);
300 }
301  
302 if((pMsg->param2 == SCAN_SPACE_RELEASED) || (pMsg->param2 == SCAN_CR_RELEASED))
303 {
304 return (BTN_MSG_RELEASED);
305 }
306 }
307  
308 if((pMsg->param2 == SCAN_SPACE_PRESSED) || (pMsg->param2 == SCAN_CRA_PRESSED))
309 {
310 return (BTN_MSG_PRESSED);
311 }
312  
313 if((pMsg->param2 == SCAN_SPACE_RELEASED) || (pMsg->param2 == SCAN_CRA_RELEASED))
314 {
315 return (BTN_MSG_RELEASED);
316 }
317 }
318 }
319  
320 return (OBJ_MSG_INVALID);
321 }
322  
323 #endif
324 return (OBJ_MSG_INVALID);
325 }
326  
327 /*********************************************************************
328 * Function: WORD BtnDraw(BUTTON *pB)
329 *
330 *
331 * Notes: This is the state machine to draw the button.
332 *
333 ********************************************************************/
334 WORD BtnDraw(BUTTON *pB)
335 {
336 typedef enum
337 {
338 REMOVE,
339 BEVEL_DRAW,
340 RNDBUTTON_DRAW,
341 TEXT_DRAW,
342 #ifdef USE_BUTTON_MULTI_LINE
343 CHECK_TEXT_DRAW,
344 #endif
345 TEXT_DRAW_RUN,
346 FOCUS_DRAW,
347 } BTN_DRAW_STATES;
348  
349 static BTN_DRAW_STATES state = REMOVE;
350 static SHORT width, height, radius;
351  
352 #ifdef USE_BUTTON_MULTI_LINE
353 static SHORT charCtr = 0, lineCtr = 0;
354 static XCHAR *pCurLine = NULL;
355 SHORT textWidth;
356 XCHAR ch = 0;
357 #endif
358 WORD faceClr, embossLtClr, embossDkClr, xText, yText;
359  
360 if(IsDeviceBusy())
361 return (0);
362  
363 switch(state)
364 {
365 case REMOVE:
366 if(IsDeviceBusy())
367 return (0);
368  
369 if(GetState(pB, BTN_HIDE))
370 { // Hide the button (remove from screen)
371 SetColor(pB->hdr.pGolScheme->CommonBkColor);
372 if(!Bar(pB->hdr.left, pB->hdr.top, pB->hdr.right, pB->hdr.bottom))
373 {
374 return (0);
375 }
376  
377 return (1);
378 }
379  
380 /* Note: that width and height adjustment considers the following assumptions:
381 1. if circular width = height = radius*2
382 2. if vertical capsule width = radius*2
383 3. if horizontal capsule height = radius*2
384 4. radius must be less than or equal to width if height is greater than width
385 5. radius must be less than or equal to height if width is greater than height
386 6. if button is cornered, radius must be zero
387 */
388 radius = pB->radius; // get radius
389 width = (pB->hdr.right - pB->hdr.left) - (radius * 2); // get width
390 height = (pB->hdr.bottom - pB->hdr.top) - (radius * 2); // get height
391 state = BEVEL_DRAW;
392  
393 case BEVEL_DRAW:
394 if(!GetState(pB, BTN_DISABLED))
395 {
396 if(GetState(pB, BTN_PRESSED))
397 {
398 embossDkClr = pB->hdr.pGolScheme->EmbossLtColor;
399 embossLtClr = pB->hdr.pGolScheme->EmbossDkColor;
400 faceClr = pB->hdr.pGolScheme->Color1;
401 }
402 else
403 {
404 embossLtClr = pB->hdr.pGolScheme->EmbossLtColor;
405 embossDkClr = pB->hdr.pGolScheme->EmbossDkColor;
406 faceClr = pB->hdr.pGolScheme->Color0;
407 }
408 }
409 else
410 {
411 embossLtClr = pB->hdr.pGolScheme->EmbossLtColor;
412 embossDkClr = pB->hdr.pGolScheme->EmbossDkColor;
413 faceClr = pB->hdr.pGolScheme->ColorDisabled;
414 }
415  
416 SetLineThickness(NORMAL_LINE);
417 SetLineType(SOLID_LINE);
418 GOLPanelDraw
419 (
420 pB->hdr.left + radius,
421 pB->hdr.top + radius,
422 pB->hdr.right - radius,
423 pB->hdr.bottom - radius,
424 radius,
425 faceClr,
426 embossLtClr,
427 embossDkClr,
428 pB->pBitmap,
429 GOL_EMBOSS_SIZE
430 );
431 state = RNDBUTTON_DRAW;
432  
433 case RNDBUTTON_DRAW:
434 if (GetState(pB, BTN_TWOTONE))
435 {
436 if(!GOLTwoTonePanelDrawTsk())
437 {
438 return (0);
439 }
440 }
441 else
442 {
443 if(!GOLPanelDrawTsk())
444 {
445 return (0);
446 }
447 }
448  
449 #ifdef USE_BUTTON_MULTI_LINE
450 state = CHECK_TEXT_DRAW;
451 #else
452 state = TEXT_DRAW;
453 #endif
454 #ifdef USE_BUTTON_MULTI_LINE
455  
456 case CHECK_TEXT_DRAW:
457 if(pB->pText != NULL)
458 {
459 if(!GetState(pB, BTN_DISABLED))
460 {
461 if(GetState(pB, BTN_PRESSED))
462 {
463 SetColor(pB->hdr.pGolScheme->TextColor1);
464 }
465 else
466 {
467 SetColor(pB->hdr.pGolScheme->TextColor0);
468 }
469 }
470 else
471 {
472 SetColor(pB->hdr.pGolScheme->TextColorDisabled);
473 }
474  
475 pCurLine = pB->pText;
476 lineCtr = 0;
477 charCtr = 0;
478 state = TEXT_DRAW;
479 }
480 else
481 {
482 state = FOCUS_DRAW;
483 goto rnd_button_draw_focus;
484 }
485  
486 case TEXT_DRAW:
487 button_draw_set_text_position : SetFont(pB->hdr.pGolScheme->pFont);
488 textWidth = GetTextWidth(pCurLine, pB->hdr.pGolScheme->pFont);
489  
490 // check text alignment
491 if(GetState(pB, BTN_TEXTRIGHT))
492 {
493 xText = pB->hdr.right - (textWidth + GOL_EMBOSS_SIZE + 2);
494 }
495 else if(GetState(pB, BTN_TEXTLEFT))
496 {
497 xText = pB->hdr.left + GOL_EMBOSS_SIZE + 2;
498 }
499 else
500 {
501  
502 // centered text in x direction
503 xText = (pB->hdr.left + pB->hdr.right - textWidth) >> 1;
504 }
505  
506 if(GetState(pB, BTN_TEXTTOP))
507 {
508 yText = pB->hdr.top + GOL_EMBOSS_SIZE + (lineCtr * GetTextHeight(pB->hdr.pGolScheme->pFont));
509 }
510 else if(GetState(pB, BTN_TEXTBOTTOM))
511 {
512 yText = pB->hdr.bottom - (GOL_EMBOSS_SIZE + pB->textHeight) + (lineCtr * GetTextHeight(pB->hdr.pGolScheme->pFont));
513 }
514 else
515 {
516  
517 // centered text in y direction
518 yText = ((pB->hdr.bottom + pB->hdr.top - pB->textHeight) >> 1) + (lineCtr * GetTextHeight(pB->hdr.pGolScheme->pFont));
519 }
520  
521 MoveTo(xText, yText);
522 state = TEXT_DRAW_RUN;
523  
524 case TEXT_DRAW_RUN:
525 ch = *(pCurLine + charCtr);
526  
527 // output one character at time until a newline character or a NULL character is sampled
528 while((0x0000 != ch) && (0x000A != ch))
529 {
530 if(!OutChar(ch))
531 return (0); // render the character
532 charCtr++; // update to next character
533 ch = *(pCurLine + charCtr);
534 }
535  
536 // pCurText is updated for the next line
537 if(ch == 0x000A)
538 { // new line character
539 pCurLine = pCurLine + charCtr + 1; // go to first char of next line
540 lineCtr++; // update line counter
541 charCtr = 0; // reset char counter
542 goto button_draw_set_text_position; // continue to next line
543 }
544  
545 // end of text string is reached no more lines to display
546 else
547 {
548 SetClip(CLIP_DISABLE); // remove clipping
549 state = FOCUS_DRAW; // go back to IDLE state
550 }
551  
552 #else
553  
554 case TEXT_DRAW:
555 if(pB->pText != NULL)
556 {
557 if(!GetState(pB, BTN_DISABLED))
558 {
559 if(GetState(pB, BTN_PRESSED))
560 {
561 SetColor(pB->hdr.pGolScheme->TextColor1);
562 }
563 else
564 {
565 SetColor(pB->hdr.pGolScheme->TextColor0);
566 }
567 }
568 else
569 {
570 SetColor(pB->hdr.pGolScheme->TextColorDisabled);
571 }
572  
573 SetFont(pB->hdr.pGolScheme->pFont);
574  
575 // check text alignment
576 if(GetState(pB, BTN_TEXTRIGHT))
577 {
578 xText = pB->hdr.right - (pB->textWidth + GOL_EMBOSS_SIZE + 2);
579 }
580 else if(GetState(pB, BTN_TEXTLEFT))
581 {
582 xText = pB->hdr.left + GOL_EMBOSS_SIZE + 2;
583 }
584 else
585 {
586  
587 // centered text in x direction
588 xText = (pB->hdr.left + pB->hdr.right - pB->textWidth) >> 1;
589 }
590  
591 if(GetState(pB, BTN_TEXTTOP))
592 {
593 yText = pB->hdr.top + GOL_EMBOSS_SIZE + 2;
594 }
595 else if(GetState(pB, BTN_TEXTBOTTOM))
596 {
597 yText = pB->hdr.bottom - (pB->textHeight + GOL_EMBOSS_SIZE);
598 }
599 else
600 {
601  
602 // centered text in y direction
603 yText = (pB->hdr.bottom + pB->hdr.top - pB->textHeight) >> 1;
604 }
605  
606 MoveTo(xText, yText);
607 state = TEXT_DRAW_RUN;
608 }
609 else
610 {
611 state = FOCUS_DRAW;
612 goto rnd_button_draw_focus;
613 }
614  
615 case TEXT_DRAW_RUN:
616 if(!OutText(pB->pText))
617 return (0);
618 state = FOCUS_DRAW;
619 #endif // #ifdef USE_BUTTON_MULTI_LINE
620  
621 case FOCUS_DRAW:
622 rnd_button_draw_focus : if(IsDeviceBusy()) return (0);
623  
624 if(GetState(pB, BTN_FOCUSED))
625 {
626 SetLineType(FOCUS_LINE);
627 if(GetState(pB, BTN_PRESSED))
628 {
629 SetColor(pB->hdr.pGolScheme->TextColor1);
630 }
631 else
632 {
633 SetColor(pB->hdr.pGolScheme->TextColor0);
634 }
635  
636 // check if the object has rounded corners or not
637 if(!pB->radius)
638 {
639 if
640 (
641 !Rectangle
642 (
643 pB->hdr.left + GOL_EMBOSS_SIZE + 2,
644 pB->hdr.top + GOL_EMBOSS_SIZE + 2,
645 pB->hdr.right - GOL_EMBOSS_SIZE - 2,
646 pB->hdr.bottom - GOL_EMBOSS_SIZE - 2
647 )
648 )
649 {
650 return (0);
651 }
652 }
653 else
654 {
655  
656 // original center is still the same, but radius is reduced
657 if
658 (
659 !Bevel
660 (
661 pB->hdr.left + radius,
662 pB->hdr.top + radius,
663 pB->hdr.right - radius,
664 pB->hdr.bottom - radius,
665 radius - 2 - GOL_EMBOSS_SIZE
666 )
667 )
668 {
669 return (0);
670 }
671 }
672  
673 SetLineType(SOLID_LINE);
674 }
675  
676 state = REMOVE;
677 return (1);
678 }
679  
680 return (1);
681 }
682  
683 #endif //#if defined (USE_BUTTON) || defined (USE_BUTTON_MULTI_LINE)
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3