/home/jonas/tidevel/adt/Advanced Dialogs/source/Dialog.c

00001 /*
00002         Advanved Dialogs v1.05
00003         Copyright (C) 2005-2007 Jonas Gehring
00004 
00005         Advanced Dialogs is free software; you can redistribute it and/or modify
00006         it under the terms of the GNU Lesser General Public License as published by
00007         the Free Software Foundation; either version 2 of the License, or
00008         (at your option) any later version.
00009 
00010         Advanced Dialogs is distributed in the hope that it will be useful,
00011         but WITHOUT ANY WARRANTY; without even the implied warranty of
00012         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013         GNU Lesser General Public License for more details.
00014 
00015         You should have received a copy of the GNU Lesser General Public License
00016         along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017 */
00018 
00019 
00020 // C Source File
00021 // Created 23.11.2005; 03:58:13
00022 
00023 
00024 #include <extgraph.h>                                                   // ExtGraph by TI-Chess Team
00025 
00026 #include "AdvDialogs.h"                                                 // This should be obvious ;)
00027 #include "Internal.h"                                                   // This header should not be included in programs using Advanced Dialogs
00028 
00029 
00030 // Temporary screen buffers
00031 void *tscr = NULL;
00032 
00033 // Counters
00034 uchar tabcounter;
00035 short elcounter;
00036 
00037 // CheckBox indicators
00038 BOOL AD_CHECKED[6][6];
00039 
00040 // Button text
00041 const char *bttext[4] = {"OK", "ESC", "YES", "NO"};
00042 
00043 // These pseudo-constants make sure the dialog is centered                                            
00044 // on a TI92+/V200 display as well                                                                    
00045 #define CENTER_XL(x) ((LCD_WIDTH-x)/2)                                                                
00046 #define CENTER_YT(y) ((LCD_HEIGHT-y)/2)                                                               
00047 #define CENTER_XR(x) ((LCD_WIDTH+x)/2)                                                                
00048 #define CENTER_YB(y) ((LCD_HEIGHT+y)/2)
00049 
00050 // Button for a dialog
00051 const unsigned short gbutton[18] =
00052 {
00053          0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002
00054         ,0x7FFE,0x0003,0x7FFF,0x7FFF,0x7FFF,0x7FFF,0x7FFF,0x7FFF
00055         ,0x7FFF,0x7FFF
00056 };
00057 
00058 
00059 
00060 // Creates and allocates space for a new dialog
00061 ADVDIALOG *AdvDlgNew(short width, short height, const char *title, BOOL savescreen)
00062 {
00063         uchar i, s;
00064         ADVDIALOG *_dialog = malloc(sizeof(ADVDIALOG));
00065         
00066         if (_dialog == NULL)
00067         {
00068                 return NULL;
00069         }
00070 
00071         memset(_dialog, 0x00, sizeof(ADVDIALOG));
00072                 
00073         // Set position vars
00074         _dialog->left_x = CENTER_XL(width);
00075         _dialog->top_y = CENTER_YT(height);
00076         _dialog->right_x = CENTER_XR(width);
00077         _dialog->bottom_y = CENTER_YB(height);
00078                 
00079         // Set all elements to AD_NONE
00080         for (i = 4; i--; )
00081         {
00082                 for (s = 6; s--; )
00083                 {
00084                         _dialog->tabs[i].elements[s].element = AD_NONE;
00085                 }
00086                 _dialog->tabs[i].numelements = 6;
00087         }
00088         
00089         // Set the title
00090         strcpy(_dialog->title, title);
00091         
00092         // Check if screen should be saved
00093         _dialog->savescreen = savescreen;
00094         
00095         return _dialog;
00096 }
00097 
00098 
00099 // Frees a pointer for a dialog 
00100 void AdvDlgFree(ADVDIALOG *dialog)
00101 {
00102         short i, j;
00103         
00104         // Free possible bitmaps
00105         for (i = 6; i--; )
00106         {
00107                 for (j = dialog->tabs[i].numbitmaps; j--; )
00108                 {
00109                         FreeBitmap(dialog->tabs[i].bitmaps[j]);
00110                 }
00111         }
00112         
00113         free(dialog);
00114 }
00115 
00116 
00117 // Adds a Tab to a dialog
00118 void AdvDlgAddTab(ADVDIALOG *dialog, uchar tab, const char *title)
00119 {
00120         strcpy(dialog->tabs[tab].title, title);
00121         
00122         dialog->numtabs++;
00123 }
00124 
00125 
00126 // Adds a button to a Dialog
00127 void AdvDlgAddButton(ADVDIALOG *dialog, uchar pos, uchar button)
00128 {
00129         dialog->buttons[pos] = button;
00130 }
00131 
00132 
00133 // Adds a Text element to a dialog
00134 void AdvDlgAddText(ADVDIALOG *dialog, uchar tab, uchar line, 
00135                                    const char *text, uchar attr, uchar color)
00136 {
00137         dialog->tabs[tab].elements[line].element = AD_TEXT;
00138         strcpy(dialog->tabs[tab].elements[line].text, text);
00139         dialog->tabs[tab].elements[line].flag = attr;
00140         dialog->tabs[tab].elements[line].color = color;
00141 } 
00142 
00143 
00144 // Adds an Input element to a dialog
00145 void AdvDlgAddInputBox(ADVDIALOG *dialog, uchar tab, uchar line, const char *text,
00146                                     char *buffer, short maxsize, uchar mode, uchar color)
00147 {
00148         dialog->tabs[tab].elements[line].element = AD_INPUT;
00149         strcpy(dialog->tabs[tab].elements[line].text, text);
00150         dialog->tabs[tab].elements[line].inputbuffer = buffer;
00151         dialog->tabs[tab].elements[line].inputsize = maxsize;
00152         dialog->tabs[tab].elements[line].flag = mode;
00153         dialog->tabs[tab].elements[line].color = color;
00154 }
00155 
00156 
00157 // Adds a Checkbox element to a dialog
00158 void AdvDlgAddCheckBox(ADVDIALOG *dialog, uchar tab, uchar line, const char *text,
00159                                        BOOL checked, uchar color)
00160 {
00161         dialog->tabs[tab].elements[line].element = AD_CHECKBOX;
00162         strcpy(dialog->tabs[tab].elements[line].text, text);
00163         dialog->tabs[tab].elements[line].flag = checked;
00164         dialog->tabs[tab].elements[line].color = color;
00165 }
00166 
00167 
00168 // Adds a DropDown menu to a dialog
00169 void AdvDlgAddDropDown(ADVDIALOG *dialog, uchar tab, uchar line, const char *text,
00170                                            const char **itemlist, short numitems, short *selected, uchar color)
00171 {
00172         dialog->tabs[tab].elements[line].element = AD_DROPDOWN;
00173         strcpy(dialog->tabs[tab].elements[line].text, text);
00174         dialog->tabs[tab].elements[line].itemlist = itemlist;
00175         dialog->tabs[tab].elements[line].flag = numitems;
00176         dialog->tabs[tab].elements[line].selected = selected;   
00177         dialog->tabs[tab].elements[line].color = color; 
00178 }
00179  
00180 
00181 // Adds a Bitmap to a dialog
00182 char AdvDlgAddBitmap(ADVDIALOG *dialog, uchar tab, short x, short y, ADVBITMAP *bitmap)
00183 {
00184         if (dialog->tabs[tab].numbitmaps > 5)
00185         {
00186                 return -1;
00187         }
00188         dialog->tabs[tab].bitmaps[dialog->tabs[tab].numbitmaps] = bitmap;
00189         bitmap->x = x;
00190         bitmap->y = y;
00191         return ++dialog->tabs[tab].numbitmaps;
00192 }
00193 
00194 
00195 // Draws the basic things (window, buttons, title)
00196 void AdvDlgDrawBasic(ADVDIALOG *dialog)
00197 {
00198         // Draw Dialog window
00199         GrayDrawRect(dialog->left_x, dialog->top_y, dialog->right_x, dialog->bottom_y, COLOR_LIGHTGRAY, RECT_FILLED);
00200         GrayDrawRect(dialog->left_x, dialog->top_y, dialog->right_x, dialog->top_y+7, COLOR_BLACK, RECT_FILLED);
00201         GrayFastDrawLine(dialog->left_x+1, dialog->bottom_y+1, dialog->right_x+1, dialog->bottom_y+1, COLOR_BLACK);
00202         GrayFastDrawLine(dialog->right_x+1, dialog->top_y+1, dialog->right_x+1, dialog->bottom_y+1, COLOR_BLACK);
00203 
00204         // Add title
00205         GrayDrawStrExt(0, dialog->top_y+1, dialog->title, A_XOR | A_CENTERED, F_4x6);
00206         
00207         // Add buttons
00208         if (dialog->buttons[0] != B_NONE)
00209         {
00210                 // Using sprites for buttons is faster and saves a few bytes!
00211                 GraySprite16_RPLC_R(dialog->left_x+10, dialog->bottom_y-9, 9, &gbutton[0], &gbutton[9],
00212                                                         GRAYPLANES);
00213                 GrayDrawStrExt(dialog->left_x+17-2*strlen(bttext[dialog->buttons[0]-1]), dialog->bottom_y-7, bttext[dialog->buttons[0]-1], A_NORMAL, F_4x6);
00214         }
00215         if (dialog->buttons[1] != B_NONE)
00216         {
00217                 GraySprite16_RPLC_R(dialog->right_x-24, dialog->bottom_y-9, 9, &gbutton[0], &gbutton[9],
00218                                                         GRAYPLANES);
00219                 GrayDrawStrExt(dialog->right_x-17-2*strlen(bttext[dialog->buttons[1]-1]), dialog->bottom_y-7, bttext[dialog->buttons[1]-1], A_NORMAL,  F_4x6);
00220         }
00221 }
00222 
00223 
00224 // Draws a tab of a Dialog
00225 void AdvDlgDrawTab(ADVDIALOG *dialog, uchar tab)
00226 {
00227         uchar i;
00228         BOOL drawastab = FALSE;
00229 
00230         AdvDlgDrawBasic(dialog);
00231         
00232         if (dialog->numtabs)
00233         {
00234                 drawastab = TRUE;
00235         }
00236         
00237         if (drawastab)
00238         {
00239                 GrayDrawRect(dialog->left_x+2, dialog->top_y+17, dialog->right_x-2, dialog->bottom_y-11, COLOR_BLACK, RECT_EMPTY);
00240                 GrayFastDrawLine(dialog->left_x+2, dialog->top_y+17, dialog->left_x+2, dialog->bottom_y-11, COLOR_WHITE);
00241                 GrayFastDrawLine(dialog->left_x+2, dialog->top_y+17, dialog->right_x-3, dialog->top_y+17, COLOR_WHITE);
00242                 
00243                 short xp = 0;
00244                 
00245                 for (i = 0; i < dialog->numtabs; i++)
00246                 {                       
00247                         short drwidth = DrawStrWidth(dialog->tabs[i].title, F_4x6);
00248                         
00249                         // Active tab
00250                         if (i == tab)
00251                         {
00252                                 GrayDrawRect(dialog->left_x+3+xp, dialog->top_y+9, dialog->left_x+5+xp+drwidth,
00253                                                          dialog->top_y+17, COLOR_WHITE, RECT_EMPTY);
00254                                 GrayFastDrawLine(dialog->left_x+4+xp, dialog->top_y+17, dialog->left_x+4+xp+drwidth, dialog->top_y+17, COLOR_LIGHTGRAY);
00255                                 GrayFastDrawLine(dialog->left_x+5+xp+drwidth, dialog->top_y+9, dialog->left_x+5+xp+drwidth, dialog->top_y+16, COLOR_BLACK);
00256                                 GrayDrawStrExt(dialog->left_x+4+xp, dialog->top_y+11, dialog->tabs[i].title, A_NORMAL, F_4x6);
00257                         }
00258                         // Inactive tab
00259                         else
00260                         {
00261                                 GrayDrawRect(dialog->left_x+3+xp, dialog->top_y+10, dialog->left_x+6+xp+drwidth,
00262                                                          dialog->top_y+17, COLOR_WHITE, RECT_EMPTY);
00263                                 GrayDrawStrExt(dialog->left_x+4+xp, dialog->top_y+11, dialog->tabs[i].title, A_NORMAL, F_4x6);
00264                         }
00265                         
00266                         xp += DrawStrWidth(dialog->tabs[i].title, F_4x6)+3;
00267                 }
00268         }
00269         
00270         for (i = 0; i < dialog->tabs[tab].numelements; i++)
00271         {
00272                 switch (dialog->tabs[tab].elements[i].element)
00273                 {
00274                         // Text
00275                         case AD_TEXT:
00276                         {
00277                                 short tx = dialog->left_x+2+(drawastab*3);
00278                         
00279                                 if (dialog->tabs[tab].elements[i].flag == TXT_ALIGNRIGHT)
00280                                 {
00281                                         tx = dialog->right_x-5-(drawastab*3) - DrawStrWidth(dialog->tabs[tab].elements[i].text, F_4x6);
00282                                 }
00283                         
00284                                 GrayDrawColorString(tx, dialog->top_y+9+2+(drawastab*10)+(i*8), dialog->tabs[tab].elements[i].text, 
00285                                                                 dialog->tabs[tab].elements[i].color, dialog->tabs[tab].elements[i].flag);
00286                         }
00287                         break;
00288                 
00289                         // InputBox
00290                         case AD_INPUT:
00291                         {
00292                                 GrayDrawColorString(dialog->left_x+2+(drawastab*3), dialog->top_y+9+2+(drawastab*10)+8*i, dialog->tabs[tab].elements[i].text, 
00293                                                                         dialog->tabs[tab].elements[i].color, TXT_STANDARD);
00294                                 GrayDrawRect(dialog->left_x+2+(drawastab*3)+DrawStrWidth(dialog->tabs[tab].elements[i].text, F_4x6) + 4, dialog->top_y+8+2+(drawastab*10)+(i*8), dialog->right_x-5-(drawastab*3), dialog->top_y+14+2+(drawastab*10)+(i*8), COLOR_WHITE, RECT_FILLED);   
00295                                 
00296                                 short show = 0;
00297                                 
00298                                 while ((unsigned short)DrawStrWidth(&dialog->tabs[tab].elements[i].inputbuffer[show], F_4x6)
00299                                            > (dialog->right_x-10-(drawastab*3) - 4 -(dialog->left_x+5+DrawStrWidth(dialog->tabs[tab].elements[i].text, F_4x6))))
00300                                 {
00301                                         show++;
00302                                 }
00303                                                 
00304                                 GrayDrawStrExt(dialog->left_x+3+(drawastab*2)+DrawStrWidth(dialog->tabs[tab].elements[i].text, F_4x6) + 4, dialog->top_y+9+2+(drawastab*10)+(i*8), &dialog->tabs[tab].elements[i].inputbuffer[show], A_NORMAL, F_4x6);
00305                         }
00306                         break;
00307                         
00308                         // CheckBox
00309                         case AD_CHECKBOX:
00310                         {
00311                                 GrayDrawColorString(dialog->left_x+2+(drawastab*3), dialog->top_y+9+2+(drawastab*10)+8*i, dialog->tabs[tab].elements[i].text, 
00312                                                                 dialog->tabs[tab].elements[i].color, TXT_STANDARD);
00313                                 GrayDrawRect(dialog->right_x-11-(drawastab*3), dialog->top_y+8+2+(drawastab*10)+(i*8), dialog->right_x-5-(drawastab*3), dialog->top_y+14+2+(drawastab*10)+(i*8), COLOR_WHITE, RECT_FILLED);     
00314                                 
00315                                 if (dialog->tabs[tab].elements[i].flag)
00316                                 {
00317                                         GrayFastDrawLine(dialog->right_x-11-(drawastab*3), dialog->top_y+11+2+(drawastab*10)+(i*8), dialog->right_x-9-(drawastab*3), dialog->top_y+14+2+(drawastab*10)+(i*8), COLOR_BLACK);     
00318                                         GrayFastDrawLine(dialog->right_x-9-(drawastab*3), dialog->top_y+14+2+(drawastab*10)+(i*8), dialog->right_x-5-(drawastab*3), dialog->top_y+8+2+(drawastab*10)+(i*8), COLOR_BLACK);       
00319                                 }
00320                         }
00321                         break;
00322                 
00323                         // DropDown
00324                         case AD_DROPDOWN:
00325                         {
00326                                 char tstr[60];
00327                         
00328                                 GrayDrawColorString(dialog->left_x+2+(drawastab*3), dialog->top_y+9+2+(drawastab*10)+8*i, dialog->tabs[tab].elements[i].text, 
00329                                                                         dialog->tabs[tab].elements[i].color, TXT_STANDARD);
00330                                 GrayDrawRect(dialog->left_x+10+(drawastab*3)+DrawStrWidth(dialog->tabs[tab].elements[i].text, F_4x6), dialog->top_y+8+2+(drawastab*10)+(i*8), dialog->right_x-5-(drawastab*3), dialog->top_y+14+2+(drawastab*10)+(i*8), COLOR_WHITE, RECT_FILLED);      
00331                                 GrayDrawChar(dialog->right_x-10-(drawastab*3), dialog->top_y+9+2+(drawastab*10)+8*i, 22, A_XOR);
00332 
00333                                 strncpy(tstr, dialog->tabs[tab].elements[i].itemlist[*dialog->tabs[tab].elements[i].selected], 59);
00334                         
00335                                 while ((unsigned short)DrawStrWidth(tstr, F_4x6)
00336                                         > ((dialog->right_x-5-(drawastab*3)) - (dialog->left_x+10+(drawastab*3)+DrawStrWidth(dialog->tabs[tab].elements[i].text, F_4x6)) - 5))
00337                                 {
00338                                         tstr[strlen(tstr)-1] = 0;
00339                                 }
00340 
00341                                 GrayDrawStrExt(dialog->left_x+10+(drawastab*3)+DrawStrWidth(dialog->tabs[tab].elements[i].text, F_4x6), dialog->top_y+9+2+(drawastab*10)+(i*8), tstr, A_XOR, F_4x6);
00342                         }
00343                         break;
00344                 
00345                         default: break;
00346                 }
00347         }
00348         
00349         // Check for possible bitmap
00350         for (i = 0; i < dialog->tabs[tab].numbitmaps; i++)
00351         {
00352                 DrawBitmap(dialog, dialog->tabs[tab].bitmaps[i]);
00353         }
00354 }
00355 
00356 
00357 // Executes a dialog
00358 BOOL AdvDlgDo(ADVDIALOG *dialog, INT_HANDLER tempint1)
00359 {
00360         short key;
00361         uchar i, ccheck = 0;
00362         BOOL returnvalue = TRUE;
00363         BOOL nexttab;
00364         void *kbq = kbd_queue();
00365         
00366         dialog->inthandler = tempint1;
00367         
00368         // Temporarily reinstall the original AUTO_INT_1
00369         if (dialog->inthandler != DUMMY_HANDLER)
00370         {
00371                 GraySetInt1Handler(dialog->inthandler);
00372         }
00373         
00374         // Save LCD contents if neccessary
00375         if (dialog->savescreen) 
00376         {
00377                 SaveScreen();
00378         }
00379         
00380         // Set system font to small
00381         char oldfont = FontSetSys(F_4x6);
00382                 
00383         // Reset counters
00384         tabcounter = elcounter = 0;
00385 
00386         // Loop through the tabs
00387         do 
00388         {
00389                 BOOL interactive = FALSE;
00390                 nexttab = FALSE;
00391                 elcounter = ccheck = 0;
00392                         
00393                 AdvDlgDrawTab(dialog, tabcounter);
00394 
00395                 // Loop through the interactive elements
00396                 do 
00397                 {
00398                         interactive = dialog->tabs[tabcounter].elements[elcounter].element > AD_TEXT;
00399                         
00400                         // Execute element interaction function
00401                         switch (dialog->tabs[tabcounter].elements[elcounter].element)
00402                         {
00403                                 case AD_INPUT:
00404                                         elcounter = AdvDlgInputBox(dialog, tabcounter, elcounter);
00405                                         break;
00406                                 
00407                                 case AD_CHECKBOX:
00408                                         elcounter = AdvDlgCheckBox(dialog, tabcounter, elcounter);
00409                                         break;
00410                                         
00411                                 case AD_DROPDOWN:
00412                                         elcounter = AdvDlgDropDown(dialog, tabcounter, elcounter);
00413                                         break;
00414                                         
00415                                 default:        // AD_NONE and AD_TEXT
00416                                         ++elcounter;
00417                                         break;
00418                         }
00419                         
00420                         // Activate next tab
00421                         if (elcounter == NEXTTAB)
00422                         {
00423                                 nexttab = TRUE;
00424                                 tabcounter = (tabcounter+1) % dialog->numtabs;
00425                                 break;
00426                         }               
00427                         
00428                         // The user has pressed ESC
00429                         if (elcounter < 0)
00430                         {
00431                                 returnvalue = FALSE;
00432                                 break;
00433                         }
00434                         
00435                 } while (elcounter < dialog->tabs[tabcounter].numelements);
00436                                                 
00437                 // Save Checkboxes
00438                 for (i = 0; i < dialog->tabs[tabcounter].numelements; i++)
00439                 {
00440                         if (dialog->tabs[tabcounter].elements[i].element == AD_CHECKBOX)
00441                         {
00442                                 AD_CHECKED[tabcounter][ccheck++] = dialog->tabs[tabcounter].elements[i].flag;
00443                         }
00444                 }
00445 
00446                 // If there was no interactive element (just text or nothing)
00447                 if (!interactive)
00448                 {
00449                         // Wait for keypress
00450                         do
00451                         {
00452                                 GetKey(kbq, &key);
00453                                 
00454                                 if (key == KEY_ESC)
00455                                 {
00456                                         returnvalue = FALSE;
00457                                         break;
00458                                 }
00459                                 else if (key == KEY_ENTER)
00460                                 {
00461                                         returnvalue = TRUE;
00462                                         break;
00463                                 }                               
00464                                 // Switch tabs
00465                                 else if (key == KEY_APPS)
00466                                 {
00467                                         tabcounter = (tabcounter+1) % dialog->numtabs;
00468                                         nexttab = TRUE;
00469                                         break;
00470                                 }               
00471                         } while (TRUE); 
00472                 }
00473         } while (nexttab);
00474         
00475         // Set AUTO_INT_1 to dummy again
00476         if (dialog->inthandler != DUMMY_HANDLER)
00477         {
00478                 GraySetInt1Handler(DUMMY_HANDLER);
00479         }
00480 
00481         RestoreScreen();
00482         
00483         // Restore previous font
00484         FontSetSys(oldfont);
00485         
00486         return returnvalue;
00487 }
00488 
00489 

Generated on Thu Oct 4 19:42:03 2007 for Advanced Dialogs by  doxygen 1.5.1