4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
27 * Green Red Orange Magenta Azure Cyan Skyblue
29 static char *SRCID_mgmx_c
= "$Id$";
35 #include <Xm/ScrolledW.h>
36 #include <Xm/ScrollBar.h>
38 #include <Xm/PushBP.h>
39 #include <Xm/ToggleB.h>
40 #include <Xm/ArrowB.h>
41 #include <Xm/CascadeB.h>
42 #include <Xm/Separator.h>
43 #include <Xm/DrawnB.h>
44 #include <Xm/DialogS.h>
47 #include <Xm/FileSB.h>
49 #include <Xm/RowColumn.h>
54 #include <Xm/DrawingA.h>
55 #include <Xm/MenuShell.h>
56 #include <Xm/MessageB.h>
57 #include <X11/Shell.h>
58 #include <X11/StringDefs.h>
76 /* global variables */
78 static Arg args
[NARGS
];
79 static Widget FdlgCaller
;
80 static int helpw
=-1,aboutw
=-1,descw
=-1,fdlgw
=-1,gmxDialog
;
81 static int *pa_index
,*pa_set_index
,*fnm_index
;
82 static bool bFdlgUp
=FALSE
,bDone
=FALSE
,bDescSet
=FALSE
;
83 extern XmString empty_str
;
84 static XmString desc_str
;
86 #define GMXDLG "gmxdlg"
87 #define GMXTOGGLE "gmxtoggle"
88 #define GMXEDIT "gmxedit"
89 #define GMXBUTTON "gmxbutton"
91 #define GMXDESC "gmxdesc"
92 #define GMXSEP "gmxsep"
93 #define GMXHELP "gmxhelp"
94 #define GMXSCROLL "gmxscroll"
95 #define GMXFILE "gmxfile"
97 /* Height handling routines */
98 static windex TopW
=0,NewTopW
=0;
99 static void set_top_windex(windex t
)
104 static windex
top_windex(void)
107 fatal_error(0,"No top widget");
111 static void new_windex_row(void)
113 if ((NewTopW
== 0) && (TopW
!= 0)) {
115 fprintf(debug
,"Empty windex row!\n");
123 /******************************************************************
125 * C A L L B A C K R O U T I N E S
127 ******************************************************************/
129 static void cancel_callback(Widget w
,caddr_t client_data
,caddr_t call_data
)
131 printf("Maybe next time...\n");
136 static void ok_callback(Widget w
,caddr_t client_data
,caddr_t call_data
)
141 static void help_callback(Widget w
,caddr_t client_data
,caddr_t call_data
)
143 XtManageChild(get_widget(helpw
));
146 static void help_ok_callback(Widget w
,caddr_t client_data
,caddr_t call_data
)
148 XtUnmanageChild(get_widget(helpw
));
151 static void about_callback(Widget w
,caddr_t client_data
,caddr_t call_data
)
153 XtManageChild(get_widget(aboutw
));
156 static void about_ok_callback(Widget w
,caddr_t client_data
,caddr_t call_data
)
158 XtUnmanageChild(get_widget(aboutw
));
161 static void file_callback(Widget www
,caddr_t client_data
,caddr_t call_data
)
169 fprintf(stderr
,"Only one file selector box at a time!\n");
171 fdlg
= get_widget(fdlgw
);
172 if ((ftp
= get_widget_ftp(www
)) != -1) {
173 xms
= char2xms(ftp2filter(ftp
));
175 XtSetArg(args
[narg
],XmNdirMask
,xms
); narg
++;
176 XtSetArg(args
[narg
],XmNpattern
,xms
); narg
++;
177 XtSetArg(args
[narg
],XmNlistUpdated
, False
); narg
++;
179 XtSetValues(fdlg
,args
,narg
);
184 FdlgCaller
= get_widget_other(get_windex(www
),TRUE
);
189 static void file_ok_callback(Widget www
,int *which
,
190 XmFileSelectionBoxCallbackStruct
*xmf
)
193 if ((xmf
->reason
== XmCR_OK
) && (xmf
->length
> 0))
194 set_widget_dir(FdlgCaller
,xmf
->value
);
196 XtUnmanageChild(get_widget(fdlgw
));
201 static void file_cancel_callback(Widget www
,int *which
,
202 XmFileSelectionBoxCallbackStruct
*xmf
)
205 XtUnmanageChild(get_widget(fdlgw
));
210 static void enter_callback(Widget www
,int *which
,caddr_t call_data
)
215 if (have_windex_desc(get_windex(www
))) {
217 XtSetArg(args
[narg
],XmNlabelString
,get_widget_desc(www
)); narg
++;
218 XtSetValues(get_widget(descw
),args
,narg
);
224 static void leave_callback(Widget www
,int *which
,caddr_t call_data
)
231 XtSetArg(args
[narg
],XmNlabelString
,desc_str
); narg
++;
232 XtSetValues(get_widget(descw
),args
,narg
);
238 /************************************************************************
240 * S E T T I N G U P T H E D I A L O G B O X
242 ************************************************************************/
244 static void mk_desc_handlers(void)
249 for(i
=0; (i
<nwidget()); i
++) {
250 if (have_windex_desc(i
)) {
252 XtAddEventHandler(www
,EnterWindowMask
,True
,
253 (XtEventHandler
) enter_callback
,&i
);
254 XtAddEventHandler(www
,LeaveWindowMask
,True
,
255 (XtEventHandler
) leave_callback
,&i
);
258 empty_str
= char2xms("");
261 static int mk_toggle(int parent
,char *title
,int top
,int left
,
262 bool bStatus
,char *desc
)
268 XtSetArg(args
[narg
],XmNtopAttachment
, XmATTACH_FORM
); narg
++;
271 XtSetArg(args
[narg
],XmNtopAttachment
, XmATTACH_WIDGET
); narg
++;
272 XtSetArg(args
[narg
],XmNtopWidget
, get_widget(top
)); narg
++;
274 XtSetArg(args
[narg
],XmNleftAttachment
, XmATTACH_POSITION
); narg
++;
275 XtSetArg(args
[narg
],XmNleftPosition
, left
+1); narg
++;
276 XtSetArg(args
[narg
],XmNrightAttachment
,XmATTACH_NONE
); narg
++;
277 /*XtSetArg(args[narg],XmNindicatorType, XmONE_OF_MANY); narg++;*/
278 /*XtSetArg(args[narg],XmNvisibleWhenOff, False); narg++;*/
279 /*XtSetArg(args[narg],XmNselectPixmap*/
280 XtSetArg(args
[narg
],XmNindicatorOn
, True
); narg
++;
282 XtSetArg(args
[narg
],XmNset
, True
); narg
++;
284 XtSetArg(args
[narg
],XmNlabelString
, char2xms(title
)); narg
++;
286 return add_widget(XtCreateWidget(GMXTOGGLE
,xmToggleButtonWidgetClass
,
287 get_widget(parent
),args
,narg
),desc
);
290 static void mk_editor(int paindex
,int parent
,int top
,int left
,
291 char *label
,char *initial_value
,char *desc
)
293 enum { nwcTOGGLE
, nwcTEXT
, NWC
};
296 int rleft
[NWC
] = { 1, 22 };
297 int rright
[NWC
]= { 21, 49 };
301 /* Create & Position the label */
302 wc
[nwcTOGGLE
] = xmToggleButtonWidgetClass
;
303 wc
[nwcTEXT
] = xmTextFieldWidgetClass
;
304 wlab
[nwcTOGGLE
] = GMXTOGGLE
;
305 wlab
[nwcTEXT
] = GMXEDIT
;
307 for(j
=0; (j
<NWC
); j
++) {
310 XtSetArg(args
[narg
],XmNtopAttachment
, XmATTACH_FORM
); narg
++;
313 XtSetArg(args
[narg
],XmNtopAttachment
, XmATTACH_WIDGET
); narg
++;
314 XtSetArg(args
[narg
],XmNtopWidget
, get_widget(top
)); narg
++;
316 XtSetArg(args
[narg
],XmNleftAttachment
, XmATTACH_POSITION
); narg
++;
317 XtSetArg(args
[narg
],XmNleftPosition
, left
+rleft
[j
]); narg
++;
318 if (j
== nwcTOGGLE
) {
319 XtSetArg(args
[narg
],XmNrightAttachment
, XmATTACH_NONE
); narg
++;
322 XtSetArg(args
[narg
],XmNrightAttachment
, XmATTACH_POSITION
); narg
++;
323 XtSetArg(args
[narg
],XmNrightPosition
, left
+rright
[j
]); narg
++;
325 XtSetArg(args
[narg
],XmNbottomAttachment
, XmATTACH_NONE
); narg
++;
327 XtSetArg(args
[narg
],XmNvalue
, initial_value
); narg
++;
330 XtSetArg(args
[narg
],XmNlabelString
, char2xms(label
)); narg
++;
333 fprintf(debug
,"There are %d args for %s\n",narg
,wlab
[j
]);
334 ww
[j
] = add_widget(XtCreateWidget(wlab
[j
],wc
[j
],
335 get_widget(parent
),args
,narg
),desc
);
337 pa_set_index
[paindex
] = ww
[nwcTOGGLE
];
338 pa_index
[paindex
] = ww
[nwcTEXT
];
341 static void mk_enumerated(int parent
,int top
,int left
,
342 int *wlabel
,int *wtextf
,
343 char *label
,char **but
,char *desc
)
345 enum { nwcTOGGLE
, nwcBUTTON
, NWC
};
348 char *wlab
[NWC
],buf
[256];
349 int rleft
[NWC
] = { 1, 22 };
350 int rright
[NWC
]= { 21, 49 };
354 /* Create & Position the label */
355 wc
[nwcTOGGLE
] = xmToggleButtonWidgetClass
;
357 wlab
[nwcTOGGLE
] = GMXTOGGLE
;
358 wlab
[nwcBUTTON
] = GMXDLG
;
360 for(j
=0; (j
<NWC
); j
++) {
362 XtSetArg(args
[narg
],XmNleftAttachment
, XmATTACH_POSITION
); narg
++;
363 XtSetArg(args
[narg
],XmNleftPosition
, left
+rleft
[j
]); narg
++;
364 if (j
!= nwcTOGGLE
) {
365 XtSetArg(args
[narg
],XmNrightAttachment
, XmATTACH_POSITION
); narg
++;
366 XtSetArg(args
[narg
],XmNrightPosition
, left
+rright
[j
]); narg
++;
369 XtSetArg(args
[narg
],XmNtopAttachment
, XmATTACH_FORM
); narg
++;
372 XtSetArg(args
[narg
],XmNtopAttachment
, XmATTACH_WIDGET
); narg
++;
373 XtSetArg(args
[narg
],XmNtopWidget
, get_widget(top
)); narg
++;
375 XtSetArg(args
[narg
],XmNbottomAttachment
, XmATTACH_NONE
); narg
++;
377 if (j
== nwcBUTTON
) {
378 ww
[j
] = add_widget(XmCreateOptionMenu(get_widget(parent
),wlab
[j
],
382 XtSetArg(args
[narg
], XmNlabelString
, char2xms(label
)); narg
++;
383 ww
[j
] = add_widget(XtCreateWidget(wlab
[j
],wc
[j
],
384 get_widget(parent
),args
,narg
),desc
);
387 /* Create the popup menu father */
388 pd
= add_widget(XmCreatePulldownMenu(get_widget(parent
),GMXPD
,NULL
,0),
391 /* Now create the popup menu children */
392 set_windex_popup(pd
,TRUE
);
393 set_parent(pd
,get_widget(ww
[nwcBUTTON
]));
394 set_widget_other(pd
,get_widget(ww
[nwcTOGGLE
]));
396 for(i
=1; (but
[i
] != NULL
); i
++) {
397 sprintf(buf
,"%s = %s",desc
,but
[i
]);
399 XtSetArg(args
[narg
],XmNlabelString
,char2xms(but
[i
])); narg
++;
400 wi
= add_widget(XtCreateWidget(GMXBUTTON
,xmPushButtonWidgetClass
,
401 get_widget(pd
),args
,narg
),buf
);
402 set_parent(wi
,get_widget(pd
));
405 /* Tell the option menu what to do */
406 XtVaSetValues(get_widget(ww
[nwcBUTTON
]),
407 /*XmNlabelString, str,*/
408 XmNsubMenuId
, get_widget(pd
),
412 *wtextf
= ww
[nwcBUTTON
];
415 static void mk_buttons(int parent
,int top
,int nb
,t_button bbb
[])
417 int i
,narg
,nw
,left
,right
,bw
;
421 dx
= (100-(nb
+1)*nw
)/(real
)nb
;
423 for(i
=0; (i
<nb
); i
++) {
424 left
= nw
*(i
+1)+i
*dx
;
427 XtSetArg(args
[narg
],XmNtopAttachment
, XmATTACH_WIDGET
); narg
++;
428 XtSetArg(args
[narg
],XmNtopWidget
, get_widget(top
)); narg
++;
430 XtSetArg(args
[narg
],XmNleftAttachment
, XmATTACH_FORM
); narg
++;
433 XtSetArg(args
[narg
],XmNleftAttachment
, XmATTACH_POSITION
); narg
++;
434 XtSetArg(args
[narg
],XmNleftPosition
, left
); narg
++;
437 XtSetArg(args
[narg
],XmNrightAttachment
, XmATTACH_FORM
); narg
++;
440 XtSetArg(args
[narg
],XmNrightAttachment
, XmATTACH_POSITION
); narg
++;
441 XtSetArg(args
[narg
],XmNrightPosition
, right
); narg
++;
443 XtSetArg(args
[narg
],XmNlabelString
,char2xms(bbb
[i
].label
)); narg
++;
444 bw
= add_widget(XtCreateWidget(GMXBUTTON
,xmPushButtonWidgetClass
,
445 get_widget(parent
),args
,narg
),
447 XtAddCallback(get_widget(bw
),XmNactivateCallback
,
448 (XtCallbackProc
) bbb
[i
].cbfn
,NULL
);
452 static XmString
xs_str_array_to_xmstr(char *header
,int ndesc
,char *desc
[])
456 char *ptr
,*cptr
,*nlptr
;
461 xmstr
= char2xms(header
);
462 for(i
=0; (i
<ndesc
); i
++) {
463 xmstr
= XmStringConcat(xmstr
,XmStringSeparatorCreate());
464 ptr
= check_tty(desc
[i
]);
465 cptr
= wrap_lines(ptr
,70,0);
467 while ((nlptr
= strchr(ptr
,'\n')) != NULL
) {
469 xmstr
= XmStringConcat(xmstr
,char2xms(ptr
));
470 xmstr
= XmStringConcat(xmstr
,XmStringSeparatorCreate());
475 xmstr
= XmStringConcat(xmstr
,char2xms(ptr
));
482 static windex
mk_separator(windex parent
,windex topw
)
488 XtSetArg(args
[narg
],XmNtopAttachment
, XmATTACH_WIDGET
); narg
++;
491 XtSetArg(args
[narg
],XmNtopWidget
, get_widget(topw
)); narg
++;
494 XtSetArg(args
[narg
],XmNtopAttachment
, XmATTACH_FORM
); narg
++;
496 XtSetArg(args
[narg
],XmNleftAttachment
, XmATTACH_FORM
); narg
++;
497 XtSetArg(args
[narg
],XmNrightAttachment
, XmATTACH_FORM
); narg
++;
499 sep
= add_widget(XtCreateWidget(GMXSEP
,xmSeparatorWidgetClass
,
500 get_widget(parent
),args
,narg
),NULL
);
507 static int mk_helplabel(int parent
,int top
)
510 char buf
[] = "Place the mouse over an item to get information";
512 desc_str
= char2xms(buf
);
514 XtSetArg(args
[narg
],XmNtopAttachment
, XmATTACH_WIDGET
); narg
++;
515 XtSetArg(args
[narg
],XmNtopWidget
, get_widget(top
)); narg
++;
516 XtSetArg(args
[narg
],XmNleftAttachment
, XmATTACH_FORM
); narg
++;
517 XtSetArg(args
[narg
],XmNrightAttachment
, XmATTACH_FORM
); narg
++;
518 XtSetArg(args
[narg
],XmNalignment
, XmALIGNMENT_BEGINNING
); narg
++;
519 XtSetArg(args
[narg
],XmNlabelString
, desc_str
); narg
++;
521 return add_widget(XmCreateLabel(get_widget(parent
),GMXDESC
,args
,narg
),NULL
);
524 static windex
mk_filedlgs(int parent
,int top
,int nfile
,
525 t_filenm fnm
[],int fnm_index
[])
527 enum { nwcLABEL
, nwcTEXT
, nwcFDLG
, NWC
};
529 int left
[NWC
] = { 1, 12, 39 };
530 int right
[NWC
] = { 11, 38, 49 };
532 int i
,j
,ftp
,narg
,dx
,www
[NWC
];
536 wc
[nwcTEXT
] = xmTextFieldWidgetClass
;
537 wc
[nwcFDLG
] = xmPushButtonWidgetClass
;
539 /* Make the compiler happy */
543 wname
[nwcLABEL
] = GMXTOGGLE
;
544 wname
[nwcTEXT
] = GMXEDIT
;
545 wname
[nwcFDLG
] = GMXBUTTON
;
546 for(i
=0; (i
<nfile
); i
++) {
549 sprintf(dbuf
,"%s [%s]",ftp2desc(ftp
),fileopt(fnm
[i
].flag
));
550 if ((fn
= strrchr(fnm
[i
].fn
,'/')) == NULL
)
555 if (is_optional(&(fnm
[i
])))
556 wc
[nwcLABEL
] = xmToggleButtonWidgetClass
;
558 wc
[nwcLABEL
] = xmLabelWidgetClass
;
560 for(j
=0; (j
<NWC
); j
++) {
564 XtSetArg(args
[narg
],XmNtopAttachment
, XmATTACH_FORM
); narg
++;
567 XtSetArg(args
[narg
],XmNtopAttachment
, XmATTACH_WIDGET
); narg
++;
568 XtSetArg(args
[narg
],XmNtopWidget
, get_widget(top
)); narg
++;
572 XtSetArg(args
[narg
],XmNtopAttachment
, XmATTACH_WIDGET
); narg
++;
573 XtSetArg(args
[narg
],XmNtopWidget
, topw
); narg
++;
576 XtSetArg(args
[narg
],XmNleftAttachment
, XmATTACH_POSITION
); narg
++;
577 XtSetArg(args
[narg
],XmNleftPosition
, dx
+left
[j
]); narg
++;
581 XtSetArg(args
[narg
],XmNrightAttachment
, XmATTACH_POSITION
); narg
++;
582 XtSetArg(args
[narg
],XmNrightPosition
, dx
+right
[j
]); narg
++;
586 XtSetArg(args
[narg
],XmNlabelString
, char2xms(fnm
[i
].opt
)); narg
++;
589 XtSetArg(args
[narg
],XmNlabelString
, char2xms("Browse")); narg
++;
592 XtSetArg(args
[narg
],XmNvalue
, fnm
[i
].fn
); narg
++;
595 www
[j
] = add_widget(XtCreateWidget(wname
[j
],wc
[j
],
596 get_widget(parent
),args
,narg
),dbuf
);
598 fnm_index
[i
] = www
[nwcTEXT
];
599 set_windex_orignm(www
[nwcTEXT
],fnm
[i
].fn
);
600 set_widget_ftp(www
[nwcFDLG
],ftp
);
601 set_widget_other(www
[nwcFDLG
],get_widget(www
[nwcTEXT
]));
603 if (is_optional(&(fnm
[i
])))
604 set_widget_other(www
[nwcTEXT
],get_widget(www
[nwcLABEL
]));
606 XtAddCallback(get_widget(www
[nwcFDLG
]),XmNactivateCallback
,
607 (XtCallbackProc
) file_callback
,NULL
);
609 topw
= get_widget(www
[nwcTEXT
]);
614 return mk_separator(parent
,nwidget()-2);
619 static bool motif_hidden(t_pargs
*pa
)
621 return (is_hidden(pa
) ||
622 (strcmp(pa
->option
,"-X") == 0) ||
623 (strcmp(pa
->option
,"-h") == 0));
626 static windex
mk_pargs(int parent
,int npargs
,t_pargs pa
[],int pa_index
[],
629 /**************************************************************
631 * Create all the children in two passes:
632 * 1st the checkboxes (etBOOL variables)
633 * 2nd the editable fields
634 * Return the index of the separator (or the last created widget)
636 **************************************************************/
637 int icb
,i
,npa
,dummy
,separator
,nbool
,nedit
,nenum
,nelem
,left
;
639 char buf
[132],descbuf
[132];
641 /* Make the compiler happy */
644 /* First round just count booleans and editors */
645 nbool
= nedit
= nenum
= 0;
646 for(i
=0; (i
<npargs
); i
++) {
647 if (!motif_hidden(&(pa
[i
]))) {
648 if (pa
[i
].type
== etBOOL
)
650 else if (pa
[i
].type
== etENUM
)
658 bwidth
= (100.0/nbool
);
663 set_top_windex(topw
);
665 for(icb
=0; (icb
<3); icb
++) {
668 for(i
=0; (i
<npargs
); i
++) {
671 if (!motif_hidden(&(pa
[i
]))) {
672 sprintf(descbuf
,"%s (%s)",pa
[i
].desc
,argtp
[pa
[i
].type
]);
673 switch (pa
[i
].type
) {
677 left
= ((npa
% nbool
)*bwidth
)+0.5;
679 fprintf(debug
,"%s,%d: nbool %d, bwidth %g, left %d, topw %d\n",
680 __FILE__
,__LINE__
,nbool
,bwidth
,left
,topw
);
681 pa_index
[i
] = mk_toggle(parent
,pa
[i
].option
,topw
,
682 left
,*(pa
[i
].u
.b
),descbuf
);
688 left
= (npa
% nenum
)*50;
689 mk_enumerated(parent
,topw
,left
,&dummy
,&(pa_index
[i
]),
690 pa
[i
].option
,pa
[i
].u
.c
,descbuf
);
696 switch (pa
[i
].type
) {
698 sprintf(buf
,"%g",*(pa
[i
].u
.r
));
701 sprintf(buf
,"%g %g %g",(*pa
[i
].u
.rv
)[XX
],
702 (*pa
[i
].u
.rv
)[YY
],(*pa
[i
].u
.rv
)[ZZ
]);
705 sprintf(buf
,"%d",*(pa
[i
].u
.i
));
708 if (*(pa
[i
].u
.c
) != NULL
)
709 strcpy(buf
,*(pa
[i
].u
.c
));
715 fprintf(debug
,"%s,%d: buf = %s\n",__FILE__
,__LINE__
,buf
);
716 left
= (npa
% nelem
)*50;
717 mk_editor(i
,parent
,topw
,left
,pa
[i
].option
,buf
,descbuf
);
724 set_top_windex(pa_index
[i
]);
725 if ((npa
% nelem
) == 0)
732 separator
= mk_separator(parent
,top_windex());
738 static void append_str(char **buf
,int *blen
,int *maxlen
,char *str
,
745 ptr
= check_tty(str
);
749 sprintf(nptr
,"* %s",ptr
);
750 str
= wrap_lines(nptr
,width
,indent
);
753 str
= wrap_lines(ptr
,width
,indent
);
755 /*while ((ptr = strstr(str,"\n\n")) != 0)
760 while (*blen
+slen
+1 > *maxlen
) {
761 srenew((*buf
),*maxlen
+DELTA
);
762 for(i
=(*maxlen
); (i
<(*maxlen
)+DELTA
); i
++)
772 static char *concat_str(char *dtitle
,int ndesc
,char *desc
[],
773 char *btitle
,int nbugs
,char *bugs
[])
778 int i
,blen
=0,maxlen
=0,dlen
;
780 append_str(&ptr
,&blen
,&maxlen
,dtitle
,0);
782 for(i
=0; (buf
[i
] != '\0'); i
++)
784 append_str(&ptr
,&blen
,&maxlen
,buf
,0);
787 append_str(&ptr
,&blen
,&maxlen
,"none?",0);
789 /* Count the length of the strings together */
791 for(i
=0; (i
<ndesc
); i
++) {
792 dlen
+= strlen(desc
[i
])+1;
795 for(i
=0; (i
<ndesc
); i
++) {
796 strcat(descer
,desc
[i
]);
800 append_str(&ptr
,&blen
,&maxlen
,descer
,0);
803 append_str(&ptr
,&blen
,&maxlen
," ",0);
804 append_str(&ptr
,&blen
,&maxlen
,btitle
,0);
806 for(i
=0; (buf
[i
] != '\0'); i
++)
808 append_str(&ptr
,&blen
,&maxlen
,buf
,0);
811 for(i
=0; (i
<nbugs
); i
++) {
812 append_str(&ptr
,&blen
,&maxlen
,bugs
[i
],2);
817 static int low_mk_help(Widget parent
,
818 char *dtitle
,int ndesc
,char *desc
[],
819 char *btitle
,int nbugs
,char *bugs
[],
820 XtCallbackProc ok_callback
)
822 windex text
,sep
,ok
,sw
;
826 /* Create the mother of all help windows */
827 sprintf(buf
,"Gromacs Help - %s",ShortProgram());
829 XtSetArg(args
[narg
],XmNdialogTitle
,char2xms(buf
)); narg
++;
830 awin
= add_widget(XmCreateFormDialog(parent
,GMXHELP
,args
,narg
),buf
);
832 ptr
= concat_str(dtitle
,ndesc
,desc
,btitle
,nbugs
,bugs
);
834 /* Now create the contents */
836 XtSetArg(args
[narg
],XmNheight
, 480); narg
++;
837 XtSetArg(args
[narg
],XmNwidth
, 570); narg
++;
838 XtSetArg(args
[narg
],XmNeditMode
, XmMULTI_LINE_EDIT
); narg
++;
839 XtSetArg(args
[narg
],XmNeditable
, FALSE
); narg
++;
840 XtSetArg(args
[narg
],XmNvalue
, ptr
); narg
++;
841 XtSetArg(args
[narg
],XmNtopAttachment
, XmATTACH_FORM
); narg
++;
842 XtSetArg(args
[narg
],XmNleftAttachment
, XmATTACH_FORM
); narg
++;
843 XtSetArg(args
[narg
],XmNrightAttachment
, XmATTACH_FORM
); narg
++;
844 XtSetArg(args
[narg
],XmNscrollingPolicy
, XmAUTOMATIC
); narg
++;
845 XtSetArg(args
[narg
],XmNscrollBarDisplayPolicy
,XmAUTOMATIC
); narg
++;
846 text
= add_widget(XmCreateScrolledText(get_widget(awin
),GMXHELP
,
848 "There is supposed to be useful information in the help window");
849 sw
= add_widget(XtParent(get_widget(text
)),NULL
);
850 sep
= mk_separator(awin
,sw
);
853 XtSetArg(args
[narg
],XmNtopAttachment
, XmATTACH_WIDGET
); narg
++;
854 XtSetArg(args
[narg
],XmNtopWidget
, get_widget(sep
)); narg
++;
855 XtSetArg(args
[narg
],XmNleftAttachment
, XmATTACH_FORM
); narg
++;
856 XtSetArg(args
[narg
],XmNrightAttachment
, XmATTACH_FORM
); narg
++;
857 XtSetArg(args
[narg
],XmNalignment
, XmALIGNMENT_CENTER
); narg
++;
858 XtSetArg(args
[narg
],XmNbottomAttachment
,XmATTACH_FORM
); narg
++;
859 XtSetArg(args
[narg
],XmNlabelString
, char2xms("OK")); narg
++;
860 ok
= add_widget(XmCreatePushButton(get_widget(awin
),
861 GMXBUTTON
,args
,narg
),
862 "Press OK to close the helpwindow");
863 XtAddCallback(get_widget(ok
),XmNactivateCallback
,ok_callback
,NULL
);
865 /* Now manage all except the mother of all help windows */
866 XtManageChild(get_widget(ok
));
867 XtManageChild(get_widget(sw
));
868 XtManageChild(get_widget(text
));
869 XtManageChild(get_widget(sep
));
874 static int mk_help(Widget base
,int ndesc
,char *desc
[],int nbugs
,char *bugs
[])
876 return low_mk_help(base
,"DESCRIPTION:",ndesc
,desc
,
877 "DIAGNOSTICS:",nbugs
,bugs
,(XtCallbackProc
) help_ok_callback
);
880 static int mk_about(Widget base
)
883 "Starting with version 2.0 GROMACS has an X/Motif graphical user interface (GUI) to all",
884 "programs. The command line interface is translated automatically into",
885 "a dialog box which should make life a bit easier for those new to the",
886 "programs. A drawback of this approach is that the options are usually",
887 "short, and therefore not very desriptive. In the GUI there is a line with",
888 "extra information at the bottom, which informs you about the option under",
889 "the mouse cursor.[PAR]",
890 "Note that in the following description all possible elements of the GUI",
891 "are described, but your program need not have all these option types.[PAR]",
892 "In the upper pane of the dialog box you find the file options. These can",
893 "be manually edited or using a File selector box under the [BB]Browse[bb]",
894 "button. Note that some files are optional, only if you tick the box before the",
895 "option the program will actually use the file. If you use the File selector",
896 "box to select a file the option will be used automatically. If you change your",
897 "mind about the option you can turn it off again using the tick box.[PAR]",
898 "In the second pane of the dialog box you will find a number of Toggle buttons",
899 "with which you can turn flags on and off.[PAR]",
900 "In the third pane of the dialog box there are options which can take",
901 "a limited set of values (enumerated in programmers jargon). This is implemented",
902 "in the GUI using a popup menu.[PAR]",
903 "In the fourth pane you find the options which require you to type (yuckie!)",
904 "a numeric or textual argument (note that the description window indicates",
905 "which kind of argument). The validity of what you type is *not* checked",
906 "by the GUI as this does not know what the options mean. Instead the program",
907 "using the GUI will (hopefully) verify that your input is meaningful.[PAR]",
908 "In the fifth pane you find the usual buttons, [BB]OK[bb], [BB]Cancel[bb],",
909 "[BB]Help[bb], and [BB]About[bb] which presumably don't need any explanation.[PAR]",
910 "The GUI was written by David van der Spoel (comments to spoel@xray.bmc.uu.se)[PAR]",
914 #define NABOUT asize(about)
916 static char *mbugs
[] = {
917 "The file selector box generates a core dump under Linux/lesstif0.86",
918 "The file selector box does not work with multiple file selections yet",
919 "It took about 1500 lines of pretty ugly C code to get this dialog box working"
922 about
[NABOUT
-1] = cool_quote();
924 return low_mk_help(base
,
925 "ABOUT THE GROMACS MOTIF USER INTERFACE",asize(about
),about
,
926 "PROBLEMS IN THE GUI",asize(mbugs
),mbugs
,
927 (XtCallbackProc
) about_ok_callback
);
930 static void mk_fdlg(Widget base
)
935 XtSetArg(args
[narg
],XmNdialogTitle
,char2xms("GMX File selector")); narg
++;
936 fdlgw
= add_widget(XmCreateFileSelectionDialog(base
,GMXFILE
,args
,narg
),NULL
);
937 XtAddCallback(get_widget(fdlgw
),XmNokCallback
,
938 (XtCallbackProc
) file_ok_callback
,NULL
);
939 XtAddCallback(XmFileSelectionBoxGetChild(get_widget(fdlgw
),
940 XmDIALOG_CANCEL_BUTTON
),
942 (XtCallbackProc
) file_cancel_callback
,NULL
);
943 XtUnmanageChild(XmFileSelectionBoxGetChild(get_widget(fdlgw
),
944 XmDIALOG_HELP_BUTTON
));
946 /* Make the filter fixed... */
948 XtSetArg(args
[narg
],XmNeditable
,False
); narg
++;
949 XtSetValues(XmFileSelectionBoxGetChild(get_widget(fdlgw
),
950 XmDIALOG_FILTER_TEXT
),args
,narg
);
953 static void mk_gui(Widget gmxBase
,
954 int nfile
,t_filenm fnm
[],int npargs
,t_pargs pa
[],
955 int ndesc
,char *desc
[],int nbugs
,char *bugs
[])
957 /****************************************************************
959 * M A K E G U I F O R G R O M A C S
961 ****************************************************************/
963 { "OK", "Press OK to accept current settings and continue",
965 { "Cancel", "Press Cancel to quit the program",
967 { "Help", "Press Help for more information about the program",
969 { "About", "Press About for information about using this dialog box",
972 #define NBUT asize(bbb)
976 /* Make the compiler happy */
979 /* Create the help window */
980 helpw
= mk_help(gmxBase
,ndesc
,desc
,nbugs
,bugs
);
982 /* Create the about window */
983 aboutw
= mk_about(gmxBase
);
985 /* Create the file selector box */
988 /* Create the dialog box! */
989 gmxDialog
= add_widget(XmCreateForm(gmxBase
,GMXDLG
,NULL
,0),NULL
);
990 XtManageChild(get_widget(gmxDialog
));
994 /* Create buttons for file dialogboxes */
996 snew(fnm_index
,nfile
);
997 sep1
= mk_filedlgs(gmxDialog
,gmxDialog
,nfile
,fnm
,fnm_index
);
1000 /* Create the checkboxes and editable fields */
1002 snew(pa_index
,npargs
);
1003 snew(pa_set_index
,npargs
);
1004 sep1
= mk_pargs(gmxDialog
,npargs
,pa
,pa_index
,sep1
);
1009 /* Create & count the buttons */
1010 mk_buttons(gmxDialog
,sep1
,NBUT
,bbb
);
1012 /* Create & Position the separator */
1013 sep2
= mk_separator(gmxDialog
,-1);
1015 /* Create help label */
1016 descw
= mk_helplabel(gmxDialog
,sep2
);
1018 /* Make eventhandlers for the help line */
1021 /* Give the children a father or mother */
1022 for(i
=widg0
; (i
<nwidget()); i
++)
1023 if (!get_windex_popup(i
))
1024 XtManageChild(get_widget(i
));
1027 /***************************************************************************
1031 ***************************************************************************/
1033 static void MyMainLoop(XtAppContext appcontext
,Widget gmxBase
,
1034 int nfile
,t_filenm fnm
[],int npargs
,t_pargs pa
[])
1041 char *fn
,buf
[256],*ptr
;
1042 double ddd
,dx
,dy
,dz
;
1046 XtAppNextEvent(appcontext
,&event
);
1047 XtDispatchEvent(&event
);
1049 /* Extract all the information from the X widgets */
1050 for(i
=0; (i
<nfile
); i
++) {
1051 www
= get_widget(fnm_index
[i
]);
1053 XtSetArg(args
[narg
], XmNvalue
, &fn
); narg
++;
1054 XtGetValues(www
,args
,narg
);
1055 sprintf(buf
,"%s%s",get_widget_dir(fnm_index
[i
]),fn
);
1058 fnm
[i
].fn
= strdup(buf
);
1059 if (is_optional(&(fnm
[i
]))) {
1060 www
= get_widget_other(fnm_index
[i
],FALSE
);
1063 XtSetArg(args
[narg
],XmNset
,&xmrb
); narg
++;
1064 XtGetValues(www
,args
,narg
);
1066 fnm
[i
].flag
= fnm
[i
].flag
| ffSET
;
1069 fatal_error(0,"No toggle button for optional file (option %s)",
1071 if (strcmp(fnm
[i
].fn
,get_windex_orignm(fnm_index
[i
])) != 0) {
1073 fprintf(debug
,"File corr. to option %s has been modified from\n"
1074 "'%s' to '%s'\n",fnm
[i
].opt
,
1075 get_windex_orignm(fnm_index
[i
]),fnm
[i
].fn
);
1077 fnm
[i
].flag
= fnm
[i
].flag
| ffSET
;
1081 fprintf(debug
,"%s,%d: File is now %s\n",__FILE__
,__LINE__
,buf
);
1084 for(i
=0; (i
<npargs
); i
++) {
1085 if (!is_hidden(&pa
[i
])) {
1086 if (pa
[i
].type
== etBOOL
) {
1088 XtSetArg(args
[narg
],XmNset
, &bbb
); narg
++;
1089 XtGetValues(get_widget(pa_index
[i
]),args
,narg
);
1090 *(pa
[i
].u
.b
) = (bbb
== True
);
1092 fprintf(debug
,"%s,%d: Boolean (windex %d) %s = %s\n",__FILE__
,__LINE__
,
1093 pa_index
[i
],pa
[i
].option
,bool_names
[*(pa
[i
].u
.b
)]);
1096 /* Check whether it is set */
1098 XtSetArg(args
[narg
],XmNset
, &bbb
); narg
++;
1099 XtGetValues(get_widget(pa_set_index
[i
]),args
,narg
);
1100 pa
[i
].bSet
= (bbb
== True
);
1102 /* Now extract the value */
1103 if (pa
[i
].type
== etENUM
) {
1104 /* First get the selected widget */
1106 XtSetArg(args
[narg
],XmNmenuHistory
, &wsub
); narg
++;
1107 XtGetValues(get_widget(pa_index
[i
]),args
,narg
);
1108 /* Now get it's label! */
1110 XtSetArg(args
[narg
],XmNlabelString
, &xms
); narg
++;
1111 XtGetValues(wsub
,args
,narg
);
1112 ptr
= xms2char(xms
);
1116 XtSetArg(args
[narg
],XmNvalue
, &ptr
); narg
++;
1117 XtGetValues(get_widget(pa_index
[i
]),args
,narg
);
1120 fprintf(debug
,"%s,%d: I found option %s value %s\n",
1121 __FILE__
,__LINE__
,pa
[i
].option
,ptr
);
1122 switch (pa
[i
].type
) {
1124 if (sscanf(ptr
,"%lf",&ddd
) != 1)
1125 fprintf(stderr
,"Warning: invalid entry (%s) for real value %s, using default %g\n",
1126 ptr
,pa
[i
].option
,*(pa
[i
].u
.r
));
1131 if (sscanf(ptr
,"%lf%lf%lf",&dx
,&dy
,&dz
) != 3)
1132 fprintf(stderr
,"Warning: invalid entry (%s) for rvec value %s, using default (%g,%g,%g)\n",
1133 ptr
,pa
[i
].option
,(*pa
[i
].u
.rv
)[XX
],(*pa
[i
].u
.rv
)[YY
],
1136 (*pa
[i
].u
.rv
)[XX
] = dx
;
1137 (*pa
[i
].u
.rv
)[YY
] = dy
;
1138 (*pa
[i
].u
.rv
)[ZZ
] = dz
;
1142 if (sscanf(ptr
,"%d",&iii
) != 1)
1143 fprintf(stderr
,"Warning: invalid entry (%s) for integer value %s, using default %d\n",
1144 ptr
,pa
[i
].option
,*(pa
[i
].u
.i
));
1149 *(pa
[i
].u
.c
) = strdup(ptr
);
1152 pa
[i
].u
.c
[0] = strdup(ptr
);
1159 /* Clean up windows */
1160 XtUnmanageChild(get_widget(gmxDialog
));
1161 XtUnmanageChild(get_widget(fdlgw
));
1162 XtUnmanageChild(get_widget(helpw
));
1163 XtUnrealizeWidget(gmxBase
);
1164 XtDestroyApplicationContext(appcontext
);
1167 void gmx_gui(int *argc
,char *argv
[],
1168 int nfile
,t_filenm fnm
[],int npargs
,t_pargs pa
[],
1169 int ndesc
,char *desc
[],int nbugs
,char *bugs
[])
1172 XtAppContext appcontext
;
1173 String Fallbacks
[] = {
1174 "*gmx*background: lightgrey",
1175 /*"*gmxdlg.background: lightgrey",
1176 "*gmxbutton.background: lightskyblue",
1177 "*gmxtoggle.background: lightgrey",
1178 "*gmxedit.background: lightgoldenrod1",
1179 "*gmxdesc.background: lightsalmon1",
1180 "*gmxsep.background: darkgrey",
1181 "*gmxhelp.background: lightgoldenrod1",
1182 "*gmxhelpSW.background: lightgrey",
1183 "*gmxhelpSW.*.background: lightgrey",
1184 "*gmxfile.*.background: lightgrey",
1185 "*gmxfile.Text.background: lightgoldenrod1",*/
1189 /* Initialize toolkit and parse command line options. */
1190 gmxBase
= XtOpenApplication(&appcontext
,"gmx",NULL
,0,argc
,argv
,Fallbacks
,
1191 applicationShellWidgetClass
,NULL
,0);
1193 mk_gui(gmxBase
,nfile
,fnm
,npargs
,pa
,ndesc
,desc
,nbugs
,bugs
);
1194 XtRealizeWidget(gmxBase
);
1195 MyMainLoop(appcontext
,gmxBase
,nfile
,fnm
,npargs
,pa
);