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