Remove unnecessary config.h includes
[alexxy/gromacs.git] / src / programs / view / xdlghi.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2013, The GROMACS development team.
6  * Copyright (c) 2013,2014, by the GROMACS development team, led by
7  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8  * and including many others, as listed in the AUTHORS file in the
9  * top-level source directory and at http://www.gromacs.org.
10  *
11  * GROMACS is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License
13  * as published by the Free Software Foundation; either version 2.1
14  * of the License, or (at your option) any later version.
15  *
16  * GROMACS is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with GROMACS; if not, see
23  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
25  *
26  * If you want to redistribute modifications to GROMACS, please
27  * consider that scientific software is very special. Version
28  * control is crucial - bugs must be traceable. We will be happy to
29  * consider code for inclusion in the official distribution, but
30  * derived work must not be called official GROMACS. Details are found
31  * in the README & COPYING files - if they are missing, get the
32  * official version at http://www.gromacs.org.
33  *
34  * To help us fund GROMACS development, we humbly ask that you cite
35  * the research papers on the package. Check out http://www.gromacs.org.
36  */
37 #include "gmxpre.h"
38
39 #include <stdlib.h>
40 #include <string.h>
41
42 #include <algorithm>
43
44 #include "gromacs/legacyheaders/macros.h"
45 #include "xutil.h"
46 #include "xdlghi.h"
47 #include "fgrid.h"
48
49 #include "gromacs/utility/cstringutil.h"
50 #include "gromacs/utility/fatalerror.h"
51 #include "gromacs/utility/smalloc.h"
52
53 t_dlgitem **CreateRadioButtonGroup(t_x11 *x11, char *szTitle,
54                                    t_id GroupID, int nrb, t_id rb[],
55                                    int nSelect,
56                                    char *szRB[], int x0, int y0)
57 /* This routine creates a radio button group at the
58  * specified position. The return values is a pointer to an
59  * array of dlgitems, the array has length (nrb+1) with the +1
60  * because of the groupbox.
61  * nSelect is the ordinal of the selected button.
62  */
63 {
64     t_dlgitem **dlgitem;
65     int         x, y, w;
66     int         i;
67
68     snew(dlgitem, nrb+1);
69     dlgitem[0] = CreateGroupBox(x11, szTitle, GroupID, nrb, rb, x0, y0, 0, 0, 0);
70     x          = x0+2*OFFS_X;
71     y          = dlgitem[0]->win.y+dlgitem[0]->win.height;
72     w          = 0;
73     for (i = 0; (i < nrb); i++)
74     {
75         dlgitem[i+1] = CreateRadioButton(x11, szRB[i], (i == nSelect),
76                                          rb[i], GroupID, x, y, 0, 0, 0);
77         y += dlgitem[i+1]->win.height+OFFS_Y;
78         w  = std::max(w, dlgitem[i+1]->win.width);
79     }
80     for (i = 0; (i < nrb); i++)
81     {
82         dlgitem[i+1]->win.width = w;
83     }
84     dlgitem[0]->win.width  = w+4*OFFS_X;
85     dlgitem[0]->win.height = y-y0;
86
87     return dlgitem;
88 }
89
90 t_dlgitem **CreateDlgitemGroup(t_x11 *x11, const char *szTitle,
91                                t_id GroupID, int x0, int y0,
92                                int nitem, ...)
93 /* This routine creates a dlgitem group at the
94  * specified position. The return values is a pointer to an
95  * array of dlgitems, the array has length (nitem+1) with the +1
96  * because of the groupbox.
97  */
98 {
99     va_list       ap;
100
101     t_dlgitem   **dlgitem;
102     t_id         *ids;
103     edlgitem      edlg;
104     char         *name;
105     bool          bBool;
106     Pixmap        pm;
107     int           nlines, buflen;
108     char         *buf, **lines;
109     int           x, y, w, i;
110
111     va_start(ap, nitem);
112
113     snew(dlgitem, nitem+1);
114     snew(ids, nitem);
115     x          = x0+2*OFFS_X;
116     dlgitem[0] = CreateGroupBox(x11, szTitle, GroupID, nitem, ids, x0, y0, 0, 0, 0);
117     y          = dlgitem[0]->win.y+dlgitem[0]->win.height;
118     w          = 0;
119     for (i = 0; (i < nitem); i++)
120     {
121         edlg   = (edlgitem)va_arg(ap, int);
122         ids[i] = va_arg(ap, int);
123         switch (edlg)
124         {
125             case edlgBN:
126                 name         = va_arg(ap, char *);
127                 bBool        = va_arg(ap, int);
128                 dlgitem[i+1] = CreateButton(x11, name, bBool, ids[i], GroupID, x, y, 0, 0, 0);
129                 break;
130             case edlgRB:
131                 name         = va_arg(ap, char *);
132                 bBool        = va_arg(ap, int);
133                 dlgitem[i+1] = CreateRadioButton(x11, name, bBool, ids[i], GroupID, x, y, 0, 0, 0);
134                 break;
135             case edlgCB:
136                 name         = va_arg(ap, char *);
137                 bBool        = va_arg(ap, int);
138                 dlgitem[i+1] = CreateCheckBox(x11, name, bBool, ids[i], GroupID, x, y, 0, 0, 0);
139                 break;
140             case edlgPM:
141                 pm           = va_arg(ap, Pixmap);
142                 dlgitem[i+1] = CreatePixmap(pm, ids[i], GroupID, x, y, 0, 0, 0);
143                 break;
144             case edlgST:
145                 nlines       = va_arg(ap, int);
146                 lines        = va_arg(ap, char **);
147                 dlgitem[i+1] = CreateStaticText(x11, nlines, lines, ids[i], GroupID,
148                                                 x, y, 0, 0, 0);
149                 break;
150             case edlgET:
151                 name         = va_arg(ap, char *);
152                 buflen       = va_arg(ap, int);
153                 buf          = va_arg(ap, char *);
154                 dlgitem[i+1] = CreateEditText(x11, name, buflen, buf, ids[i],
155                                               GroupID, x, y, 0, 0, 0);
156                 break;
157             case edlgGB:
158             default:
159                 gmx_fatal(FARGS, "Invalid dlgitem type: %d\n", edlg);
160         }
161         y += dlgitem[i+1]->win.height+OFFS_Y;
162         w  = std::max(w, dlgitem[i+1]->win.width);
163     }
164     va_end(ap);
165     sfree(dlgitem[0]->u.groupbox.item);
166     sfree(dlgitem[0]->win.text);
167     dlgitem[0] = CreateGroupBox(x11, szTitle, GroupID, nitem, ids, x0, y0, 0, 0, 0);
168     for (i = 0; (i < nitem); i++)
169     {
170         dlgitem[i+1]->win.width = w;
171     }
172     dlgitem[0]->win.width  = w+4*OFFS_X;
173     dlgitem[0]->win.height = y-y0;
174     return dlgitem;
175 }
176
177 static void AddDlgItemGroups(t_dlg *dlg, int gridx, int gridy,
178                              t_dlgitemlist **grid, bool bAutoPosition)
179 {
180     t_dlgitemlist *item;
181     int            x1, y1, w1, h1;
182     int            x, y, dw, dh;
183     float          w, h;
184
185     w = h = 0;
186     for (x = 0; (x < gridx); x++)
187     {
188         for (y = 0; (y < gridy); y++)
189         {
190             item = &(grid[x][y]);
191             if (item->nitem)
192             {
193                 if (!item->list)
194                 {
195                     printf("Error: empty list with non-empty nitem (%d)\n", item->nitem);
196                     printf("       at grid point: %d,%d\n", x, y);
197                     printf("       with size: %dx%d\n", item->w, item->h);
198                     exit(1);
199                 }
200                 else
201                 {
202                     AddDlgItems(dlg, item->nitem, item->list);
203                     dw = item->w;
204                     dh = item->h;
205                     w  = std::max(w, ((float) QueryDlgItemW(dlg, item->list[0]->ID))/dw);
206                     h  = std::max(h, ((float) QueryDlgItemH(dlg, item->list[0]->ID))/dh);
207                 }
208             }
209         }
210     }
211     w1 = gridx*w;
212     h1 = gridy*h;
213     SetDlgSize(dlg, w1, h1, bAutoPosition);
214 #ifdef DEBUG
215     printf("Dimensions of grid cell: %8.3f x %8.3f\n", w, h);
216     printf("Dimensions of window:    %d x %d\n", w1, h1);
217 #endif
218
219     for (x = 0; (x < gridx); x++)
220     {
221         for (y = 0; (y < gridy); y++)
222         {
223             item = &(grid[x][y]);
224             if (item->nitem)
225             {
226                 x1 = x*w;
227                 y1 = y*h;
228                 w1 = item->w*w;
229                 h1 = item->h*h;
230 #ifdef DEBUG
231                 printf("New size: %d x %d at %d, %d\n", w1, h1, x1, y1);
232 #endif
233                 SetDlgItemSize(dlg, item->list[0]->ID, w1, h1);
234                 SetDlgItemPos(dlg, item->list[0]->ID, x1, y1);
235             }
236         }
237     }
238 }
239
240 static t_dlgitemlist **NewDlgitemList(int w, int h)
241 {
242     int             i, j;
243     t_dlgitemlist **grid;
244
245     snew(grid, w);
246     for (i = 0; (i < w); i++)
247     {
248         snew(grid[i], h);
249         for (j = 0; (j < h); j++)
250         {
251             grid[i][j].nitem = 0;
252             grid[i][j].list  = NULL;
253         }
254     }
255     return grid;
256 }
257
258 static void AddListItem(t_dlgitemlist *list, t_dlgitem *item)
259 {
260     srenew(list->list, ++list->nitem);
261     list->list[list->nitem-1] = item;
262 }
263
264 static void AddListFItem(t_x11 *x11, t_dlgitemlist *list,
265                          t_fitem *fitem, t_id GroupID, t_id *ID,
266                          int x, int *y, int *w, bool bUseMon)
267 {
268     int  i, iSel, slen;
269     char buf[STRLEN];
270
271     switch (fitem->edlg)
272     {
273         case edlgBN:
274             AddListItem
275                 (list, CreateButton(x11, fitem->name[0], fitem->bDef, (*ID)++, GroupID,
276                                     x, (*y), 0, 0, 0));
277             break;
278         case edlgRB:
279             strcpy(buf, fitem->def);
280             iSel = -1;
281             for (i = 0; (i < fitem->nname); i++)
282             {
283                 char buf2[100];
284
285                 strcpy(buf2, fitem->name[i]);
286                 buf2[strlen(buf)] = '\0'; /* truncate itemname */
287                 if (gmx_strcasecmp(buf2, buf) == 0)
288                 {
289                     iSel = i;
290                 }
291             }
292
293             for (i = 0; (i < fitem->nname); i++)
294             {
295                 AddListItem(list,
296                             CreateRadioButton(x11, fitem->name[i], (iSel == i),
297                                               (*ID)++, GroupID, x, (*y), 0, 0, 0));
298                 (*y) += list->list[list->nitem-1]->win.height+OFFS_Y;
299                 (*w)  = std::max((*w), list->list[list->nitem-1]->win.width);
300                 SetDlgitemOpts(list->list[list->nitem-1], bUseMon,
301                                fitem->set, fitem->get, fitem->help);
302             }
303             break;
304         case edlgCB:
305         {
306             bool bCheck;
307
308             bCheck = gmx_strcasecmp(fitem->def, "TRUE") == 0;
309             AddListItem(list, CreateCheckBox(x11, fitem->name[0], bCheck,
310                                              (*ID)++, GroupID, x, (*y), 0, 0, 0));
311             break;
312         }
313         case edlgST:
314             AddListItem(list,
315                         CreateStaticText(x11, fitem->nname,
316                                          fitem->name, (*ID)++,
317                                          GroupID, x, (*y), 0, 0, 0));
318             break;
319         case edlgET:
320             slen = strlen(fitem->name[0])+strlen(fitem->def);
321             AddListItem(list, CreateEditText(x11, fitem->name[0], slen, fitem->def,
322                                              (*ID)++, GroupID, x, (*y), 0, 0, 0));
323             break;
324         case edlgPM:
325         case edlgGB:
326         default:
327             gmx_fatal(FARGS, "Invalid list->list type: %d\n", fitem->edlg);
328     }
329     SetDlgitemOpts(list->list[list->nitem-1], bUseMon,
330                    fitem->set, fitem->get, fitem->help);
331
332     if (fitem->edlg != edlgRB)
333     {
334         (*y) += list->list[list->nitem-1]->win.height+OFFS_Y;
335         (*w)  = std::max((*w), list->list[list->nitem-1]->win.width);
336     }
337 }
338
339 static void AddListFGroup(t_x11 *x11, t_dlgitemlist **grid,
340                           t_fgroup *fgroup, t_id *ID, bool bUseMon)
341 {
342     int            i;
343     t_id           GroupID, *ids;
344     t_dlgitemlist *item;
345     int            x, y, w;
346
347     GroupID = (*ID)++;
348     item    = &(grid[fgroup->x][fgroup->y]);
349     AddListItem(item, CreateGroupBox(x11, fgroup->name, GroupID,
350                                      0, NULL, 0, 0, 0, 0, 0));
351     x = 2*OFFS_X;
352     y = item->list[0]->win.y+item->list[0]->win.height;
353     w = 0;
354     for (i = 0; (i < fgroup->nfitem); i++)
355     {
356         AddListFItem(x11, item, fgroup->fitem[i], GroupID, ID, x, &y, &w, bUseMon);
357     }
358
359     w = std::max(w, item->list[0]->win.width+4*OFFS_X);
360     sfree(item->list[0]->u.groupbox.item);
361     sfree(item->list[0]->win.text);
362     snew(ids, item->nitem);
363     for (i = 0; (i < item->nitem-1); i++)
364     {
365         ids[i] = GroupID+i+1;
366     }
367     item->list[0] =
368         CreateGroupBox(x11, fgroup->name, GroupID, item->nitem-1, ids,
369                        2*OFFS_X, 2*OFFS_Y, w+2*OFFS_X, y, 0);
370     sfree(ids);
371     item->w = fgroup->w;
372     item->h = fgroup->h;
373 }
374
375 static void AddListFSimple(t_x11 *x11, t_dlgitemlist **grid,
376                            t_fsimple *fsimple, t_id *ID, bool bUseMon)
377 {
378     t_dlgitemlist *item;
379     int            x, y, w;
380
381     item = &(grid[fsimple->x][fsimple->y]);
382     x    = 0;
383     y    = 0;
384     w    = 0;
385     AddListFItem(x11, item, fsimple->fitem, *ID, ID, x, &y, &w, bUseMon);
386     item->w = fsimple->w;
387     item->h = fsimple->h;
388 }
389
390 t_dlg *ReadDlg(t_x11 *x11, Window Parent, const char *title,
391                const char *infile,
392                int x0, int y0, bool bAutoPosition, bool bUseMon,
393                DlgCallback *cb, void *data)
394 {
395     t_fgrid        *fgrid;
396     t_dlgitemlist **grid;
397     t_dlg          *dlg;
398     int             i;
399     t_id            ID;
400
401     fgrid = FGridFromFile(infile);
402     dlg   = CreateDlg(x11, Parent, title, x0, y0, 0, 0, 0, cb, data);
403     grid  = NewDlgitemList(fgrid->w, fgrid->h);
404     ID    = 0;
405
406     for (i = 0; (i < fgrid->nfgroup); i++)
407     {
408         AddListFGroup(x11, grid, fgrid->fgroup[i], &ID, bUseMon);
409     }
410     for (i = 0; (i < fgrid->nfsimple); i++)
411     {
412         AddListFSimple(x11, grid, fgrid->fsimple[i], &ID, bUseMon);
413     }
414     AddDlgItemGroups(dlg, fgrid->w, fgrid->h, grid, bAutoPosition);
415
416     DoneFGrid(fgrid);
417
418     return dlg;
419 }