Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

MolBrowser.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2019 The Board of Trustees of the           
00004  *cr                        University of Illinois                       
00005  *cr                         All Rights Reserved                        
00006  *cr                                                                   
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: MolBrowser.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.44 $      $Date: 2020/07/08 04:34:46 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *   Molecule browser
00019  ***************************************************************************/
00020 
00021 #include "MolBrowser.h"
00022 #include "FL/Fl_Menu_Button.H"
00023 #include "FL/Fl_Menu_Item.H"
00024 #include "FL/Fl_Multi_Browser.H"
00025 #include "FL/forms.H"
00026 #include "frame_selector.h"
00027 
00028 #include "VMDApp.h"
00029 #include "Molecule.h"
00030 #include "MoleculeList.h"
00031 
00032 #if FL_MAJOR_VERSION <= 1
00033 #if FL_MINOR_VERSION < 1
00034 #include "FL/fl_file_chooser.H"
00035 #endif
00036 #endif
00037 
00038 static const int widths[] = { 30, 18, 18, 18, 18, 160, 80, 70, 22, 0 };
00039 
00040 MolBrowser::MolBrowser(VMDApp *vmdapp, MainFltkMenu *mm,
00041                        int x, int y, int xw, int yw)
00042 : Fl_Multi_Browser(x, y, xw, yw), app(vmdapp) {
00043   mainmenu = mm;
00044   dragpending = 0;  
00045   align(FL_ALIGN_TOP_LEFT);
00046   column_widths(widths);
00047   color(VMDMENU_BROWSER_BG);
00048   selection_color(VMDMENU_BROWSER_SEL);
00049 
00050   VMDFLTKTOOLTIP(this, "Select molecule, toggle top/active/drawn/fixed, \nload/save coordinates or trajectory frames, \ndouble-click to rename molecule")
00051 
00052   new Fl_Box(x,   y-20,30,20,"ID");
00053   new Fl_Box(x+32,y-20,18,20,"T");
00054   new Fl_Box(x+50,y-20,18,20,"A");
00055   new Fl_Box(x+68,y-20,18,20,"D");
00056   new Fl_Box(x+86,y-20,18,20,"F");
00057   Fl_Box *b = new Fl_Box(x+102,y-20,220,20,"Molecule");
00058   b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
00059   b = new Fl_Box(x+262,y-20,80,20,"Atoms");
00060   b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
00061   b = new Fl_Box(x+342,y-20,60,20,"Frames");
00062   b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
00063   b = new Fl_Box(x+412,y-20,30,20,"Vol");
00064   b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
00065   end();
00066 }
00067 
00068 int MolBrowser::handle(int type) {
00069 #if 1
00070   // handle paste operations
00071   if (type == FL_PASTE) {
00072     // ignore paste operations that weren't due to drag-and-drop 
00073     // since they could be any arbitrary data/text, and not just filenames.
00074     if (dragpending) {
00075       int len = Fl::event_length();
00076 
00077       // ignore zero-length paste events (why do these occur???)
00078       if (len > 0) {
00079         int numfiles, i;
00080         const char *lastc;
00081         int lasti;
00082         FileSpec spec; 
00083         const char *ctext = Fl::event_text();
00084         char *filename = (char *) malloc((1 + len) * sizeof(char));
00085 
00086         for (lasti=0,lastc=ctext,numfiles=0,i=0; i<len; i++) {
00087           // parse out all but last filename, which doesn't have a CR
00088           if (ctext[i] == '\n') {
00089             memcpy(filename, lastc, (i-lasti)*sizeof(char));
00090             filename[i-lasti] = '\0';
00091 
00092             // attempt to load the file into a new molecule
00093             app->molecule_load(-1, filename, NULL, &spec);
00094 
00095             lasti=i+1;
00096             lastc=&ctext[lasti];
00097             numfiles++;
00098           }
00099 
00100           // special-case last filename, since there's no CR
00101           if (i == (len-1)) {
00102             memcpy(filename, lastc, (1+i-lasti)*sizeof(char));
00103             filename[1+i-lasti] = '\0';
00104 
00105             // attempt to load the file into a new molecule
00106             app->molecule_load(-1, filename, NULL, &spec);
00107             numfiles++;
00108           }
00109         }
00110 
00111         free(filename);
00112       }
00113 
00114       dragpending = 0; // no longer waiting for drag-and-drop paste
00115     }
00116 
00117     return 1; // indicate that we handled the paste operation
00118   }
00119 
00120   // handle drag-and-drop operations
00121   if (type == FL_DND_ENTER || type == FL_DND_DRAG) {
00122     return 1; // indicate that we want the drag-and-drop operation
00123   }
00124   if (type == FL_DND_RELEASE) {
00125     Fl::paste(*this);
00126     dragpending = 1; // flag to expect incoming paste due to DND operation
00127     return 1;
00128   }
00129 #endif
00130 
00131   if (type == FL_RELEASE) {
00132     // update the MainMenu gui in case the molecule selections have changed
00133     if (mainmenu) mainmenu->update_gui_state();
00134   }
00135   
00136   if (type == FL_PUSH && Fl::event_button() == FL_LEFT_MOUSE 
00137       && Fl::event_clicks()) {
00138     // figure out which line is selected; since it's a double click there
00139     // can be only one.
00140     int molid = -1; //unique ID of selected mol
00141     int selmol= -1; //GUI index of the selected mol
00142     
00143     for (int i=1; i<=size(); i++) {
00144       if (selected(i)) { 
00145         selmol = i-1;
00146         molid = app->molecule_id(selmol); 
00147         break;
00148       }
00149     }
00150  
00151     if (molid >= 0) {
00152       char need_more_clicks = FALSE;
00153       
00154       // figure out where on the line the double click occurred. 
00155       int mx = Fl::event_x();
00156       if (mx >= 30 && mx < 48) {
00157         if ( Fl::event_clicks() > 1){ // triple click: single A/T/D molecule
00158           for (int j=1; j<= size(); j++) {
00159             int id = app->molecule_id(j-1);
00160             app->molecule_activate(id, molid == id);
00161             app->molecule_display(id, molid == id);
00162             app->menu_select_mol("graphics", selmol);
00163           }
00164           app->molecule_make_top(molid);
00165           app->scene_resetview();
00166         }
00167         else {
00168           app->molecule_make_top(molid);
00169           need_more_clicks = TRUE;
00170         }
00171       } else if (mx >= 48 && mx < 66) {
00172         app->molecule_activate(molid, !app->molecule_is_active(molid));
00173       } else if (mx >= 66 && mx < 84) {
00174         app->molecule_display(molid, !app->molecule_is_displayed(molid));
00175       } else if (mx >= 84 && mx < 102) {
00176         app->molecule_fix(molid, !app->molecule_is_fixed(molid));
00177       } else if (mx >= 102 && mx < 262) { //rename
00178         // this code snippet is an exact copy of code in MainFltkMenu.C:
00179         const char *oldname = app->molecule_name(molid);
00180         const char *newname = fl_input("Enter a new name for molecule %d:", 
00181           oldname, molid);
00182         if (newname) app->molecule_rename(molid, newname);
00183       } else if (mx >= 332 && mx < 412) { //delete frames
00184         // this code snippet is an exact copy of code in MainFltkMenu.C:
00185         int numframes = app->molecule_numframes(molid);
00186         if (!numframes) {
00187           fl_alert("Molecule %d has no frames to delete!", molid);
00188         } else {
00189           const char *molname = app->molecule_name(molid);
00190           int frst=0, lst=numframes-1, stride=0;
00191           int ok = frame_delete_selector(molname, numframes-1, &frst, &lst, &stride);
00192           if (ok) app->molecule_deleteframes(molid, frst, lst, stride);
00193         }
00194       } 
00195       else need_more_clicks = TRUE;
00196       if (!need_more_clicks) Fl::event_is_click(0);
00197     }
00198   }
00199 
00200   if (mainmenu && type == FL_PUSH && Fl::event_button() == FL_RIGHT_MOUSE) {
00201     const Fl_Menu_Item *menuitem;
00202     menuitem=mainmenu->browserpopup_menuitems->popup(Fl::event_x(), Fl::event_y());
00203     if (menuitem && menuitem->callback()) 
00204       menuitem->do_callback((Fl_Widget *) mainmenu->menubar, menuitem->user_data());
00205     return 1; // do not allow parent to process event
00206   }
00207 
00208   return Fl_Multi_Browser::handle(type);
00209 }
00210 
00211 void MolBrowser::update() {
00212   MoleculeList *mlist = app->moleculeList;
00213   int nummols = mlist->num();
00214 
00215 #if 1
00216   //
00217   // XXX this code updates the state of all of the molecules reliably, but
00218   //     creates a huge performance cost when thousands of molecules are 
00219   //     loaded.  We really need a scheme to create a changelist and apply
00220   //     the changelist to only those molecule browser lines that need updates.
00221   //
00222   if (size() > nummols)
00223     clear();
00224 
00225   for (int i=0; i<nummols; i++) {
00226     char buf[256] = { 0 }; 
00227     char molnamebuf[81] = { 0 };
00228     Molecule *mol = mlist->molecule(i);
00229 
00230     // prevent string length overflows
00231     strncpy(molnamebuf, mol->molname(), sizeof(molnamebuf)-1);
00232 
00233     // display state of active/displayed/fixed by toggling the text color
00234     sprintf(buf, "%d\t%s\t%s\t%s\t%s\t%-13s\t%-9d\t%-7d\t%-3d",
00235       mol->id(),
00236       mlist->is_top(i) ? "T" : " ",
00237       mlist->active(i) ? VMDMENU_MOL_ACTIVE : VMDMENU_MOL_INACTIVE,
00238       mlist->displayed(i) ? VMDMENU_MOL_DISPLAYED : VMDMENU_MOL_NONDISPLAYED,
00239       mlist->fixed(i) ? VMDMENU_MOL_FIXED : VMDMENU_MOL_NONFIXED,
00240       molnamebuf, mol->nAtoms, mol->numframes(), mol->num_volume_data()
00241     );
00242 
00243     if (i < size())
00244       text(i+1, buf); // update existing browser line
00245     else
00246       add(buf); // add a new browser line
00247   }
00248 #else
00249   //
00250   // XXX this code addresses the performance issues associated with the
00251   //     full-update code above, but breaks molecule browser's handling
00252   //     of operations multi-molecule selections.
00253   // 
00254   char buf[256] = { 0 };
00255   char molnamebuf[81] = { 0 };
00256   int need_full_regen = 0;
00257 
00258 #if 1
00259   // If the browser is larger than needed, we have to 
00260   // re-create it from scratch since some molecule was 
00261   // potentially deleted from the middle.
00262   // If the size remains fixed, then we need to regenerate
00263   // because we are getting called to rename an existing molecule...
00264   if (size() > nummols || size() == nummols) {
00265     need_full_regen = 1;
00266   }
00267 #else
00268   need_full_regen = 1;
00269 #endif
00270 
00271   if (need_full_regen) {
00272     clear();
00273 
00274     for (int i=0; i<nummols; i++) {
00275       Molecule *mol = mlist->molecule(i);
00276 
00277       // prevent string length overflows
00278       strncpy(molnamebuf, mol->molname(), sizeof(molnamebuf)-1);
00279 
00280       // display state of active/displayed/fixed by toggling the text color
00281       sprintf(buf, "%d\t%s\t%s\t%s\t%s\t%-13s\t%-9d\t%-7d\t%-3d",
00282         mol->id(),
00283         mlist->is_top(i) ? "T" : " ",
00284         mlist->active(i) ? VMDMENU_MOL_ACTIVE : VMDMENU_MOL_INACTIVE,
00285         mlist->displayed(i) ? VMDMENU_MOL_DISPLAYED : VMDMENU_MOL_NONDISPLAYED,
00286         mlist->fixed(i) ? VMDMENU_MOL_FIXED : VMDMENU_MOL_NONFIXED,
00287         molnamebuf, mol->nAtoms, mol->numframes(), mol->num_volume_data()
00288       );
00289 
00290       if (i < size())
00291         text(i+1, buf); // update existing browser line
00292       else
00293         add(buf); // add a new browser line
00294     }
00295   } else {
00296     // we just need to add one new molecule...
00297     int i = nummols - 1;
00298     Molecule *mol = mlist->molecule(i);
00299 
00300     // prevent string length overflows
00301     strncpy(molnamebuf, mol->molname(), sizeof(molnamebuf)-1);
00302 
00303     // display state of active/displayed/fixed by toggling the text color
00304     sprintf(buf, "%d\t%s\t%s\t%s\t%s\t%-13s\t%-9d\t%-7d\t%-3d",
00305       mol->id(),
00306       mlist->is_top(i) ? "T" : " ",
00307       mlist->active(i) ? VMDMENU_MOL_ACTIVE : VMDMENU_MOL_INACTIVE,
00308       mlist->displayed(i) ? VMDMENU_MOL_DISPLAYED : VMDMENU_MOL_NONDISPLAYED,
00309       mlist->fixed(i) ? VMDMENU_MOL_FIXED : VMDMENU_MOL_NONFIXED,
00310       molnamebuf, mol->nAtoms, mol->numframes(), mol->num_volume_data()
00311     );
00312 
00313     if (i < size())
00314       text(i+1, buf); // update existing browser line
00315     else
00316       add(buf); // add a new browser line
00317   }
00318 #endif
00319  
00320   if (mainmenu) mainmenu->update_gui_state();
00321 }
00322   

Generated on Thu Mar 28 02:43:29 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002