a6d98e1edf377040e712fcd2e054f3e0b1229e7a
[alexxy/gromacs.git] / src / ngmx / pulldown.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 #include <smalloc.h>
41 #include <x11.h>
42 #include <macros.h>
43 #include "popup.h"
44 #include "pulldown.h"
45
46 static gmx_bool PDCallBack(t_x11 *x11,XEvent *event,Window w,void *data)
47 {
48   t_pulldown *pd;
49   int        i,x,x1,y,nsel;
50
51   pd=(t_pulldown *)data;
52   y=pd->wd.height;
53   switch(event->type) {
54   case Expose:
55     XSetForeground(x11->disp,x11->gc,x11->fg);
56     XDrawLine(x11->disp,w,x11->gc,0,y-1,pd->wd.width,y-1);
57     for(i=0; (i<pd->nmenu); i++)
58       XDrawString(x11->disp,pd->wd.self,x11->gc,pd->xpos[i],x11->font->ascent,
59                   pd->title[i],strlen(pd->title[i]));
60     break;
61   case ButtonPress:
62     if (pd->nsel==-1) {
63       x=event->xbutton.x;
64       for(nsel=0; (pd->xpos[nsel+1] < x) && (nsel < pd->nmenu-1); nsel++);
65       pd->nsel=nsel;
66       x1=max(0,min(pd_width(pd)-menu_width(pd->m[nsel]),pd->xpos[nsel]));
67       show_menu(x11,pd->m[nsel],x1,y+1,FALSE);
68     }
69     break;
70   case ButtonRelease:
71     hide_pd(x11,pd);
72     break;
73   default:
74     break;
75   }
76   return FALSE;
77 }
78
79 t_pulldown *init_pd(t_x11 *x11,Window Parent,int width,int height,
80                     unsigned long fg,unsigned long bg,
81                     int nmenu,int *nsub,t_mentry *ent[],const char **title)
82 {
83   t_pulldown *pd;
84   int        i;
85
86   snew(pd,1);
87   pd->title=title;
88   pd->nmenu=nmenu;
89   pd->nsel=-1;
90   snew(pd->m,nmenu);
91   snew(pd->xpos,nmenu+1);
92   pd->xpos[0]=5;
93   for(i=1; (i<=nmenu); i++)
94     pd->xpos[i]=20+pd->xpos[i-1]+
95       XTextWidth(x11->font,title[i-1],strlen(title[i-1]));
96   if (pd->xpos[nmenu] > width) 
97     printf("Menu too wide\n");
98
99   InitWin(&(pd->wd),0,0,width,XTextHeight(x11->font)+2,0,"PullDown");
100   pd->wd.self=XCreateSimpleWindow(x11->disp,Parent,
101                                   pd->wd.x, pd->wd.y,
102                                   pd->wd.width,pd->wd.height,
103                                   pd->wd.bwidth,fg,bg);
104   x11->RegisterCallback(x11,pd->wd.self,Parent,PDCallBack,pd);
105   x11->SetInputMask(x11,pd->wd.self,ExposureMask | ButtonPressMask | 
106                     OwnerGrabButtonMask | ButtonReleaseMask);
107   XMapWindow(x11->disp,pd->wd.self);
108
109   for(i=0; (i<nmenu); i++) 
110     pd->m[i]=init_menu(x11,Parent,fg,bg,nsub[i],ent[i],1);
111
112   return pd;
113 }
114
115 void hide_pd(t_x11 *x11,t_pulldown *pd)
116 {
117   if (pd->nsel != -1)
118     hide_menu(x11,pd->m[pd->nsel]);
119   pd->nsel=-1;
120 }
121
122 void check_pd_item(t_pulldown *pd,int nreturn,gmx_bool bStatus)
123 {
124   int i;
125
126   for(i=0; (i<pd->nmenu); i++)
127     check_menu_item(pd->m[i],nreturn,bStatus);
128 }
129
130 void done_pd(t_x11 *x11,t_pulldown *pd)
131 {
132   int i;
133
134   for(i=0; (i<pd->nmenu); i++)
135     done_menu(x11,pd->m[i]);
136   x11->UnRegisterCallback(x11,pd->wd.self);
137   sfree(pd->m);
138   sfree(pd->xpos);
139 }
140
141 int pd_width(t_pulldown *pd)
142 {
143   int i,w;
144   
145   w=0;
146   for(i=0; (i<pd->nmenu); i++)
147     w=max(w,menu_width(pd->m[i]));
148   w=max(w,pd->xpos[pd->nmenu]);
149   return w;
150 }
151
152 int pd_height(t_pulldown *pd)
153 {
154   int i,h;
155   
156   h=0;
157   for(i=0; (i<pd->nmenu); i++)
158     h=max(h,menu_height(pd->m[i]));
159
160   return h;
161 }
162