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