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