Added new testing code for normal mode analysis.
[gromacs.git] / src / programs / view / xdlghi.cpp
blob3cae52d971c57c2df6d1809dbee9f26857a33cc3
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2013, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015,2017, 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.
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.
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.
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.
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.
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.
37 #include "gmxpre.h"
39 #include "xdlghi.h"
41 #include <cstdio>
42 #include <cstdlib>
43 #include <cstring>
45 #include <algorithm>
47 #include "gromacs/utility/cstringutil.h"
48 #include "gromacs/utility/fatalerror.h"
49 #include "gromacs/utility/smalloc.h"
51 #include "fgrid.h"
52 #include "xutil.h"
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.
65 t_dlgitem **dlgitem;
66 int x, y, w;
67 int i;
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++)
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);
81 for (i = 0; (i < nrb); i++)
83 dlgitem[i+1]->win.width = w;
85 dlgitem[0]->win.width = w+4*OFFS_X;
86 dlgitem[0]->win.height = y-y0;
88 return dlgitem;
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.
100 va_list ap;
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;
112 va_start(ap, nitem);
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++)
122 edlg = (edlgitem)va_arg(ap, int);
123 ids[i] = va_arg(ap, int);
124 switch (edlg)
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);
162 y += dlgitem[i+1]->win.height+OFFS_Y;
163 w = std::max(w, dlgitem[i+1]->win.width);
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++)
171 dlgitem[i+1]->win.width = w;
173 dlgitem[0]->win.width = w+4*OFFS_X;
174 dlgitem[0]->win.height = y-y0;
175 return dlgitem;
178 static void AddDlgItemGroups(t_dlg *dlg, int gridx, int gridy,
179 t_dlgitemlist **grid, bool bAutoPosition)
181 t_dlgitemlist *item;
182 int x1, y1, w1, h1;
183 int x, y, dw, dh;
184 float w, h;
186 w = h = 0;
187 for (x = 0; (x < gridx); x++)
189 for (y = 0; (y < gridy); y++)
191 item = &(grid[x][y]);
192 if (item->nitem)
194 if (!item->list)
196 std::printf("Error: empty list with non-empty nitem (%d)\n", item->nitem);
197 std::printf(" at grid point: %d,%d\n", x, y);
198 std::printf(" with size: %dx%d\n", item->w, item->h);
199 std::exit(1);
201 else
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);
212 w1 = gridx*w;
213 h1 = gridy*h;
214 SetDlgSize(dlg, w1, h1, bAutoPosition);
215 #ifdef DEBUG
216 std::printf("Dimensions of grid cell: %8.3f x %8.3f\n", w, h);
217 std::printf("Dimensions of window: %d x %d\n", w1, h1);
218 #endif
220 for (x = 0; (x < gridx); x++)
222 for (y = 0; (y < gridy); y++)
224 item = &(grid[x][y]);
225 if (item->nitem)
227 x1 = x*w;
228 y1 = y*h;
229 w1 = item->w*w;
230 h1 = item->h*h;
231 #ifdef DEBUG
232 std::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);
241 static t_dlgitemlist **NewDlgitemList(int w, int h)
243 int i, j;
244 t_dlgitemlist **grid;
246 snew(grid, w);
247 for (i = 0; (i < w); i++)
249 snew(grid[i], h);
250 for (j = 0; (j < h); j++)
252 grid[i][j].nitem = 0;
253 grid[i][j].list = nullptr;
256 return grid;
259 static void AddListItem(t_dlgitemlist *list, t_dlgitem *item)
261 srenew(list->list, ++list->nitem);
262 list->list[list->nitem-1] = item;
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)
269 int i, iSel, slen;
270 char buf[STRLEN];
272 switch (fitem->edlg)
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 std::strcpy(buf, fitem->def);
281 iSel = -1;
282 for (i = 0; (i < fitem->nname); i++)
284 char buf2[100];
286 std::strcpy(buf2, fitem->name[i]);
287 buf2[strlen(buf)] = '\0'; /* truncate itemname */
288 if (gmx_strcasecmp(buf2, buf) == 0)
290 iSel = i;
294 for (i = 0; (i < fitem->nname); i++)
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);
304 break;
305 case edlgCB:
307 bool bCheck;
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;
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 = std::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);
330 SetDlgitemOpts(list->list[list->nitem-1], bUseMon,
331 fitem->set, fitem->get, fitem->help);
333 if (fitem->edlg != edlgRB)
335 (*y) += list->list[list->nitem-1]->win.height+OFFS_Y;
336 (*w) = std::max((*w), list->list[list->nitem-1]->win.width);
340 static void AddListFGroup(t_x11 *x11, t_dlgitemlist **grid,
341 t_fgroup *fgroup, t_id *ID, bool bUseMon)
343 int i;
344 t_id GroupID, *ids;
345 t_dlgitemlist *item;
346 int x, y, w;
348 GroupID = (*ID)++;
349 item = &(grid[fgroup->x][fgroup->y]);
350 AddListItem(item, CreateGroupBox(x11, fgroup->name, GroupID,
351 0, nullptr, 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++)
357 AddListFItem(x11, item, fgroup->fitem[i], GroupID, ID, x, &y, &w, bUseMon);
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++)
366 ids[i] = GroupID+i+1;
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;
376 static void AddListFSimple(t_x11 *x11, t_dlgitemlist **grid,
377 t_fsimple *fsimple, t_id *ID, bool bUseMon)
379 t_dlgitemlist *item;
380 int x, y, w;
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;
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)
396 t_fgrid *fgrid;
397 t_dlgitemlist **grid;
398 t_dlg *dlg;
399 int i;
400 t_id ID;
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;
407 for (i = 0; (i < fgrid->nfgroup); i++)
409 AddListFGroup(x11, grid, fgrid->fgroup[i], &ID, bUseMon);
411 for (i = 0; (i < fgrid->nfsimple); i++)
413 AddListFSimple(x11, grid, fgrid->fsimple[i], &ID, bUseMon);
415 AddDlgItemGroups(dlg, fgrid->w, fgrid->h, grid, bAutoPosition);
417 DoneFGrid(fgrid);
419 return dlg;