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