2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
45 #include "gromacs/legacyheaders/macros.h"
46 #include "gromacs/utility/cstringutil.h"
47 #include "gromacs/utility/fatalerror.h"
48 #include "gromacs/utility/smalloc.h"
53 /*****************************
57 ****************************/
58 t_dlgitem *FindItem(t_dlg *dlg, t_id id)
62 for (i = 0; (i < dlg->nitem); i++)
64 if (dlg->dlgitem[i]->ID == id)
66 return dlg->dlgitem[i];
72 t_dlgitem *FindWin(t_dlg *dlg, Window win)
76 for (i = 0; (i < dlg->nitem); i++)
78 if (dlg->dlgitem[i]->win.self == win)
80 return dlg->dlgitem[i];
86 /*****************************
88 * Routines to manipulate items on a dialog box
90 ****************************/
91 bool QueryDlgItemSize(t_dlg *dlg, t_id id, int *w, int *h)
95 if ((dlgitem = FindItem(dlg, id)) != NULL)
97 *w = dlgitem->win.width;
98 *h = dlgitem->win.height;
104 bool QueryDlgItemPos(t_dlg *dlg, t_id id, int *x0, int *y0)
108 if ((dlgitem = FindItem(dlg, id)) != NULL)
110 *x0 = dlgitem->win.x;
111 *y0 = dlgitem->win.y;
117 int QueryDlgItemX(t_dlg *dlg, t_id id)
121 if ((dlgitem = FindItem(dlg, id)) != NULL)
123 return dlgitem->win.x;
128 int QueryDlgItemY(t_dlg *dlg, t_id id)
132 if ((dlgitem = FindItem(dlg, id)) != NULL)
134 return dlgitem->win.y;
139 int QueryDlgItemW(t_dlg *dlg, t_id id)
143 if ((dlgitem = FindItem(dlg, id)) != NULL)
145 return dlgitem->win.width;
150 int QueryDlgItemH(t_dlg *dlg, t_id id)
154 if ((dlgitem = FindItem(dlg, id)) != NULL)
156 return dlgitem->win.height;
161 bool SetDlgItemSize(t_dlg *dlg, t_id id, int w, int h)
168 if ((dlgitem = FindItem(dlg, id)) != NULL)
171 old_w = dlgitem->win.width;
172 old_h = dlgitem->win.height;
176 dlgitem->win.width = w;
180 dlgitem->win.height = h;
183 fprintf(dlg->x11->console,
184 "Size window from: %dx%d to %dx%d\n", old_w, old_h,
185 dlgitem->win.width, dlgitem->win.height);
186 dlg->x11->Flush(dlg->x11);
188 if (dlgitem->win.self)
190 XResizeWindow(dlg->x11->disp, dlgitem->win.self, dlgitem->win.width,
191 dlgitem->win.height);
193 if ((w) && (dlgitem->type == edlgGB))
196 t_id gid = dlgitem->GroupID;
197 t_id id = dlgitem->ID;
198 for (i = 0; (i < dlg->nitem); i++)
200 t_dlgitem *child = dlg->dlgitem[i];
201 if ((child->GroupID == gid) && (child->ID != id))
203 SetDlgItemSize(dlg, child->ID, w-4*OFFS_X, 0);
212 bool SetDlgItemPos(t_dlg *dlg, t_id id, int x0, int y0)
217 if ((dlgitem = FindItem(dlg, id)) != NULL)
219 old_x = dlgitem->win.x;
220 old_y = dlgitem->win.y;
224 fprintf(dlg->x11->console,
225 "Move window from: %d,%d to %d,%d\n", old_x, old_y, x0, y0);
226 dlg->x11->Flush(dlg->x11);
228 if (dlgitem->win.self)
230 XMoveWindow(dlg->x11->disp, dlgitem->win.self, x0, y0);
232 if (dlgitem->type == edlgGB)
235 t_id gid = dlgitem->GroupID;
236 t_id id = dlgitem->ID;
237 x = dlgitem->win.x+2*OFFS_X-old_x;
238 y = dlgitem->win.y+2*OFFS_Y-old_y;
239 for (i = 0; (i < dlg->nitem); i++)
241 t_dlgitem *child = dlg->dlgitem[i];
242 if ((child->GroupID == gid) && (child->ID != id))
244 SetDlgItemPos(dlg, child->ID, child->win.x+x, child->win.y+y);
253 /*****************************
255 * Routines to extract information from the dlg proc
256 * after dlg is exec'ed
258 ****************************/
259 bool IsCBChecked(t_dlg *dlg, t_id id)
263 if ((dlgitem = FindItem(dlg, id)) != NULL)
265 if (dlgitem->type == edlgCB)
267 return dlgitem->u.checkbox.bChecked;
274 t_id RBSelected(t_dlg *dlg, int gid)
278 for (i = 0; (i < dlg->nitem); i++)
280 if ((dlg->dlgitem[i]->type == edlgRB) &&
281 (dlg->dlgitem[i]->u.radiobutton.bSelect) &&
282 (dlg->dlgitem[i]->GroupID == gid))
284 return dlg->dlgitem[i]->ID;
291 int EditTextLen(t_dlg *dlg, t_id id)
295 if ((dlgitem = FindItem(dlg, id)) != NULL)
297 if (dlgitem->type == edlgET)
299 return strlen(dlgitem->u.edittext.buf);
306 char *EditText(t_dlg *dlg, t_id id)
310 if ((dlgitem = FindItem(dlg, id)) != NULL)
312 if (dlgitem->type == edlgET)
314 return dlgitem->u.edittext.buf;
321 /*****************************
323 * Exececute the dialog box procedure
324 * Returns when a button is pushed.
325 * return value is the ID of the button
327 ****************************/
328 void ShowDlg(t_dlg *dlg)
333 XMapWindow(dlg->x11->disp, dlg->win.self);
334 XMapSubwindows(dlg->x11->disp, dlg->win.self);
335 for (i = 0; (i < dlg->nitem); i++)
337 LightBorder(dlg->x11->disp, dlg->dlgitem[i]->win.self, dlg->bg);
339 XSetForeground(dlg->x11->disp, dlg->x11->gc, dlg->x11->fg);
340 for (i = 0; (i < dlg->nitem); i++)
342 dlgitem = dlg->dlgitem[i];
343 if ((dlgitem->type == edlgBN) &&
344 (dlgitem->u.button.bDefault))
346 PushMouse(dlg->x11->disp, dlgitem->win.self,
347 dlgitem->win.width/2, dlgitem->win.height/2);
355 void HideDlg(t_dlg *dlg)
359 PopMouse(dlg->x11->disp);
362 XUnmapSubwindows(dlg->x11->disp, dlg->win.self);
363 XUnmapWindow(dlg->x11->disp, dlg->win.self);
366 void NoHelp(t_dlg *dlg)
368 const char *lines[2] = {
370 "No help for this item"
372 MessageBox(dlg->x11, dlg->wDad, "No Help", 2, lines,
373 MB_OK | MB_ICONSTOP | MB_APPLMODAL, NULL, NULL);
376 void HelpDlg(t_dlg *dlg)
378 const char *lines[] = {
379 "Place the cursor over one of the items",
380 "and press the F1 key to get more help.",
381 "First press the OK button."
383 MessageBox(dlg->x11, dlg->win.self, "Help Dialogbox",
384 3, lines, MB_OK | MB_ICONINFORMATION | MB_APPLMODAL, NULL, NULL);
387 void HelpNow(t_dlg *dlg, t_dlgitem *dlgitem)
400 printf("%s\n", dlgitem->help);
403 fgets2(buf, 79, stdin);
405 fprintf(dlg->x11->console, "buffer: '%s'\n", buf);
406 dlg->x11->Flush(dlg->x11);
408 if (gmx_strcasecmp(buf, "nok") == 0)
410 /* An error occurred */
411 for (i = 0; (i < nlines); i++)
421 bCont = (gmx_strcasecmp(buf, "ok") != 0);
424 srenew(lines, ++nlines);
425 lines[nlines-1] = gmx_strdup(buf);
430 MessageBox(dlg->x11, dlg->wDad, "Help",
432 MB_OK | MB_ICONINFORMATION | MB_APPLMODAL, NULL, NULL);
433 for (i = 0; (i < nlines); i++)
440 static void EnterDlg(t_dlg *dlg)
442 if (dlg->flags & DLG_APPLMODAL)
444 dlg->bGrab = GrabOK(dlg->x11->console,
445 XGrabPointer(dlg->x11->disp, dlg->win.self,
446 True, 0, GrabModeAsync, GrabModeAsync,
447 dlg->win.self, None, CurrentTime));
449 dlg->x11->Flush(dlg->x11);
452 static void ExitDlg(t_dlg *dlg)
456 XUngrabPointer(dlg->x11->disp, CurrentTime);
460 if (dlg->flags & DLG_FREEONBUTTON)
466 static bool DlgCB(t_x11 *x11, XEvent *event, Window w, void *data)
468 t_dlg *dlg = (t_dlg *)data;
472 if ((dlgitem = FindWin(dlg, w)) != NULL)
474 nWndProc = (dlgitem->WndProc)(x11, dlgitem, event);
476 fprintf(x11->console,
477 "window: %s, nWndProc: %d\n", dlgitem->win.text, nWndProc);
483 if ((dlgitem->type == edlgBN) && (dlgitem->u.button.bDefault))
487 dlg->cb(x11, DLG_EXIT, dlgitem->ID, dlgitem->win.text, dlg->data);
496 for (i = 0; (i < dlg->nitem); i++)
498 if ((dlg->dlgitem[i]->type == edlgBN) &&
499 (dlg->dlgitem[i]->u.button.bDefault))
501 PushMouse(x11->disp, dlg->dlgitem[i]->win.self,
502 dlg->dlgitem[i]->win.width/2,
503 dlg->dlgitem[i]->win.height/2);
512 dlg->cb(x11, DLG_EXIT, dlgitem->ID, dlgitem->win.text, dlg->data);
521 int gid = dlgitem->GroupID;
522 t_id tid = RBSelected(dlg, gid);
524 fprintf(stderr, "RBPRESSED\n");
528 t_dlgitem *dit = FindItem(dlg, tid);
529 dit->u.radiobutton.bSelect = false;
530 ExposeWin(x11->disp, dit->win.self);
534 gmx_fatal(FARGS, "No RB Selected initially!\n");
536 dlgitem->u.radiobutton.bSelect = true;
537 ExposeWin(x11->disp, dlgitem->win.self);
540 dlg->cb(x11, DLG_SET, dlgitem->ID, dlgitem->win.text, dlg->data);
545 ExposeWin(x11->disp, dlgitem->win.self);
548 dlg->cb(x11, DLG_SET, dlgitem->ID, dlgitem->set, dlg->data);
552 ExposeWin(x11->disp, dlgitem->win.self);
555 dlg->cb(x11, DLG_SET, dlgitem->ID, dlgitem->u.edittext.buf, dlg->data);
559 HelpNow(dlg, dlgitem);
564 gmx_fatal(FARGS, "Invalid return code (%d) from wndproc\n", nWndProc);
567 else if (w == dlg->win.self)
576 if (HelpPressed(event))
582 XBell(x11->disp, 50);
592 /*****************************
594 * Routine to add an item to the dialog box
595 * The pointer to the item is copied to the dlg struct,
596 * the item itself may not be freed until the dlg is done with
598 ****************************/
599 void DoCreateDlg(t_dlg *dlg)
602 XSetWindowAttributes attr;
605 attr.border_pixel = dlg->x11->fg;
606 attr.background_pixel = dlg->bg;
607 attr.override_redirect = False;
608 attr.save_under = True;
609 attr.cursor = XCreateFontCursor(dlg->x11->disp, XC_hand2);
610 Val = CWBackPixel | CWBorderPixel | CWOverrideRedirect | CWSaveUnder |
612 dlg->win.self = XCreateWindow(dlg->x11->disp, dlg->wDad,
613 dlg->win.x, dlg->win.y,
614 dlg->win.width, dlg->win.height,
615 dlg->win.bwidth, CopyFromParent,
616 InputOutput, CopyFromParent,
618 dlg->x11->RegisterCallback(dlg->x11, dlg->win.self, dlg->wDad,
620 dlg->x11->SetInputMask(dlg->x11, dlg->win.self,
621 ExposureMask | ButtonPressMask | KeyPressMask);
623 if (!CheckWindow(dlg->win.self))
627 hints.x = dlg->win.x;
628 hints.y = dlg->win.y;
629 hints.flags = PPosition;
630 XSetStandardProperties(dlg->x11->disp, dlg->win.self, dlg->title,
631 dlg->title, None, NULL, 0, &hints);
634 void AddDlgItem(t_dlg *dlg, t_dlgitem *item)
636 #define EnterLeaveMask (EnterWindowMask | LeaveWindowMask)
637 #define UserMask (ButtonPressMask | KeyPressMask)
638 static unsigned long InputMask[edlgNR] = {
639 ExposureMask | UserMask | EnterLeaveMask, /* edlgBN */
640 ExposureMask | UserMask | EnterLeaveMask, /* edlgRB */
641 ExposureMask, /* edlgGB */
642 ExposureMask | UserMask | EnterLeaveMask, /* edlgCB */
644 ExposureMask, /* edlgST */
645 ExposureMask | UserMask | EnterLeaveMask /* edlgET */
652 srenew(dlg->dlgitem, dlg->nitem+1);
655 gmx_fatal(FARGS, "dlgitem not allocated");
658 XCreateSimpleWindow(dlg->x11->disp, dlg->win.self, item->win.x, item->win.y,
659 item->win.width, item->win.height,
660 item->win.bwidth, dlg->x11->fg, dlg->x11->bg);
661 CheckWindow(item->win.self);
663 dlg->x11->RegisterCallback(dlg->x11, item->win.self, dlg->win.self,
665 dlg->x11->SetInputMask(dlg->x11, item->win.self, InputMask[item->type]);
670 XSetWindowBackgroundPixmap(dlg->x11->disp, item->win.self, item->u.pixmap.pm);
675 dlg->dlgitem[dlg->nitem] = item;
680 void AddDlgItems(t_dlg *dlg, int nitem, t_dlgitem *item[])
684 for (i = 0; (i < nitem); i++)
687 fprintf(dlg->x11->console,
688 "Adding item: %d from group %d\n", item[i]->ID, item[i]->GroupID);
689 dlg->x11->Flush(dlg->x11);
691 AddDlgItem(dlg, item[i]);
695 void FreeDlgItem(t_dlg *dlg, t_id id)
700 if ((dlgitem = FindItem(dlg, id)) != NULL)
702 dlg->x11->UnRegisterCallback(dlg->x11, dlgitem->win.self);
703 if (dlgitem->win.self)
705 XDestroyWindow(dlg->x11->disp, dlgitem->win.self);
707 FreeWin(dlg->x11->disp, &(dlgitem->win));
708 switch (dlgitem->type)
714 sfree(dlgitem->u.groupbox.item);
719 XFreePixmap(dlg->x11->disp, dlgitem->u.pixmap.pm);
722 for (i = 0; (i < dlgitem->u.statictext.nlines); i++)
724 sfree(dlgitem->u.statictext.lines[i]);
726 sfree(dlgitem->u.statictext.lines);
729 sfree(dlgitem->u.edittext.buf);
737 void FreeDlg(t_dlg *dlg)
744 dlg->x11->UnRegisterCallback(dlg->x11, dlg->win.self);
745 for (i = 0; (i < dlg->nitem); i++)
747 FreeDlgItem(dlg, dlg->dlgitem[i]->ID);
750 sfree(dlg->dlgitem[i]);
756 XDestroyWindow(dlg->x11->disp, dlg->win.self);
762 /*****************************
764 * Routine to create the DLG structure, returns NULL on failure
766 ****************************/
767 t_dlg *CreateDlg(t_x11 *x11, Window Parent, const char *title,
768 int x0, int y0, int w, int h, int bw,
769 DlgCallback *cb, void *data)
780 dlg->title = gmx_strdup(title);
797 dlg->xmax = DisplayWidth(x11->disp, x11->screen);
798 dlg->ymax = DisplayHeight(x11->disp, x11->screen);
805 XGetGeometry(x11->disp, Parent, &root, &x, &y,
806 &(dlg->xmax), &(dlg->ymax), &dum, &dum);
808 fprintf(x11->console,
809 "Daddy is %d x %d at %d, %d\n", dlg->xmax, dlg->ymax, x, y);
810 dlg->x11->Flush(dlg->x11);
821 InitWin(&(dlg->win), x, y, w, h, bw, NULL);
822 SetDlgSize(dlg, w, h, x0 || y0);
834 void SetDlgSize(t_dlg *dlg, int w, int h, bool bAutoPosition)
849 fprintf(dlg->x11->console, "SetDlgSize: Dialog is %dx%d, at %d,%d\n",
850 dlg->win.width, dlg->win.height, dlg->win.x, dlg->win.y);
851 dlg->x11->Flush(dlg->x11);
855 XMoveWindow(dlg->x11->disp, dlg->win.self, dlg->win.x, dlg->win.y);
856 XResizeWindow(dlg->x11->disp, dlg->win.self, w, h);