Tagged files with gromacs 3.0 header and added some license info
[alexxy/gromacs.git] / src / ngmx / popup.c
1 /*
2  * $Id$
3  * 
4  *                This source code is part of
5  * 
6  *                 G   R   O   M   A   C   S
7  * 
8  *          GROningen MAchine for Chemical Simulations
9  * 
10  *                        VERSION 3.0
11  * 
12  * Copyright (c) 1991-2001
13  * BIOSON Research Institute, Dept. of Biophysical Chemistry
14  * University of Groningen, The Netherlands
15  * 
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License
18  * as published by the Free Software Foundation; either version 2
19  * of the License, or (at your option) any later version.
20  * 
21  * If you want to redistribute modifications, please consider that
22  * scientific software is very special. Version control is crucial -
23  * bugs must be traceable. We will be happy to consider code for
24  * inclusion in the official distribution, but derived work must not
25  * be called official GROMACS. Details are found in the README & COPYING
26  * files - if they are missing, get the official version at www.gromacs.org.
27  * 
28  * To help us fund GROMACS development, we humbly ask that you cite
29  * the papers on the package - you can find them in the top README file.
30  * 
31  * Do check out http://www.gromacs.org , or mail us at gromacs@gromacs.org .
32  * 
33  * And Hey:
34  * Good gRace! Old Maple Actually Chews Slate
35  */
36 static char *SRCID_popup_c = "$Id$";
37 #include <string.h>
38 #include <math.h>
39 #include <macros.h>
40 #include <smalloc.h>
41 #include <x11.h>
42 #include <xutil.h>
43 #include "popup.h"
44
45 bool ChildCallBack(t_x11 *x11,XEvent *event, Window w, void *data)
46 {
47   t_child   *child;
48   t_mentry  *m;
49   t_windata *wd;
50   XEvent    letter;
51
52   child=(t_child *)data;
53   m=child->m;
54   wd=&(child->wd);
55   switch (event->type) {
56   case Expose:
57     XSetForeground(x11->disp,x11->gc,x11->fg);
58     TextInRect(x11,w,m->str,16,0,wd->width-16-2,wd->height-2,
59                eXLeft,eYCenter);
60     if (m->bChecked) {
61       int y=x11->font->ascent;
62       XDrawLine(x11->disp,w,x11->gc,2,(y*2)/3,6,y);
63       XDrawLine(x11->disp,w,x11->gc,3,(y*2)/3,7,y);
64       XDrawLine(x11->disp,w,x11->gc,7,y,12,2);
65     }
66     break;
67   case EnterNotify:
68     LightBorder(x11->disp,w,x11->fg);
69     break;
70   case LeaveNotify:
71     LightBorder(x11->disp,w,x11->bg);
72     break;
73   case ButtonRelease:
74     letter.type=ClientMessage;
75     letter.xclient.display=x11->disp;
76     letter.xclient.window=m->send_to ? m->send_to : child->Parent;
77     letter.xclient.message_type=0;
78     letter.xclient.format=32;
79     letter.xclient.data.l[0]=m->nreturn;
80     XSendEvent(x11->disp,letter.xclient.window,True,0,&letter);
81     break;
82   default:
83     break;
84   }
85   return FALSE;
86 }
87
88 bool MenuCallBack(t_x11 *x11,XEvent *event, Window w, void *data)
89 {
90   t_menu *m;
91
92   m=(t_menu *)data;
93   switch(event->type) {
94   case Expose:
95     /* Nothing to be done */
96     if (m->bGrabbed)
97       m->bGrabbed=
98         GrabOK(stderr,XGrabPointer(x11->disp,m->wd.self,True,
99                                    ButtonReleaseMask,GrabModeAsync,
100                                    GrabModeAsync,m->wd.self,None,CurrentTime));
101     break;
102   case ButtonRelease:
103     hide_menu(x11,m);
104     break;
105   case ClientMessage:
106     event->xclient.window=m->Parent;
107     XSendEvent(x11->disp,m->Parent,True,0,event);
108     break;
109   default:
110     break;
111   }
112   return FALSE;
113 }
114
115 t_menu *init_menu(t_x11 *x11,Window Parent,unsigned long fg,unsigned long bg,
116                   int nent,t_mentry ent[],int ncol)
117 {
118   int       i,mlen,mht,area,ht;
119   int       j,k,l;
120   int       frows,fcol;
121   t_menu    *m;
122   t_child   *kid;
123   t_windata *w;
124
125   snew(m,1);
126   m->nitem=nent;
127   m->Parent=Parent;
128
129   /* Calculate dimensions of the menu */
130   mlen=0;
131   for(i=0; (i<nent); i++)
132     mlen=max(mlen,XTextWidth(x11->font,ent[i].str,strlen(ent[i].str)));
133   mht=XTextHeight(x11->font);
134   /* Now we have the biggest single box, add a border of 2 pixels */
135   mlen+=20; /* We need extra space at the left for checkmarks */
136   mht+=4;
137   /* Calculate the area of the menu */
138   area=mlen*mht;
139   ht=sqrt(area);
140   /* No the number of rows per column, only beyond 8 rows */
141   if (ncol == 0) {
142     if (nent > 8)
143       frows=(1+ht/mht);
144     else
145       frows=nent;
146     fcol=nent/frows;
147   }
148   else {
149     fcol=ncol;
150     frows=nent/ncol;
151     if (nent % ncol)
152       frows++;
153   }
154   InitWin(&(m->wd),10,10,fcol*mlen,frows*mht,1,"Menu");
155   snew(m->item,nent);
156   m->wd.self=XCreateSimpleWindow(x11->disp,Parent,
157                                  m->wd.x, m->wd.y,
158                                  m->wd.width,m->wd.height,
159                                  m->wd.bwidth,fg,bg);
160   x11->RegisterCallback(x11,m->wd.self,Parent,MenuCallBack,m);
161   x11->SetInputMask(x11,m->wd.self,ExposureMask | 
162                     OwnerGrabButtonMask | ButtonReleaseMask);
163
164   for(j=l=0; (j<fcol); j++)
165     for(k=0; (k<frows) && (l<nent); k++,l++) {
166       kid=&(m->item[l]);
167       kid->m=&(ent[l]);
168       kid->Parent=Parent; 
169       w=&(kid->wd);
170       InitWin(w,j*mlen,k*mht,mlen-2,mht-2,1,NULL);
171       w->self=XCreateSimpleWindow(x11->disp,m->wd.self,
172                                   w->x,w->y,w->width,w->height,
173                                   w->bwidth,bg,bg);
174       x11->RegisterCallback(x11,w->self,m->wd.self,
175                             ChildCallBack,kid);
176       x11->SetInputMask(x11,w->self,
177                         ButtonPressMask | ButtonReleaseMask | 
178                         OwnerGrabButtonMask | ExposureMask | 
179                         EnterWindowMask | LeaveWindowMask);
180     }
181
182   return m;
183 }
184
185 void show_menu(t_x11 *x11,t_menu *m,int x,int y,bool bGrab)
186 {
187   XMoveWindow(x11->disp,m->wd.self,x,y);
188   m->bGrabbed=bGrab;
189   XMapWindow(x11->disp,m->wd.self);
190   XMapSubwindows(x11->disp,m->wd.self);
191 }
192
193 void hide_menu(t_x11 *x11,t_menu *m)
194 {
195   if (m->bGrabbed)
196     XUngrabPointer(x11->disp,CurrentTime);
197   XUnmapWindow(x11->disp,m->wd.self);
198 }
199
200 void check_menu_item(t_menu *m,int nreturn,bool bStatus)
201 {
202   int i;
203
204   for(i=0; (i<m->nitem); i++)
205     if(m->item[i].m->nreturn==nreturn)
206       m->item[i].m->bChecked=bStatus;
207 }
208
209 void done_menu(t_x11 *x11,t_menu *m)
210 {
211   int i;
212
213   for(i=0; (i<m->nitem); i++)
214     x11->UnRegisterCallback(x11,m->item[i].wd.self);
215   sfree(m->item);
216   x11->UnRegisterCallback(x11,m->wd.self);
217   sfree(m);
218 }
219
220 int menu_width(t_menu *m)
221 {
222   return m->wd.width;
223 }
224
225 int menu_height(t_menu *m)
226 {
227   return m->wd.height;
228 }
229