Sort includes outside src/gromacs
[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 "xdlghi.h"
40
41 #include <stdlib.h>
42 #include <string.h>
43
44 #include <algorithm>
45
46 #include "gromacs/legacyheaders/macros.h"
47 #include "gromacs/utility/cstringutil.h"
48 #include "gromacs/utility/fatalerror.h"
49 #include "gromacs/utility/smalloc.h"
50
51 #include "fgrid.h"
52 #include "xutil.h"
53
54 t_dlgitem **CreateRadioButtonGroup(t_x11 *x11, char *szTitle,
55                                    t_id GroupID, int nrb, t_id rb[],
56                                    int nSelect,
57                                    char *szRB[], int x0, int y0)
58 /* This routine creates a radio button group at the
59  * specified position. The return values is a pointer to an
60  * array of dlgitems, the array has length (nrb+1) with the +1
61  * because of the groupbox.
62  * nSelect is the ordinal of the selected button.
63  */
64 {
65     t_dlgitem **dlgitem;
66     int         x, y, w;
67     int         i;
68
69     snew(dlgitem, nrb+1);
70     dlgitem[0] = CreateGroupBox(x11, szTitle, GroupID, nrb, rb, x0, y0, 0, 0, 0);
71     x          = x0+2*OFFS_X;
72     y          = dlgitem[0]->win.y+dlgitem[0]->win.height;
73     w          = 0;
74     for (i = 0; (i < nrb); i++)
75     {
76         dlgitem[i+1] = CreateRadioButton(x11, szRB[i], (i == nSelect),
77                                          rb[i], GroupID, x, y, 0, 0, 0);
78         y += dlgitem[i+1]->win.height+OFFS_Y;
79         w  = std::max(w, dlgitem[i+1]->win.width);
80     }
81     for (i = 0; (i < nrb); i++)
82     {
83         dlgitem[i+1]->win.width = w;
84     }
85     dlgitem[0]->win.width  = w+4*OFFS_X;
86     dlgitem[0]->win.height = y-y0;
87
88     return dlgitem;
89 }
90
91 t_dlgitem **CreateDlgitemGroup(t_x11 *x11, const char *szTitle,
92                                t_id GroupID, int x0, int y0,
93                                int nitem, ...)
94 /* This routine creates a dlgitem group at the
95  * specified position. The return values is a pointer to an
96  * array of dlgitems, the array has length (nitem+1) with the +1
97  * because of the groupbox.
98  */
99 {
100     va_list       ap;
101
102     t_dlgitem   **dlgitem;
103     t_id         *ids;
104     edlgitem      edlg;
105     char         *name;
106     bool          bBool;
107     Pixmap        pm;
108     int           nlines, buflen;
109     char         *buf, **lines;
110     int           x, y, w, i;
111
112     va_start(ap, nitem);
113
114     snew(dlgitem, nitem+1);
115     snew(ids, nitem);
116     x          = x0+2*OFFS_X;
117     dlgitem[0] = CreateGroupBox(x11, szTitle, GroupID, nitem, ids, x0, y0, 0, 0, 0);
118     y          = dlgitem[0]->win.y+dlgitem[0]->win.height;
119     w          = 0;
120     for (i = 0; (i < nitem); i++)
121     {
122         edlg   = (edlgitem)va_arg(ap, int);
123         ids[i] = va_arg(ap, int);
124         switch (edlg)
125         {
126             case edlgBN:
127                 name         = va_arg(ap, char *);
128                 bBool        = va_arg(ap, int);
129                 dlgitem[i+1] = CreateButton(x11, name, bBool, ids[i], GroupID, x, y, 0, 0, 0);
130                 break;
131             case edlgRB:
132                 name         = va_arg(ap, char *);
133                 bBool        = va_arg(ap, int);
134                 dlgitem[i+1] = CreateRadioButton(x11, name, bBool, ids[i], GroupID, x, y, 0, 0, 0);
135                 break;
136             case edlgCB:
137                 name         = va_arg(ap, char *);
138                 bBool        = va_arg(ap, int);
139                 dlgitem[i+1] = CreateCheckBox(x11, name, bBool, ids[i], GroupID, x, y, 0, 0, 0);
140                 break;
141             case edlgPM:
142                 pm           = va_arg(ap, Pixmap);
143                 dlgitem[i+1] = CreatePixmap(pm, ids[i], GroupID, x, y, 0, 0, 0);
144                 break;
145             case edlgST:
146                 nlines       = va_arg(ap, int);
147                 lines        = va_arg(ap, char **);
148                 dlgitem[i+1] = CreateStaticText(x11, nlines, lines, ids[i], GroupID,
149                                                 x, y, 0, 0, 0);
150                 break;
151             case edlgET:
152                 name         = va_arg(ap, char *);
153                 buflen       = va_arg(ap, int);
154                 buf          = va_arg(ap, char *);
155                 dlgitem[i+1] = CreateEditText(x11, name, buflen, buf, ids[i],
156                                               GroupID, x, y, 0, 0, 0);
157                 break;
158             case edlgGB:
159             default:
160                 gmx_fatal(FARGS, "Invalid dlgitem type: %d\n", edlg);
161         }
162         y += dlgitem[i+1]->win.height+OFFS_Y;
163         w  = std::max(w, dlgitem[i+1]->win.width);
164     }
165     va_end(ap);
166     sfree(dlgitem[0]->u.groupbox.item);
167     sfree(dlgitem[0]->win.text);
168     dlgitem[0] = CreateGroupBox(x11, szTitle, GroupID, nitem, ids, x0, y0, 0, 0, 0);
169     for (i = 0; (i < nitem); i++)
170     {
171         dlgitem[i+1]->win.width = w;
172     }
173     dlgitem[0]->win.width  = w+4*OFFS_X;
174     dlgitem[0]->win.height = y-y0;
175     return dlgitem;
176 }
177
178 static void AddDlgItemGroups(t_dlg *dlg, int gridx, int gridy,
179                              t_dlgitemlist **grid, bool bAutoPosition)
180 {
181     t_dlgitemlist *item;
182     int            x1, y1, w1, h1;
183     int            x, y, dw, dh;
184     float          w, h;
185
186     w = h = 0;
187     for (x = 0; (x < gridx); x++)
188     {
189         for (y = 0; (y < gridy); y++)
190         {
191             item = &(grid[x][y]);
192             if (item->nitem)
193             {
194                 if (!item->list)
195                 {
196                     printf("Error: empty list with non-empty nitem (%d)\n", item->nitem);
197                     printf("       at grid point: %d,%d\n", x, y);
198                     printf("       with size: %dx%d\n", item->w, item->h);
199                     exit(1);
200                 }
201                 else
202                 {
203                     AddDlgItems(dlg, item->nitem, item->list);
204                     dw = item->w;
205                     dh = item->h;
206                     w  = std::max(w, ((float) QueryDlgItemW(dlg, item->list[0]->ID))/dw);
207                     h  = std::max(h, ((float) QueryDlgItemH(dlg, item->list[0]->ID))/dh);
208                 }
209             }
210         }
211     }
212     w1 = gridx*w;
213     h1 = gridy*h;
214     SetDlgSize(dlg, w1, h1, bAutoPosition);
215 #ifdef DEBUG
216     printf("Dimensions of grid cell: %8.3f x %8.3f\n", w, h);
217     printf("Dimensions of window:    %d x %d\n", w1, h1);
218 #endif
219
220     for (x = 0; (x < gridx); x++)
221     {
222         for (y = 0; (y < gridy); y++)
223         {
224             item = &(grid[x][y]);
225             if (item->nitem)
226             {
227                 x1 = x*w;
228                 y1 = y*h;
229                 w1 = item->w*w;
230                 h1 = item->h*h;
231 #ifdef DEBUG
232                 printf("New size: %d x %d at %d, %d\n", w1, h1, x1, y1);
233 #endif
234                 SetDlgItemSize(dlg, item->list[0]->ID, w1, h1);
235                 SetDlgItemPos(dlg, item->list[0]->ID, x1, y1);
236             }
237         }
238     }
239 }
240
241 static t_dlgitemlist **NewDlgitemList(int w, int h)
242 {
243     int             i, j;
244     t_dlgitemlist **grid;
245
246     snew(grid, w);
247     for (i = 0; (i < w); i++)
248     {
249         snew(grid[i], h);
250         for (j = 0; (j < h); j++)
251         {
252             grid[i][j].nitem = 0;
253             grid[i][j].list  = NULL;
254         }
255     }
256     return grid;
257 }
258
259 static void AddListItem(t_dlgitemlist *list, t_dlgitem *item)
260 {
261     srenew(list->list, ++list->nitem);
262     list->list[list->nitem-1] = item;
263 }
264
265 static void AddListFItem(t_x11 *x11, t_dlgitemlist *list,
266                          t_fitem *fitem, t_id GroupID, t_id *ID,
267                          int x, int *y, int *w, bool bUseMon)
268 {
269     int  i, iSel, slen;
270     char buf[STRLEN];
271
272     switch (fitem->edlg)
273     {
274         case edlgBN:
275             AddListItem
276                 (list, CreateButton(x11, fitem->name[0], fitem->bDef, (*ID)++, GroupID,
277                                     x, (*y), 0, 0, 0));
278             break;
279         case edlgRB:
280             strcpy(buf, fitem->def);
281             iSel = -1;
282             for (i = 0; (i < fitem->nname); i++)
283             {
284                 char buf2[100];
285
286                 strcpy(buf2, fitem->name[i]);
287                 buf2[strlen(buf)] = '\0'; /* truncate itemname */
288                 if (gmx_strcasecmp(buf2, buf) == 0)
289                 {
290                     iSel = i;
291                 }
292             }
293
294             for (i = 0; (i < fitem->nname); i++)
295             {
296                 AddListItem(list,
297                             CreateRadioButton(x11, fitem->name[i], (iSel == i),
298                                               (*ID)++, GroupID, x, (*y), 0, 0, 0));
299                 (*y) += list->list[list->nitem-1]->win.height+OFFS_Y;
300                 (*w)  = std::max((*w), list->list[list->nitem-1]->win.width);
301                 SetDlgitemOpts(list->list[list->nitem-1], bUseMon,
302                                fitem->set, fitem->get, fitem->help);
303             }
304             break;
305         case edlgCB:
306         {
307             bool bCheck;
308
309             bCheck = gmx_strcasecmp(fitem->def, "TRUE") == 0;
310             AddListItem(list, CreateCheckBox(x11, fitem->name[0], bCheck,
311                                              (*ID)++, GroupID, x, (*y), 0, 0, 0));
312             break;
313         }
314         case edlgST:
315             AddListItem(list,
316                         CreateStaticText(x11, fitem->nname,
317                                          fitem->name, (*ID)++,
318                                          GroupID, x, (*y), 0, 0, 0));
319             break;
320         case edlgET:
321             slen = strlen(fitem->name[0])+strlen(fitem->def);
322             AddListItem(list, CreateEditText(x11, fitem->name[0], slen, fitem->def,
323                                              (*ID)++, GroupID, x, (*y), 0, 0, 0));
324             break;
325         case edlgPM:
326         case edlgGB:
327         default:
328             gmx_fatal(FARGS, "Invalid list->list type: %d\n", fitem->edlg);
329     }
330     SetDlgitemOpts(list->list[list->nitem-1], bUseMon,
331                    fitem->set, fitem->get, fitem->help);
332
333     if (fitem->edlg != edlgRB)
334     {
335         (*y) += list->list[list->nitem-1]->win.height+OFFS_Y;
336         (*w)  = std::max((*w), list->list[list->nitem-1]->win.width);
337     }
338 }
339
340 static void AddListFGroup(t_x11 *x11, t_dlgitemlist **grid,
341                           t_fgroup *fgroup, t_id *ID, bool bUseMon)
342 {
343     int            i;
344     t_id           GroupID, *ids;
345     t_dlgitemlist *item;
346     int            x, y, w;
347
348     GroupID = (*ID)++;
349     item    = &(grid[fgroup->x][fgroup->y]);
350     AddListItem(item, CreateGroupBox(x11, fgroup->name, GroupID,
351                                      0, NULL, 0, 0, 0, 0, 0));
352     x = 2*OFFS_X;
353     y = item->list[0]->win.y+item->list[0]->win.height;
354     w = 0;
355     for (i = 0; (i < fgroup->nfitem); i++)
356     {
357         AddListFItem(x11, item, fgroup->fitem[i], GroupID, ID, x, &y, &w, bUseMon);
358     }
359
360     w = std::max(w, item->list[0]->win.width+4*OFFS_X);
361     sfree(item->list[0]->u.groupbox.item);
362     sfree(item->list[0]->win.text);
363     snew(ids, item->nitem);
364     for (i = 0; (i < item->nitem-1); i++)
365     {
366         ids[i] = GroupID+i+1;
367     }
368     item->list[0] =
369         CreateGroupBox(x11, fgroup->name, GroupID, item->nitem-1, ids,
370                        2*OFFS_X, 2*OFFS_Y, w+2*OFFS_X, y, 0);
371     sfree(ids);
372     item->w = fgroup->w;
373     item->h = fgroup->h;
374 }
375
376 static void AddListFSimple(t_x11 *x11, t_dlgitemlist **grid,
377                            t_fsimple *fsimple, t_id *ID, bool bUseMon)
378 {
379     t_dlgitemlist *item;
380     int            x, y, w;
381
382     item = &(grid[fsimple->x][fsimple->y]);
383     x    = 0;
384     y    = 0;
385     w    = 0;
386     AddListFItem(x11, item, fsimple->fitem, *ID, ID, x, &y, &w, bUseMon);
387     item->w = fsimple->w;
388     item->h = fsimple->h;
389 }
390
391 t_dlg *ReadDlg(t_x11 *x11, Window Parent, const char *title,
392                const char *infile,
393                int x0, int y0, bool bAutoPosition, bool bUseMon,
394                DlgCallback *cb, void *data)
395 {
396     t_fgrid        *fgrid;
397     t_dlgitemlist **grid;
398     t_dlg          *dlg;
399     int             i;
400     t_id            ID;
401
402     fgrid = FGridFromFile(infile);
403     dlg   = CreateDlg(x11, Parent, title, x0, y0, 0, 0, 0, cb, data);
404     grid  = NewDlgitemList(fgrid->w, fgrid->h);
405     ID    = 0;
406
407     for (i = 0; (i < fgrid->nfgroup); i++)
408     {
409         AddListFGroup(x11, grid, fgrid->fgroup[i], &ID, bUseMon);
410     }
411     for (i = 0; (i < fgrid->nfsimple); i++)
412     {
413         AddListFSimple(x11, grid, fgrid->fsimple[i], &ID, bUseMon);
414     }
415     AddDlgItemGroups(dlg, fgrid->w, fgrid->h, grid, bAutoPosition);
416
417     DoneFGrid(fgrid);
418
419     return dlg;
420 }