Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

dialog++.c

Go to the documentation of this file.
00001 
00002 /* dialog.c: Lux-based routines to permit easy construction of simple
00003  *           dialog boxes.
00004  *
00005  *           Steve McMillan (Drexel U.), Jan-May 1996.
00006  */
00007 
00008 #include "c_lux.h"
00009 #include "local.h"
00010 
00011 local int mymin(int a, int b)
00012 {
00013     return (a < b ? a : b);
00014 }
00015 
00016 local int mymax(int a, int b)
00017 {
00018     return (a > b ? a : b);
00019 }
00020 
00021 local int count_left_digits(double d)
00022 {
00023     /* How many digits to the left of the decimal point in d? */
00024 
00025     int n = 1;
00026 
00027     if (d < 0) {
00028         d = -d;
00029         n = 2;
00030     }
00031 
00032     while (d > 10.0) {
00033         n++;
00034         d /= 10.0;
00035     }
00036 
00037     return n;
00038 }
00039 
00040 local int format_double_string(double d, int w, char* s)
00041 {
00042     /* Attempt to format the value d into string s, of maximum width w. */
00043 
00044     char* temp;
00045     char fmt[40];
00046     int size;
00047 
00048     size = w;
00049 
00050     /* Try f format first. */
00051 
00052     sprintf(fmt, "%%.%df", mymax(2, w - 1 - count_left_digits(d)));
00053     sprintf(s, fmt, d);
00054 
00055     /* Strip trailing zeros (and the decimal point, if possible). */
00056 
00057     if (strchr(s, '.')) {
00058 
00059         temp = s + strlen(s) - 1;
00060         while (*temp == '0') {
00061             *temp = '\0';
00062             temp--;
00063         }
00064         if (*temp == '.') *temp = '\0';
00065     }
00066 
00067     if (strlen(s) > w) {
00068 
00069         /* Won't fit -- resort to e format. */
00070 
00071         sprintf(fmt, "%%.%de", mymax(2, w - 7));
00072         sprintf(s, fmt, d);
00073 
00074         if (strlen(s) > w) size = strlen(s);
00075 
00076     }
00077 
00078     return size;
00079 }
00080 
00081 local int convert_value(dialog_entry* d, char* s)
00082 {
00083     int i, size;
00084     double dd;
00085     char* temp;
00086 
00087     switch (d->type) {
00088 
00089         case 0: *s = *(d->value);
00090                 size = 1;
00091                 break;
00092 
00093         case 1: i = sprintf(s, "%d", *((int*)(d->value)));
00094                 size = 3;
00095                 if (i > 3 && i <= 8) size = i;
00096                 if (i > 8) size = 8;
00097                 break;
00098 
00099         case 2:
00100         case 3: if (d->type == 2)
00101                     dd = (double)*((float*)(d->value));
00102                 else
00103                     dd = *((double*)(d->value));
00104 
00105                 size = format_double_string(dd, d->width, s);
00106 
00107                 break;
00108 
00109         case 4: size = strlen(d->value);
00110 
00111                 /* Strip leading blanks */
00112                 temp = d->value;
00113                 while(*temp <= ' ' && *temp > '\0') temp++;
00114 
00115                 sprintf(s, "%s", temp);
00116                 break;
00117     }
00118 
00119     if (size < d->width) size = d->width;
00120     return size;
00121 }
00122 
00123 local void set_dialog_item(Window* dialog_win, int i, dialog_entry* d,
00124                            int x1, int x2, int y)
00125 {
00126     /* Translate d into a string representing the value. */
00127 
00128     int size, j;
00129     char temp_buffer[80];
00130 
00131     size = convert_value(d, temp_buffer);
00132 
00133     /* Initialize the appropriate box (twice, just in case...). */
00134 
00135     for (j = 0; j < 2; j++) {
00136 
00137         if (d->type) {
00138             lux_set_item(*dialog_win, i, TEXT_WINDOW, NO_TYPE,
00139                          x1, y, strlen(d->name), d->name);
00140             lux_set_item(*dialog_win, i, INPUT_WINDOW, NO_TYPE,
00141                          x2, y, size, temp_buffer);
00142             
00143         } else {
00144             lux_set_item(*dialog_win, i, TEXT_WINDOW, CHECK_BUTTON,
00145                          x1, y, strlen(d->name), d->name);
00146             lux_set_item(*dialog_win, i, BUTTON_WINDOW, CHECK_BUTTON,
00147                          x2, y, size, temp_buffer);
00148         }
00149 
00150     }
00151 }
00152 
00153 void initialize_dialog(Window* dialog_win,
00154                        int xorigin, int yorigin, char* title,
00155                        int* xsize, int* ysize,
00156                        dialog_entry* list, int n, int split)
00157 {
00158     int l1, h, lchar, l2, xgap, xmid, dy, x1, x2, ymax, y, uchar;
00159 
00160     /* Get maximum name length. */
00161 
00162     int i_max = -1, max_length = -1;
00163     int i_maxb = -1, ll, max_box = -1;
00164 
00165     char temp[40];
00166 
00167     int i, l;
00168     for (i = 0; i < n; i++) {
00169 
00170         if ( (l = strlen(list[i].name)) > max_length) {
00171             max_length = l;
00172             i_max = i;
00173         }
00174 
00175         if ((ll = convert_value(list+i, temp)) > max_box) {
00176             max_box = ll;
00177             i_maxb = i;
00178         }
00179     }
00180 
00181     if (i_max < 0 || max_length < 0 || i_maxb < 0 || max_box < 0) {
00182         fprintf(stderr, "Error in initialize_dialog.\n");
00183         exit(1);
00184     }
00185 
00186     lux_string_dimensions(list[i_max].name, &l1, &h);
00187 
00188     lux_string_dimensions("0", &lchar, &h);
00189     l2 = lchar;
00190     if (max_box > 0) l2 *= max_box;
00191     l2 += lchar;                        /* Take box itself into account */
00192 
00193     xgap = 10;
00194     xmid = 15;
00195     dy = 15;
00196 
00197     if (!split) {
00198         *xsize = 3*xgap + l1 + l2;
00199         *ysize = (n+1) * (dy + h) + dy;
00200     } else {
00201         *xsize = 5*xgap + xmid + 2*(l1 + l2);
00202         *ysize = ((split < n-split ? n-split : split)+1) * (dy + h) + dy;
00203     }
00204     if (*xsize < 3*xgap + 12*lchar) *xsize = 3*xgap + 12*lchar; /* OK/CANCEL */
00205 
00206     /* Make room for the box title */
00207 
00208     if (title)
00209         i = strlen(title);
00210     else
00211         i = 10;
00212 
00213     i += 8;     /* Take size of buttons. etc., into account */
00214 
00215     lux_string_dimensions("X", &uchar, &h);
00216     i *= uchar*1.25;    /* Trial and error! */
00217     if (*xsize < i) *xsize = i;
00218 
00219     /* Initialize dialog box material. */
00220 
00221     *dialog_win = lux_open_dialog(xorigin, yorigin, *xsize, *ysize);
00222 
00223     if (title)
00224         lux_set_window_name(*dialog_win, title);
00225     else
00226         lux_set_window_name(*dialog_win, "Parameters");
00227 
00228     x1 = xgap;
00229     x2 = x1 + l1 + xgap;
00230 
00231     ymax = *ysize - dy/2;
00232     y = ymax + dy/2;
00233 
00234     for (i = 0; i < n; i++) {
00235         set_dialog_item(dialog_win, i, list+i, x1,  x2, (y -= dy+h));
00236         if (split > 0 && i == split-1) {
00237             y = ymax + dy/2;
00238             x1 = 3*xgap + xmid + l1 + l2;
00239             x2 = x1 + l1 + xgap;
00240         }
00241     }
00242 
00243     /* OK/cancel boxes: */
00244 
00245     xgap = (*xsize - 12*lchar)/3;
00246     lux_set_item(*dialog_win, n, BUTTON_WINDOW, OK_KEEP_BUTTON,
00247                  xgap, dy, 6, "  OK  ");
00248     lux_set_item(*dialog_win, n+1, BUTTON_WINDOW, CANCEL_BUTTON,
00249                  2*xgap + 6*lchar, dy, 6, "CANCEL");
00250 }
00251 
00252 /*---------------------------------------------------------------------- */
00253 
00254 void update_from_dialog(Window dialog_win, dialog_entry* list, int n)
00255 {
00256     /* Read all items from the dialog box. */
00257 
00258     int i;
00259 
00260     for (i = 0; i < n; i++) {
00261 
00262         if (list[i].type == 0)
00263             lux_get_itemvalue(dialog_win, i, BUTTON_WINDOW, CHECK_BUTTON,
00264                               list[i].value);
00265         else {
00266 
00267             if (list[i].type < 4) {
00268 
00269                 char temp[40];
00270                 lux_get_itemvalue(dialog_win, i, INPUT_WINDOW, NO_TYPE, temp);
00271 
00272                 if (list[i].type == 1)
00273                     sscanf(temp, "%d", (int*)list[i].value);
00274                 else if (list[i].type == 2)
00275                     sscanf(temp, "%f", (float*)list[i].value);
00276                 else
00277                     sscanf(temp, "%lf", (double*)list[i].value);
00278 
00279             } else
00280 
00281                 lux_get_itemvalue(dialog_win, i, INPUT_WINDOW, NO_TYPE,
00282                                   list[i].value);
00283 
00284         }
00285 
00286     }
00287 }
00288 
00289 void reset_dialog_entries(Window dialog_win, dialog_entry* list, int n)
00290 {
00291     /* Reset all items in the dialog box. */
00292 
00293     int i;
00294 
00295     for (i = 0; i < n; i++) {
00296         if (list[i].type == 0)
00297 
00298             lux_update_itemvalue(dialog_win, i, BUTTON_WINDOW, CHECK_BUTTON,
00299                                  list[i].value);
00300 
00301         else {
00302 
00303             char temp[40];
00304             convert_value(list+i, temp);
00305 
00306             lux_update_itemvalue(dialog_win, i, INPUT_WINDOW, NO_TYPE, temp);
00307         }
00308     }
00309 }
00310 
00311 /*---------------------------------------------------------------------- */
00312 
00313 /* For "easy" dialog options: */
00314 
00315 static int n_dialog = 0;
00316 static int split = 0;
00317 static dialog_entry * d = NULL;
00318 
00319 void print_dialog_list(char* s)
00320 {
00321     int i;
00322 
00323     fprintf(stderr, "%s\n", s);
00324     for (i = 0; i < n_dialog; i++) {
00325         fprintf(stderr, "Item %d: name = \"%s\", type = %d, ",
00326                 i, d[i].name, d[i].type);
00327         if (d[i].type == 0)
00328             fprintf(stderr, "value = %d\n", *d[i].value);
00329         else if (d[i].type == 1)
00330             fprintf(stderr, "value = %d\n", *(int*)d[i].value);
00331         else if (d[i].type == 2)
00332             fprintf(stderr, "value = %g\n", *(float*)d[i].value);
00333         else if (d[i].type ==3)
00334             fprintf(stderr, "value = %g\n", *(double*)d[i].value);
00335         else
00336             fprintf(stderr, "value = %s\n", d[i].value);
00337     }
00338 }
00339 
00340 local void extend_dialog_list()
00341 {
00342     /* Untested realloc!! */
00343 
00344     n_dialog++;
00345     d = realloc(d, n_dialog*sizeof(dialog_entry));
00346 }
00347 
00348 /* Note: These functions could be merged into one in C++! */
00349 
00350 void create_button_dialog_entry(char* name, char* value)
00351 {
00352     extend_dialog_list();
00353 
00354     /*
00355      *  Define buttons:
00356      *
00357      *          label,  type,  address of variable.
00358      *
00359      *  Types:  0 = char
00360      *          1 = int
00361      *          2 = float
00362      *          3 = double
00363      *          4 = string
00364      */
00365 
00366     d[n_dialog-1].name = name;
00367     d[n_dialog-1].type = 0;
00368     d[n_dialog-1].value = value;
00369     d[n_dialog-1].width = 1;
00370 }
00371 
00372 void create_int_dialog_entry(char* name, int* value)
00373 {
00374     extend_dialog_list();
00375 
00376     d[n_dialog-1].name = name;
00377     d[n_dialog-1].type = 1;
00378     d[n_dialog-1].value = (char*)value;
00379     d[n_dialog-1].width = 6;
00380 }
00381 
00382 void create_float_dialog_entry(char* name, float* value)
00383 {
00384     extend_dialog_list();
00385 
00386     d[n_dialog-1].name = name;
00387     d[n_dialog-1].type = 2;
00388     d[n_dialog-1].value = (char*)value;
00389     d[n_dialog-1].width = 8;
00390 }
00391 
00392 void create_double_dialog_entry(char* name, double* value)
00393 {
00394     extend_dialog_list();
00395 
00396     d[n_dialog-1].name = name;
00397     d[n_dialog-1].type = 3;
00398     d[n_dialog-1].value = (char*)value;
00399     d[n_dialog-1].width = 8;
00400 }
00401 
00402 void create_string_dialog_entry(char* name, char* value)
00403 {
00404     extend_dialog_list();
00405 
00406     d[n_dialog-1].name = name;
00407     d[n_dialog-1].type = 4;
00408     d[n_dialog-1].value = value;
00409     d[n_dialog-1].width = 10;
00410 }
00411 
00412 void set_dialog_width(int width)
00413 {
00414     /* Set width of the *most recently defined* dialog entry. */
00415 
00416     if (width > 0) d[n_dialog-1].width = width;
00417 }
00418 
00419 void initialize_graphics()
00420 {
00421     /* Set up LUX. */
00422 
00423     set_default_font("7x13");   /* Better for MacX */
00424     lux_xinit();
00425 }
00426 
00427 void set_dialog_split(int s)
00428 {
00429     if (s >= 0)
00430         split = s;
00431     else
00432         split = -1;
00433 }
00434 
00435 /* "Ez" user probably doesn't care about these,
00436     so hide them from view: */
00437 
00438 static Window ez_dialog_win;
00439 static int ez_xsize, ez_ysize;
00440 
00441 void set_up_dialog(char* title, int xorigin, int yorigin)
00442 {
00443     int spl;
00444 
00445     if (n_dialog > 0) {
00446 
00447         if (split >= 0)
00448             spl = split;
00449         else
00450             spl = (n_dialog+1)/2;
00451 
00452         initialize_graphics();
00453         initialize_dialog(&ez_dialog_win,
00454                           xorigin, yorigin, title,
00455                           &ez_xsize, &ez_ysize,
00456                           d, n_dialog, spl);
00457     }
00458 }
00459 
00460 int read_dialog_window()
00461 {
00462     /*
00463      * Display the dialog box; lux_getevent() = 3 on return when the
00464      * user exits with "OK".  Then read the dialog box.
00465      */
00466 
00467     int status;
00468 
00469     lux_show_dialog(ez_dialog_win);
00470 
00471     if ((status = lux_getevent()) == 3)
00472         update_from_dialog(ez_dialog_win, d, n_dialog);
00473 
00474     return (status == 3);
00475 }
00476 
00477 void reset_dialog_window()
00478 {
00479     reset_dialog_entries(ez_dialog_win, d, n_dialog);
00480 }

Generated at Sun Feb 24 09:56:57 2002 for STARLAB by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001