1fca2e61a9193864cfe3f3a58769760cd40a559a
[alexxy/gromacs.git] / src / ngmx / ngmx.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 <ctype.h>
40 #include <string.h>
41
42 #include "sysstuff.h"
43 #include "macros.h"
44 #include "smalloc.h"
45 #include "gmx_fatal.h"
46 #include "typedefs.h"
47 #include "string2.h"
48 #include "statutil.h"
49 #include "Xstuff.h"
50 #include "gromacs.bm"
51 #include "copyrite.h"
52 #include "confio.h"
53 #include "dialogs.h"
54 #include "writeps.h"
55 #include "molps.h"
56 #include "nmol.h"
57 #include "tpxio.h"
58
59 /* Forward declarations: I Don't want all that init shit here */
60 void init_gmx(t_x11 *x11,char *program,int nfile,t_filenm fnm[],
61               const output_env_t oenv);
62
63 static void dump_xw(char *dispname,Window w,char *fn)
64 {
65   char comm[256];
66   int  rc;
67
68   sprintf(comm,"xwd -id %d -display %s > %s",(int)w,dispname,fn);
69
70 #ifdef GMX_NO_SYSTEM
71   printf("Warning-- No calls to system(3) supported on this platform.");
72   printf("Warning-- Skipping execution of 'system(\"%s\")'.", buf);
73 #else
74   rc=system(comm);
75 #endif
76 }
77
78 static void dump_it(t_manager *man)
79 {
80   t_psdata ps;
81   
82   ps=ps_open("ngmx.ps",0,0,man->molw->wd.width,man->molw->wd.height);
83   ps_draw_mol(ps,man);
84   ps_close(ps);
85 }
86
87 static void done_gmx(t_x11 *x11,t_gmx *gmx)
88 {
89   done_logo(x11,gmx->logo);
90   done_pd(x11,gmx->pd);
91   done_man(x11,gmx->man);
92   done_dlgs(gmx);
93   x11->UnRegisterCallback(x11,gmx->wd->self);
94 }
95
96 static void move_gmx(t_x11 *x11,t_gmx *gmx,int width,int height,
97                      gmx_bool bSizePD)
98 {
99   int y0,wl,hl;
100 #ifdef DEBUG
101   fprintf(stderr,"Move gmx %dx%d\n",width,height);
102 #endif
103   y0=XTextHeight(x11->font);
104   /* Resize PD-Menu */
105   if (bSizePD)
106     XResizeWindow(x11->disp,gmx->pd->wd.self,width,y0);
107
108   XMoveWindow(x11->disp,gmx->man->wd.self,0,y0+1);
109   XResizeWindow(x11->disp,gmx->man->wd.self,width,height-y0-1);
110   
111   wl=gmx->logo->wd.width;
112   hl=gmx->logo->wd.height;
113   XMoveWindow(x11->disp,gmx->logo->wd.self,(width-wl)/2,(height-y0-hl)/2);
114 }
115
116 static gmx_bool HandleClient(t_x11 *x11,int ID,t_gmx *gmx)
117 {
118   t_pulldown *pd;
119   
120   pd=gmx->pd;
121   
122   switch(ID) {
123     /* File Menu */
124   case IDDUMPWIN:
125     write_gmx(x11,gmx,IDDODUMP);
126     break;
127   case IDDODUMP:
128     if (gmx->man->bAnimate) 
129       hide_but(x11,gmx->man->vbox);
130     dump_it(gmx->man);
131     if (gmx->man->bAnimate) 
132       show_but(x11,gmx->man->vbox);
133     break;
134   case IDCLOSE:
135   case IDIMPORT:
136   case IDEXPORT: 
137     ShowDlg(gmx->dlgs[edExport]);
138     break;
139   case IDDOEXPORT:
140     write_sto_conf(gmx->confout,*gmx->man->top.name,
141                    &(gmx->man->top.atoms),
142                    gmx->man->x,NULL,gmx->man->molw->ePBC,gmx->man->box);
143     break;
144   case IDQUIT:
145     show_mb(gmx,emQuit);
146     break;
147   case IDTERM:
148     done_gmx(x11,gmx);
149     return TRUE;
150     
151     /* Edit Menu */
152   case IDEDITTOP: 
153     edit_file("topol.gmx");
154     break;
155   case IDEDITCOORDS: 
156     edit_file("confin.gmx");
157     break;
158   case IDEDITPARAMS: 
159     edit_file("mdparin.gmx");
160     break;
161     
162     /* Display Menu */
163   case IDFILTER:
164     if (gmx->filter)
165       ShowDlg(gmx->dlgs[edFilter]);
166     break;
167   case IDDOFILTER:
168     do_filter(x11,gmx->man,gmx->filter);
169     break;
170   case IDANIMATE: 
171     check_pd_item(pd,IDANIMATE,toggle_animate(x11,gmx->man));
172     break;
173   case IDLABELSOFF:
174     no_labels(x11,gmx->man);
175     break;
176   case IDRESETVIEW: 
177     reset_view(gmx->man->view);
178     ExposeWin(x11->disp,gmx->man->molw->wd.self);
179     break;
180   case IDPHOTO:
181     show_mb(gmx,emNotImplemented);
182     break;
183   case IDBONDOPTS:
184     ShowDlg(gmx->dlgs[edBonds]);
185     break;
186   case IDTHIN:
187     set_bond_type(x11,gmx->man->molw,eBThin);
188     break;
189   case IDFAT:
190     set_bond_type(x11,gmx->man->molw,eBFat);
191     break;
192   case IDVERYFAT:
193     set_bond_type(x11,gmx->man->molw,eBVeryFat);
194     break;
195   case IDBALLS:
196     set_bond_type(x11,gmx->man->molw,eBSpheres);
197     break;
198   case IDNOBOX:
199     set_box_type(x11,gmx->man->molw,esbNone);
200     break;
201   case IDRECTBOX:
202     set_box_type(x11,gmx->man->molw,esbRect);
203     break;
204   case IDTRIBOX:
205     set_box_type(x11,gmx->man->molw,esbTri);
206     break;
207   case IDTOBOX:
208     set_box_type(x11,gmx->man->molw,esbTrunc);
209     break;
210     
211     /* Analysis Menu */
212   case IDBOND: 
213   case IDANGLE: 
214   case IDDIH: 
215   case IDRMS:
216   case IDRDF:
217   case IDENERGIES: 
218   case IDCORR:
219     show_mb(gmx,emNotImplemented);
220     break;
221     
222     /* Help Menu */
223   case IDHELP:
224     show_mb(gmx,emHelp);
225     break;
226   case IDABOUT:
227     show_logo(x11,gmx->logo);
228     break;
229       
230   default:
231     break;
232   }
233   return FALSE;
234 }
235
236 static gmx_bool MainCallBack(t_x11 *x11,XEvent *event, Window w, void *data)
237 {
238   t_gmx *gmx;
239   int   nsel,width,height;
240   gmx_bool  result;
241
242   result = FALSE;
243   gmx=(t_gmx *)data;
244   switch(event->type) {
245   case ButtonRelease:
246     hide_pd(x11,gmx->pd);
247     break;
248   case ConfigureNotify:
249     width=event->xconfigure.width;
250     height=event->xconfigure.height;
251     if ((width!=gmx->wd->width) || (height!=gmx->wd->height))
252       move_gmx(x11,gmx,width,height,TRUE);
253     break;
254   case ClientMessage:
255     hide_pd(x11,gmx->pd);
256     nsel=event->xclient.data.l[0];
257     result = HandleClient(x11,nsel,gmx);
258     break;
259   default:
260     break;
261   }
262   return result;
263 }
264
265 int main(int argc, char *argv[])
266 {
267   const char *desc[] = {
268     "[TT]ngmx[tt] is the GROMACS trajectory viewer. This program reads a",
269     "trajectory file, a run input file and an index file and plots a",
270     "3D structure of your molecule on your standard X Window",
271     "screen. No need for a high end graphics workstation, it even",
272     "works on Monochrome screens.[PAR]",
273     "The following features have been implemented:",
274     "3D view, rotation, translation and scaling of your molecule(s),",
275     "labels on atoms, animation of trajectories,",
276     "hardcopy in PostScript format, user defined atom-filters",
277     "runs on MIT-X (real X), open windows and motif,",
278     "user friendly menus, option to remove periodicity, option to",
279     "show computational box.[PAR]",
280     "Some of the more common X command line options can be used: ",
281     "[TT]-bg[tt], [TT]-fg[tt] change colors, [TT]-font fontname[tt] changes the font."
282   };
283   const char *bugs[] = {
284     "Balls option does not work",
285     "Some times dumps core without a good reason"
286   };
287
288   output_env_t oenv;
289   t_x11 *x11;
290   t_filenm fnm[] = {
291     { efTRX, "-f", NULL, ffREAD },
292     { efTPX, NULL, NULL, ffREAD },
293     { efNDX, NULL, NULL, ffOPTRD }
294   };
295 #define NFILE asize(fnm)
296   
297   CopyRight(stderr,argv[0]);
298   parse_common_args(&argc,argv,PCA_CAN_TIME,NFILE,fnm,
299                     0,NULL,asize(desc),desc,asize(bugs),bugs,&oenv);
300   
301   if ((x11=GetX11(&argc,argv))==NULL) {
302     fprintf(stderr,"Can't connect to X Server.\n"
303             "Check your DISPLAY environment variable\n");
304     exit(1);
305   }
306   init_gmx(x11,argv[0],NFILE,fnm,oenv);
307
308   x11->MainLoop(x11);
309   x11->CleanUp(x11);
310
311   thanx(stderr);
312   
313   return 0;
314 }
315
316 static t_mentry FileMenu[] = {
317   { 0,  IDEXPORT,       FALSE,  "Export..." },
318   { 0,  IDDUMPWIN,      FALSE,  "Print"     },
319   { 0,  IDQUIT,         FALSE,  "Quit"      }
320 };
321
322 static t_mentry DispMenu[] = {
323   { 0,  IDFILTER,       FALSE,  "Filter..." },
324   { 0,  IDANIMATE,      FALSE,  "Animate"   },
325   { 0,  IDLABELSOFF,    FALSE,  "Labels Off"},  
326   { 0,  IDRESETVIEW,    FALSE,  "Reset View"},
327   { 0,  IDBONDOPTS,     FALSE,  "Options..."}
328 };
329
330 static t_mentry HelpMenu[] = {
331   { 0,  IDHELP,         FALSE,  "Help"             },
332   { 0,  IDABOUT,        FALSE,  "About Gromacs..." }
333 };
334
335 static t_mentry *gmx_pd[] = { FileMenu, DispMenu, HelpMenu };
336
337 #define MSIZE asize(gmx_pd)
338
339 static int gmx_pd_size[MSIZE] = {
340   asize(FileMenu), asize(DispMenu), asize(HelpMenu)
341 };
342
343 static const char *MenuTitle[MSIZE] = {
344   "File", "Display", "Help"
345 };
346
347 void init_gmx(t_x11 *x11,char *program,int nfile,t_filenm fnm[], 
348               const output_env_t oenv)
349 {
350   Pixmap               pm;
351   t_gmx                *gmx;
352   XSizeHints           hints;
353   int                  w0,h0;
354   int                  natom,nre,natom_trx;
355   t_topology           top;
356   int                  ePBC;
357   matrix               box;
358   t_trxframe           fr;
359   t_trxstatus          *status;
360   char                 quote[256];
361   
362   snew(gmx,1);
363   snew(gmx->wd,1);
364
365   ePBC = read_tpx_top(ftp2fn(efTPX,nfile,fnm),
366                       NULL,box,&natom,NULL,NULL,NULL,&top);
367
368   read_first_frame(oenv,&status,ftp2fn(efTRX,nfile,fnm),&fr,TRX_DONT_SKIP);
369   close_trx(status);
370   natom_trx = fr.natoms;
371            
372   /* Creates a simple window */
373   w0=DisplayWidth(x11->disp,x11->screen)-132;
374   h0=DisplayHeight(x11->disp,x11->screen)-140;
375   bromacs(quote,255);
376   InitWin(gmx->wd,0,0,w0,h0,3,quote);
377   gmx->wd->self=XCreateSimpleWindow(x11->disp,x11->root,
378                                     gmx->wd->x, gmx->wd->y,
379                                     gmx->wd->width,gmx->wd->height,
380                                     gmx->wd->bwidth,WHITE,BLACK);
381   pm=XCreatePixmapFromBitmapData(x11->disp,x11->root,
382                                  (char *)gromacs_bits,gromacs_width,
383                                  gromacs_height,
384                                  WHITE,BLACK,1);
385   hints.flags=PMinSize;
386   hints.min_width=2*EWIDTH+40;
387   hints.min_height=EHEIGHT+LDHEIGHT+LEGHEIGHT+40;
388   XSetStandardProperties(x11->disp,gmx->wd->self,gmx->wd->text,program,
389                          pm,NULL,0,&hints);
390   
391   x11->RegisterCallback(x11,gmx->wd->self,x11->root,MainCallBack,gmx);
392   x11->SetInputMask(x11,gmx->wd->self,
393                     ButtonPressMask     | ButtonReleaseMask |
394                     OwnerGrabButtonMask | ExposureMask      |
395                     StructureNotifyMask);
396
397   /* The order of creating windows is important here! */
398   /* Manager */
399   gmx->man  = init_man(x11,gmx->wd->self,0,0,1,1,WHITE,BLACK,ePBC,box,oenv);
400   gmx->logo = init_logo(x11,gmx->wd->self,FALSE);
401
402   /* Now put all windows in the proper place */
403   move_gmx(x11,gmx,w0,h0,FALSE);
404   
405   XMapWindow(x11->disp,gmx->wd->self);
406   map_man(x11,gmx->man);
407
408   /* Pull Down menu */
409   gmx->pd=init_pd(x11,gmx->wd->self,gmx->wd->width,
410                   XTextHeight(x11->font),x11->fg,x11->bg,
411                   MSIZE,gmx_pd_size,gmx_pd,MenuTitle);
412
413   /* Dialogs & Filters */
414
415   gmx->filter=init_filter(&(top.atoms),ftp2fn_null(efNDX,nfile,fnm),
416                           natom_trx);
417   
418   init_dlgs(x11,gmx);
419
420   /* Now do file shit */
421   set_file(x11,gmx->man,ftp2fn(efTRX,nfile,fnm),ftp2fn(efTPX,nfile,fnm));
422
423   /*show_logo(x11,gmx->logo);*/
424   
425   ShowDlg(gmx->dlgs[edFilter]);
426 }
427