Line No. | Rev | Author | Line |
---|---|---|---|
1 | 32 | kaklik | /***************************************************************************** |
2 | * Module for Microchip Graphics Library |
||
3 | * Grid control |
||
4 | ***************************************************************************** |
||
5 | * FileName: Grid.c |
||
6 | * Dependencies: string.h, Graphics.h |
||
7 | * Processor: PIC24F, PIC24H, dsPIC, PIC32 |
||
8 | * Compiler: MPLAB C30 V3.00, MPLAB C32 |
||
9 | * Linker: MPLAB LINK30, MPLAB LINK32 |
||
10 | * Company: Microchip Technology Incorporated |
||
11 | * |
||
12 | * Software License Agreement |
||
13 | * |
||
14 | * Copyright © 2008 Microchip Technology Inc. All rights reserved. |
||
15 | * Microchip licenses to you the right to use, modify, copy and distribute |
||
16 | * Software only when embedded on a Microchip microcontroller or digital |
||
17 | * signal controller, which is integrated into your product or third party |
||
18 | * product (pursuant to the sublicense terms in the accompanying license |
||
19 | * agreement). |
||
20 | * |
||
21 | * You should refer to the license agreement accompanying this Software |
||
22 | * for additional information regarding your rights and obligations. |
||
23 | * |
||
24 | * SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY |
||
25 | * KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY |
||
26 | * OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR |
||
27 | * PURPOSE. IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR |
||
28 | * OBLIGATED UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, |
||
29 | * BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT |
||
30 | * DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, |
||
31 | * INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, |
||
32 | * COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY |
||
33 | * CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), |
||
34 | * OR OTHER SIMILAR COSTS. |
||
35 | * |
||
36 | * Author Date Comment |
||
37 | *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||
38 | * Kim Otten 02/29/08 ... |
||
39 | * PAT 04/16/10 Added Grid Item as text. |
||
40 | *****************************************************************************/ |
||
41 | |||
42 | /* |
||
43 | Grid Object |
||
44 | |||
45 | TODO: Currently the grid does not support scroll bars. It must fit on the screen. |
||
46 | |||
47 | */ |
||
48 | #include <string.h> |
||
49 | #include "Graphics\Graphics.h" |
||
50 | |||
51 | #ifdef USE_GRID |
||
52 | #define CELL_AT(c, r) ((c * pGrid->numRows) + r) |
||
53 | |||
54 | /* */ |
||
55 | |||
56 | GRID *GridCreate |
||
57 | ( |
||
58 | WORD ID, |
||
59 | SHORT left, |
||
60 | SHORT top, |
||
61 | SHORT right, |
||
62 | SHORT bottom, |
||
63 | WORD state, |
||
64 | SHORT numColumns, |
||
65 | SHORT numRows, |
||
66 | SHORT cellWidth, |
||
67 | SHORT cellHeight, |
||
68 | GOL_SCHEME *pScheme |
||
69 | ) |
||
70 | { |
||
71 | GRID *pGrid = NULL; |
||
72 | |||
73 | if((pGrid = (GRID *)GFX_malloc(sizeof(GRID))) == NULL) |
||
74 | { |
||
75 | return (NULL); |
||
76 | } |
||
77 | |||
78 | if((pGrid->gridObjects = GFX_malloc(sizeof(GRIDITEM) * numColumns * numRows)) == NULL) |
||
79 | { |
||
80 | GFX_free(pGrid); |
||
81 | return (NULL); |
||
82 | } |
||
83 | |||
84 | // Initialize grid items to default. |
||
85 | memset(pGrid->gridObjects, 0, sizeof(GRIDITEM) * numColumns * numRows); |
||
86 | |||
87 | // Initialize grid |
||
88 | pGrid->hdr.ID = ID; |
||
89 | pGrid->hdr.pNxtObj = NULL; |
||
90 | pGrid->hdr.type = OBJ_GRID; |
||
91 | pGrid->hdr.state = state; |
||
92 | pGrid->hdr.left = left; |
||
93 | pGrid->hdr.top = top; |
||
94 | pGrid->hdr.right = right; |
||
95 | pGrid->hdr.bottom = bottom; |
||
96 | pGrid->numColumns = numColumns; |
||
97 | pGrid->numRows = numRows; |
||
98 | pGrid->cellWidth = cellWidth; |
||
99 | pGrid->cellHeight = cellHeight; |
||
100 | pGrid->focusX = 0; |
||
101 | pGrid->focusY = 0; |
||
102 | |||
103 | // Set the color scheme to be used |
||
104 | if(pScheme == NULL) |
||
105 | { |
||
106 | pGrid->hdr.pGolScheme = _pDefaultGolScheme; |
||
107 | } |
||
108 | else |
||
109 | { |
||
110 | pGrid->hdr.pGolScheme = (GOL_SCHEME *)pScheme; |
||
111 | } |
||
112 | |||
113 | GOLAddObject((OBJ_HEADER *)pGrid); |
||
114 | |||
115 | return (pGrid); |
||
116 | } |
||
117 | |||
118 | #define CELL_LEFT (1 + pGrid->hdr.left + (i * (pGrid->cellWidth + 1))) |
||
119 | #define CELL_TOP (1 + pGrid->hdr.top + (j * (pGrid->cellHeight + 1))) |
||
120 | #define CELL_RIGHT (CELL_LEFT + pGrid->cellWidth - 1) |
||
121 | #define CELL_BOTTOM (CELL_TOP + pGrid->cellHeight - 1) |
||
122 | #define BITMAP_SCALE 1 |
||
123 | |||
124 | /* */ |
||
125 | |||
126 | WORD GridDraw(GRID *pGrid) |
||
127 | { |
||
128 | SHORT i; |
||
129 | SHORT j; |
||
130 | SHORT xText, yText; |
||
131 | |||
132 | |||
133 | if |
||
134 | ( |
||
135 | (pGrid->hdr.state & GRID_DRAW_ITEMS) || |
||
136 | (pGrid->hdr.state & GRID_DRAW_ALL) || |
||
137 | (pGrid->hdr.state & GRID_SHOW_FOCUS) |
||
138 | ) |
||
139 | { |
||
140 | if(pGrid->hdr.state & GRID_DRAW_ALL) |
||
141 | { |
||
142 | |||
143 | // Clear the entire region. |
||
144 | SetColor(pGrid->hdr.pGolScheme->CommonBkColor); |
||
145 | while(!Bar(pGrid->hdr.left, pGrid->hdr.top, pGrid->hdr.right, pGrid->hdr.bottom)); |
||
146 | |||
147 | // Draw the grid lines |
||
148 | if(pGrid->hdr.state & (GRID_SHOW_LINES | GRID_SHOW_BORDER_ONLY | GRID_SHOW_SEPARATORS_ONLY)) |
||
149 | { |
||
150 | SetLineType(SOLID_LINE); |
||
151 | SetColor(pGrid->hdr.pGolScheme->EmbossLtColor); |
||
152 | |||
153 | // Draw the outside of the box |
||
154 | // TODO This should have some 3D effects added with GOL_EMBOSS_SIZE |
||
155 | if(pGrid->hdr.state & (GRID_SHOW_LINES | GRID_SHOW_BORDER_ONLY)) |
||
156 | { |
||
157 | while(!Line(pGrid->hdr.left, pGrid->hdr.top, pGrid->hdr.right, pGrid->hdr.top)); |
||
158 | LineTo(_cursorX, pGrid->hdr.bottom); |
||
159 | LineTo(pGrid->hdr.left, _cursorY); |
||
160 | LineTo(pGrid->hdr.left, pGrid->hdr.top); |
||
161 | } |
||
162 | |||
163 | // Draw the lines between each cell |
||
164 | if(pGrid->hdr.state & (GRID_SHOW_LINES | GRID_SHOW_SEPARATORS_ONLY)) |
||
165 | { |
||
166 | for(i = 1; i < pGrid->numColumns; i++) |
||
167 | { |
||
168 | while |
||
169 | ( |
||
170 | !Line |
||
171 | ( |
||
172 | pGrid->hdr.left + i * (pGrid->cellWidth + 1), |
||
173 | pGrid->hdr.top, |
||
174 | pGrid->hdr.left + i * (pGrid->cellWidth + 1), |
||
175 | pGrid->hdr.top + pGrid->numRows * (pGrid->cellHeight + 1) |
||
176 | ) |
||
177 | ); |
||
178 | } |
||
179 | |||
180 | for(i = 1; i < pGrid->numRows; i++) |
||
181 | { |
||
182 | while |
||
183 | ( |
||
184 | !Line |
||
185 | ( |
||
186 | pGrid->hdr.left, |
||
187 | pGrid->hdr.top + i * (pGrid->cellHeight + 1), |
||
188 | pGrid->hdr.right, |
||
189 | pGrid->hdr.top + i * (pGrid->cellHeight + 1) |
||
190 | ) |
||
191 | ); |
||
192 | } |
||
193 | } |
||
194 | } |
||
195 | } |
||
196 | |||
197 | for(i = 0; i < pGrid->numColumns; i++) |
||
198 | { |
||
199 | for(j = 0; j < pGrid->numRows; j++) |
||
200 | { |
||
201 | if |
||
202 | ( |
||
203 | (pGrid->hdr.state & GRID_DRAW_ALL) || |
||
204 | ( |
||
205 | (pGrid->hdr.state & GRID_DRAW_ITEMS) && |
||
206 | (pGrid->gridObjects[CELL_AT(i, j)].status & GRIDITEM_DRAW) |
||
207 | ) || |
||
208 | ((pGrid->hdr.state & GRID_SHOW_FOCUS) && (i == pGrid->focusX) && (j == pGrid->focusY)) |
||
209 | ) |
||
210 | { |
||
211 | |||
212 | // Clear the cell |
||
213 | SetColor(pGrid->hdr.pGolScheme->CommonBkColor); |
||
214 | while(!Bar(CELL_LEFT, CELL_TOP, CELL_RIGHT, CELL_BOTTOM)); |
||
215 | |||
216 | // Draw the cell |
||
217 | if((pGrid->gridObjects[CELL_AT(i, j)].status & GRID_TYPE_MASK) == GRIDITEM_IS_BITMAP) |
||
218 | { |
||
219 | |||
220 | // Draw the bitmap |
||
221 | if(pGrid->gridObjects[CELL_AT(i, j)].data) |
||
222 | { |
||
223 | while(!PutImage(CELL_LEFT, CELL_TOP, pGrid->gridObjects[CELL_AT(i, j)].data, BITMAP_SCALE)); |
||
224 | } |
||
225 | } |
||
226 | else |
||
227 | { |
||
228 | |||
229 | // Draw the text |
||
230 | if(pGrid->gridObjects[CELL_AT(i, j)].data) |
||
231 | { |
||
232 | SetFont(pGrid->hdr.pGolScheme->pFont); |
||
233 | SetColor(pGrid->hdr.pGolScheme->TextColor0); |
||
234 | |||
235 | if(GetState(pGrid, GRIDITEM_TEXTRIGHT)) |
||
236 | { |
||
237 | xText = CELL_LEFT+pGrid->cellWidth-GetTextWidth(pGrid->gridObjects[CELL_AT(i, j)].data,pGrid->hdr.pGolScheme->pFont); |
||
238 | } |
||
239 | else if(GetState(pGrid, GRIDITEM_TEXTLEFT)) |
||
240 | { |
||
241 | xText = CELL_LEFT; |
||
242 | } |
||
243 | else |
||
244 | { |
||
245 | xText = CELL_LEFT+(pGrid->cellWidth>>1)-(GetTextWidth(pGrid->gridObjects[CELL_AT(i, j)].data,pGrid->hdr.pGolScheme->pFont)>>1); |
||
246 | } |
||
247 | if(GetState(pGrid, GRIDITEM_TEXTBOTTOM)) |
||
248 | { |
||
249 | yText = CELL_TOP+pGrid->cellHeight-GetTextHeight(pGrid->hdr.pGolScheme->pFont); |
||
250 | } |
||
251 | else if(GetState(pGrid, GRIDITEM_TEXTTOP)) |
||
252 | { |
||
253 | yText = CELL_TOP; |
||
254 | } |
||
255 | else |
||
256 | { |
||
257 | yText = CELL_TOP+(pGrid->cellHeight>>1)-(GetTextHeight(pGrid->hdr.pGolScheme->pFont)>>1); |
||
258 | } |
||
259 | |||
260 | while(!OutTextXY( xText, yText, pGrid->gridObjects[CELL_AT(i, j)].data)); |
||
261 | } |
||
262 | } |
||
263 | |||
264 | // Draw the focus if applicable. |
||
265 | if((pGrid->hdr.state & GRID_SHOW_FOCUS) && (i == pGrid->focusX) && (j == pGrid->focusY)) |
||
266 | { |
||
267 | SetColor(pGrid->hdr.pGolScheme->EmbossLtColor); |
||
268 | SetLineType(DOTTED_LINE); |
||
269 | SetLineThickness(NORMAL_LINE); |
||
270 | while(!Rectangle(CELL_LEFT, CELL_TOP, CELL_RIGHT, CELL_BOTTOM)); |
||
271 | } |
||
272 | |||
273 | // If the cell is selected, indicate it. |
||
274 | if(pGrid->gridObjects[CELL_AT(pGrid->focusX, pGrid->focusY)].status & GRIDITEM_SELECTED) |
||
275 | { |
||
276 | SetColor(pGrid->hdr.pGolScheme->EmbossLtColor); |
||
277 | SetLineType(SOLID_LINE); |
||
278 | if(pGrid->hdr.state & GRID_SHOW_LINES) |
||
279 | { |
||
280 | SetLineThickness(THICK_LINE); |
||
281 | } |
||
282 | else |
||
283 | { |
||
284 | SetLineThickness(NORMAL_LINE); |
||
285 | } |
||
286 | |||
287 | while(!Rectangle(CELL_LEFT - 1, CELL_TOP - 1, CELL_RIGHT + 1, CELL_BOTTOM + 1)); |
||
288 | } |
||
289 | |||
290 | GridClearCellState(pGrid, i, j, GRIDITEM_DRAW); |
||
291 | } |
||
292 | } |
||
293 | } |
||
294 | |||
295 | //pGrid->state &= ~(GRID_DRAW_ITEMS || GRID_DRAW_ALL || GRID_SHOW_FOCUS); |
||
296 | pGrid->hdr.state &= ~(GRID_DRAW_ITEMS || GRID_DRAW_ALL); |
||
297 | |||
298 | // Set line state |
||
299 | SetLineType(SOLID_LINE); |
||
300 | } |
||
301 | |||
302 | return (1); |
||
303 | } |
||
304 | |||
305 | /* */ |
||
306 | void GridFreeItems(GRID *pGrid) |
||
307 | { |
||
308 | if(pGrid && pGrid->gridObjects) |
||
309 | { |
||
310 | GFX_free(pGrid->gridObjects); |
||
311 | pGrid->gridObjects = NULL; // Just in case... |
||
312 | } |
||
313 | } |
||
314 | |||
315 | /* */ |
||
316 | WORD GridSetCell(GRID *pGrid, SHORT column, SHORT row, WORD state, void *data) |
||
317 | { |
||
318 | if((column >= pGrid->numColumns) || (row >= pGrid->numRows)) |
||
319 | { |
||
320 | return (GRID_OUT_OF_BOUNDS); |
||
321 | } |
||
322 | |||
323 | pGrid->gridObjects[CELL_AT(column, row)].data = data; |
||
324 | pGrid->gridObjects[CELL_AT(column, row)].status = state; // This overwrites GRIDITEM_SELECTED |
||
325 | return (GRID_SUCCESS); |
||
326 | } |
||
327 | |||
328 | /* */ |
||
329 | void GridClearCellState(GRID *pGrid, SHORT column, SHORT row, WORD state) |
||
330 | { |
||
331 | if((column >= pGrid->numColumns) || (row >= pGrid->numRows)) |
||
332 | { |
||
333 | return; |
||
334 | } |
||
335 | |||
336 | pGrid->gridObjects[CELL_AT(column, row)].status &= ~state; |
||
337 | |||
338 | return; |
||
339 | } |
||
340 | |||
341 | /* */ |
||
342 | void GridSetFocus(GRID *pGrid, SHORT column, SHORT row) |
||
343 | { |
||
344 | if((column >= pGrid->numColumns) || (row >= pGrid->numRows)) |
||
345 | { |
||
346 | return; |
||
347 | } |
||
348 | |||
349 | pGrid->focusX = column; |
||
350 | pGrid->focusY = row; |
||
351 | } |
||
352 | |||
353 | /* */ |
||
354 | void GridSetCellState(GRID *pGrid, SHORT column, SHORT row, WORD state) |
||
355 | { |
||
356 | if((column >= pGrid->numColumns) || (row >= pGrid->numRows)) |
||
357 | { |
||
358 | return; |
||
359 | } |
||
360 | |||
361 | pGrid->gridObjects[CELL_AT(column, row)].status |= state; |
||
362 | |||
363 | return; |
||
364 | } |
||
365 | |||
366 | /* */ |
||
367 | void *GridGetCell(GRID *pGrid, SHORT column, SHORT row, WORD *cellType) |
||
368 | { |
||
369 | if((column >= pGrid->numColumns) || (row >= pGrid->numRows)) |
||
370 | { |
||
371 | return (NULL); |
||
372 | } |
||
373 | |||
374 | *cellType = pGrid->gridObjects[CELL_AT(column, row)].status & GRID_TYPE_MASK; |
||
375 | |||
376 | return (pGrid->gridObjects[CELL_AT(column, row)].data); |
||
377 | } |
||
378 | |||
379 | /* */ |
||
380 | void GridMsgDefault(WORD translatedMsg, GRID *pGrid, GOL_MSG *pMsg) |
||
381 | { |
||
382 | switch(translatedMsg) |
||
383 | { |
||
384 | case GRID_MSG_ITEM_SELECTED: |
||
385 | |||
386 | // Currently, only a single item can be selected. This can be expanded later, |
||
387 | // when touchscreen support is enhanced. |
||
388 | pGrid->gridObjects[CELL_AT(pGrid->focusX, pGrid->focusY)].status ^= GRIDITEM_SELECTED; |
||
389 | |||
390 | // SetState( pGrid, GRID_SHOW_FOCUS | GRID_DRAW_ITEMS ); |
||
391 | SetState(pGrid, GRID_DRAW_ITEMS); |
||
392 | break; |
||
393 | |||
394 | case GRID_MSG_UP: |
||
395 | if(pGrid->focusY > 0) |
||
396 | { |
||
397 | pGrid->gridObjects[CELL_AT(pGrid->focusX, pGrid->focusY)].status |= GRIDITEM_DRAW; |
||
398 | pGrid->focusY--; |
||
399 | |||
400 | // SetState( pGrid, GRID_SHOW_FOCUS | GRID_DRAW_ITEMS ); |
||
401 | SetState(pGrid, GRID_DRAW_ITEMS); |
||
402 | } |
||
403 | |||
404 | break; |
||
405 | |||
406 | case GRID_MSG_DOWN: |
||
407 | if(pGrid->focusY < (pGrid->numRows - 1)) |
||
408 | { |
||
409 | pGrid->gridObjects[CELL_AT(pGrid->focusX, pGrid->focusY)].status |= GRIDITEM_DRAW; |
||
410 | pGrid->focusY++; |
||
411 | |||
412 | // SetState( pGrid, GRID_SHOW_FOCUS | GRID_DRAW_ITEMS ); |
||
413 | SetState(pGrid, GRID_DRAW_ITEMS); |
||
414 | } |
||
415 | |||
416 | break; |
||
417 | |||
418 | case GRID_MSG_LEFT: |
||
419 | if(pGrid->focusX > 0) |
||
420 | { |
||
421 | pGrid->gridObjects[CELL_AT(pGrid->focusX, pGrid->focusY)].status |= GRIDITEM_DRAW; |
||
422 | pGrid->focusX--; |
||
423 | |||
424 | // SetState( pGrid, GRID_SHOW_FOCUS | GRID_DRAW_ITEMS ); |
||
425 | SetState(pGrid, GRID_DRAW_ITEMS); |
||
426 | } |
||
427 | |||
428 | break; |
||
429 | |||
430 | case GRID_MSG_RIGHT: |
||
431 | if(pGrid->focusX < (pGrid->numColumns - 1)) |
||
432 | { |
||
433 | pGrid->gridObjects[CELL_AT(pGrid->focusX, pGrid->focusY)].status |= GRIDITEM_DRAW; |
||
434 | pGrid->focusX++; |
||
435 | |||
436 | // SetState( pGrid, GRID_SHOW_FOCUS | GRID_DRAW_ITEMS ); |
||
437 | SetState(pGrid, GRID_DRAW_ITEMS); |
||
438 | } |
||
439 | |||
440 | break; |
||
441 | } |
||
442 | } |
||
443 | |||
444 | /* */ |
||
445 | WORD GridTranslateMsg(GRID *pGrid, GOL_MSG *pMsg) |
||
446 | { |
||
447 | |||
448 | // Evaluate if the message is for the check box |
||
449 | // Check if disabled first |
||
450 | if(GetState(pGrid, GRID_DISABLED)) |
||
451 | { |
||
452 | return (OBJ_MSG_INVALID); |
||
453 | } |
||
454 | |||
455 | #ifdef USE_TOUCHSCREEN |
||
456 | if(pMsg->type == TYPE_TOUCHSCREEN) |
||
457 | { |
||
458 | |||
459 | // Check if it falls in the check box borders |
||
460 | if |
||
461 | ( |
||
462 | (pGrid->hdr.left <= pMsg->param1) && |
||
463 | (pGrid->hdr.right >= pMsg->param1) && |
||
464 | (pGrid->hdr.top <= pMsg->param2) && |
||
465 | (pGrid->hdr.bottom >= pMsg->param2) |
||
466 | ) |
||
467 | { |
||
468 | return (GRID_MSG_TOUCHED); |
||
469 | } |
||
470 | |||
471 | return (OBJ_MSG_INVALID); |
||
472 | } |
||
473 | |||
474 | #endif |
||
475 | #ifdef USE_KEYBOARD |
||
476 | if((pMsg->uiEvent == EVENT_KEYSCAN) && (pMsg->type == TYPE_KEYBOARD) && (pMsg->param1 == pGrid->hdr.ID)) |
||
477 | { |
||
478 | if((pMsg->param2 == SCAN_SPACE_PRESSED) || (pMsg->param2 == SCAN_CR_PRESSED)) |
||
479 | { |
||
480 | return (GRID_MSG_ITEM_SELECTED); |
||
481 | } |
||
482 | else if(pMsg->param2 == SCAN_LEFT_PRESSED) |
||
483 | { |
||
484 | return (GRID_MSG_LEFT); |
||
485 | } |
||
486 | else if(pMsg->param2 == SCAN_RIGHT_PRESSED) |
||
487 | { |
||
488 | return (GRID_MSG_RIGHT); |
||
489 | } |
||
490 | else if(pMsg->param2 == SCAN_UP_PRESSED) |
||
491 | { |
||
492 | return (GRID_MSG_UP); |
||
493 | } |
||
494 | else if(pMsg->param2 == SCAN_DOWN_PRESSED) |
||
495 | { |
||
496 | return (GRID_MSG_DOWN); |
||
497 | } |
||
498 | } |
||
499 | |||
500 | return (OBJ_MSG_INVALID); |
||
501 | #endif |
||
502 | return (OBJ_MSG_INVALID); |
||
503 | } |
||
504 | |||
505 | #endif // USE_GRID |
Powered by WebSVN v2.8.3