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

FileChooserFltkMenu.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2008 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: FileChooserFltkMenu.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.45 $       $Date: 2008/03/27 19:36:38 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *  generated by Fast Light User Interface Designer (fluid) version 1.0100
00019  ***************************************************************************/
00020 
00021 #include <assert.h>
00022 #include <stdio.h>
00023 #include <FL/forms.H>
00024 #include <FL/Fl_Menu_.H>
00025 #include <FL/Fl_Round_Button.H>
00026 #include <FL/Fl_Multi_Browser.H>
00027 #include <FL/Fl_Int_Input.H>
00028 #include "FileChooserFltkMenu.h"
00029 #include "VMDApp.h"
00030 #include "Command.h"
00031 #include "molfile_plugin.h"
00032 #include "utilities.h"
00033 #include "Inform.h"
00034 
00035 void FileChooserFltkMenu::browse_cb(Fl_Widget *w, void *v) {
00036   FileChooserFltkMenu *self = (FileChooserFltkMenu *)v;
00037   self->browse_files();
00038 }
00039 
00040 void FileChooserFltkMenu::browse_files() {
00041   char mask[4096];
00042   strcpy(mask, "*");
00043 
00044   const char *filetype = "All files";
00045   int val = filetypechooser->value();
00046   if (val) {
00047     const Fl_Menu_Item *menulist = filetypechooser->menu();
00048     const char *extension = ((molfile_plugin_t *)menulist[val].user_data())->filename_extension;
00049 
00050     if (extension) {
00051       int cnt = 0; // number of extensions added
00052 
00053       // add all extensions to the filename selection mask
00054       char *extbuf = strdup(extension);
00055       int extlen = strlen(extbuf);
00056       char *extcur = extbuf;
00057       char *extnext = NULL;
00058       while ((extcur - extbuf) < extlen) {
00059         extnext = strchr(extcur, ','); // find next extension string
00060         if (extnext) {
00061           *extnext = '\0'; // NUL terminate this extension string
00062           extnext++;       // step to beginning of next extension string
00063         } else {
00064           extnext = extbuf + extlen; // no more extensions, last time through
00065         }
00066 
00067         if (cnt == 0) {
00068           sprintf(mask, "*.%s", extcur); // overwrite if the first extension
00069         } 
00070 // XXX current file browser code doesn't do well with multiple 
00071 // filename extensions, so we just drop subsequent ones 
00072 #if 0
00073         else {
00074           char tmpmask[256];
00075           sprintf(tmpmask, ",*.%s", extcur);
00076           strcat(mask, tmpmask);         // concat subsequent extensions
00077         } 
00078 #endif
00079         cnt++;
00080 
00081         extcur = extnext;
00082       }
00083       free(extbuf);
00084 
00085       filetype = ((molfile_plugin_t *)menulist[val].user_data())->name;
00086     }
00087   }
00088   char *result = app->vmd_choose_file(
00089       "Choose a molecule file", mask, filetype, 0);
00090   if (result) {
00091     add_file(result);
00092     delete [] result;
00093   }
00094 }
00095 
00096 void FileChooserFltkMenu::filenameinput_cb(Fl_Widget *w, void *v) {
00097   FileChooserFltkMenu *menu = (FileChooserFltkMenu *)v;
00098   menu->add_file(((Fl_Input *)w)->value());
00099 }
00100   
00101 void FileChooserFltkMenu::add_file(const char *s) {
00102   if (!s) return;
00103   filenameinput->value(s);
00104   filenameinput->position(filenameinput->size(),0);
00105 
00106   // Figure out what kind of file this is.  If the file type chooser has
00107   // an item selected, don't change it.  If it's "unknown", try to guess the 
00108   // file type based on the filename extension.
00109   if (filetypechooser->value() > 0) {
00110     update_checkboxes();
00111     return; // already have a file type.
00112   }
00113   filetypechooser->value(0);
00114   const char *filetype = app->guess_filetype(s);
00115   if (filetype) {
00116     const Fl_Menu_Item *menu = filetypechooser->menu();
00117     if (menu != NULL) {
00118       // skip over the special "Automatically" item
00119       for (int j=1; j<menu->size()-2; j++) {
00120         const vmdplugin_t *plugin = (const vmdplugin_t *) menu[j].user_data();
00121         if (plugin != NULL && !strcmp(plugin->name, filetype)) {
00122           filetypechooser->value(j);
00123           break;
00124         }
00125       }
00126     }
00127   }
00128   update_checkboxes();
00129 }
00130 
00131 
00132 void FileChooserFltkMenu::update_molchooser(int selmol) {
00133     molchooser->clear();
00134     molchooser->add("New Molecule");
00135     fill_fltk_molchooser(molchooser, app);
00136     if (selmol >= -1) molchooser->value(selmol+1);
00137 }
00138 
00139 // compare plugin names, for sorted display in the GUI
00140 static int compare_plugin_name(const void *p1, const void *p2) {
00141   return strcmp( (*(vmdplugin_t **)p1)->prettyname, (*(vmdplugin_t **)p2)->prettyname);
00142 }
00143 
00144 // Create the file type chooser from all the plugins.  Set the chooser to
00145 // show "automatically", the default.  Store the plugin in the user data of 
00146 // the menu item.
00147 void FileChooserFltkMenu::update_filetypes() {
00148   PluginList plugins;
00149   int n;
00150 
00151   // prepare the file type chooser and add the special "Automatically" choice 
00152   filetypechooser->clear();
00153   filetypechooser->add("Automatically");
00154 
00155   // 
00156   // retrieve list of mol file reader plugins
00157   // 
00158   n = app->list_plugins(plugins, "mol file reader");
00159 
00160   // sort plugins by their "pretty" name
00161   qsort(&(plugins[0]), n, sizeof(vmdplugin_t *), compare_plugin_name);
00162 
00163   // add the plugins to the chooser, storing the plugin pointer in the menu 
00164   for (int j=0; j<n; j++) {
00165     vmdplugin_t *p = plugins[j];
00166     filetypechooser->add(p->prettyname, 0, NULL, p); // XXX valgrind FMR
00167   }
00168 
00169 
00170   // 
00171   // retrieve list of mol file converter plugins
00172   // 
00173   plugins.clear();
00174   n = app->list_plugins(plugins, "mol file converter");
00175 
00176   // sort converter plugins by their "pretty" name
00177   qsort(&(plugins[0]), n, sizeof(vmdplugin_t *), compare_plugin_name);
00178 
00179   // add the plugins to the chooser, storing the plugin pointer in the menu 
00180   for (int k=0; k<n; k++) {
00181     vmdplugin_t *p = plugins[k];
00182     char *buf = new char[strlen(p->prettyname)+16];
00183     sprintf(buf, "Convert from:/%s", p->name);
00184     filetypechooser->add(buf, 0, NULL, p); // XXX valgrind FMR
00185     delete [] buf;
00186   }
00187 
00188   // set the default value to "Automatically"
00189   filetypechooser->value(0);
00190 }
00191 
00192 void FileChooserFltkMenu::filetype_cb(Fl_Widget *w, void *v) {
00193   FileChooserFltkMenu *self = (FileChooserFltkMenu *)v;
00194   self->update_checkboxes();
00195 }
00196   
00197 // reset the activity and value of checkboxes based on the current
00198 // value of filetypechooser
00199 void FileChooserFltkMenu::update_checkboxes() {
00200   has_structure = has_bonds = has_timesteps = has_graphics = 
00201     has_volumetric = 0;
00202   timestepgroup->deactivate();
00203   datasetbrowser->deactivate();
00204   if (!filetypechooser->value()) return;
00205 
00206   molfile_plugin_t *plugin = 
00207     (molfile_plugin_t *)filetypechooser->mvalue()->user_data();
00208   has_structure = (plugin->read_structure != NULL);
00209   has_bonds = (plugin->read_bonds != NULL);
00210   has_timesteps = (plugin->read_next_timestep != NULL);
00211   has_graphics = (plugin->read_rawgraphics != NULL);
00212   has_volumetric = (plugin->read_volumetric_metadata != NULL);
00213 
00214   if (has_timesteps) {
00215     timestepgroup->activate();
00216     firstinput->value("0");
00217     lastinput->value("-1");
00218     strideinput->value("1");
00219     loadinbackgroundbutton->setonly();
00220   }
00221 
00222   if (has_volumetric) { 
00223     datasetbrowser->activate(); 
00224     datasetbrowser->clear(); 
00225     const char *filename = filenameinput->value();
00226     if (filename == NULL || !strlen(filename)) {
00227       msgInfo << "Can't show volumetric data; no filename selected yet" << sendmsg;
00228       return; 
00229     }
00230     int natoms = -1;
00231     void *rv = plugin->open_file_read(filename, plugin->name, &natoms);
00232     if (!rv) {
00233       msgErr << "Unable to open file with plugin of type " <<  plugin->name << sendmsg;
00234       return;
00235     }
00236     molfile_volumetric_t *tmp;
00237     int nsets = -1;
00238     if (plugin->read_volumetric_metadata(rv, &nsets, &tmp)) {
00239       msgErr << "read_volumetric_metadata returned error" << sendmsg;
00240       plugin->close_file_read(rv);
00241       return;
00242     }
00243     if (nsets <= 0) {
00244       msgInfo << "No volumetric datasets found" << sendmsg;
00245       return;
00246     }
00247     for (int n=0; n<nsets; n++) {
00248       molfile_volumetric_t *v = tmp+n;
00249       char *buf = new char[strlen(v->dataname)+5];
00250       sprintf(buf, "%d: %s", n+1, v->dataname);
00251       datasetbrowser->add(buf);
00252       delete [] buf;
00253     }
00254     datasetbrowser->select(1, datasetbrowser->size());
00255     plugin->close_file_read(rv);
00256   }
00257 }
00258 
00259 void FileChooserFltkMenu::load_cb(Fl_Widget *, void *v) {
00260   FileChooserFltkMenu *self = (FileChooserFltkMenu *)v;
00261   self->load_file(self->filenameinput->value());
00262 }
00263 
00264 void FileChooserFltkMenu::load_file(const char *filename) {
00265   const Fl_Menu_Item *menu = filetypechooser->menu();
00266 
00267   // Make sure a file is selected
00268   if (!filename || !strlen(filename)) {
00269     fl_alert("Please select a file.");
00270     return;
00271   }
00272 
00273   // Make sure a plugin has been assigned 
00274   if (filetypechooser->value() == 0) {
00275     const char *filetype = app->guess_filetype(filename);
00276     if (filetype) {
00277       if (menu != NULL) {
00278         // skip over the special "Automatically" item
00279         for (int j=1; j<menu->size()-2; j++) {
00280           const vmdplugin_t *plugin = (const vmdplugin_t *) menu[j].user_data();
00281           if (plugin != NULL && !strcmp(plugin->name, filetype)) {
00282             filetypechooser->value(j);
00283             update_checkboxes();
00284             break;
00285           }
00286         }
00287       }
00288     } else {
00289       fl_alert("Please select a file type.");
00290       return;
00291     }
00292   }
00293 
00294   const vmdplugin_t *plugin = (const vmdplugin_t *) menu[filetypechooser->value()].user_data();
00295   const char *filetype = plugin->name;
00296 
00297   int molid = app->molecule_id(molchooser->value()-1);
00298 
00299   FileSpec spec;
00300   sscanf(firstinput->value(), "%d", &spec.first);
00301   sscanf(lastinput->value(), "%d", &spec.last);
00302   sscanf(strideinput->value(), "%d", &spec.stride);
00303   if (spec.first < 0) spec.first = 0;
00304   if (spec.last >= 0 && spec.last < spec.first) spec.last = spec.first;
00305   if (spec.stride < 1) spec.stride = 1;
00306   spec.waitfor = allatoncebutton->value() ? -1 : 1;
00307 
00308   ResizeArray<int> setids;
00309   for (int j=0; j<datasetbrowser->size(); j++) {
00310     if (datasetbrowser->selected(j+1)) {
00311       setids.append(j);
00312     }
00313   }
00314   spec.nvolsets = setids.num();
00315   spec.setids = &(setids[0]);
00316 
00317   molid = app->molecule_load(molid, filename, filetype, &spec);
00318   spec.setids = NULL; // don't want FileSpec to delete the data!
00319   if (molid < 0) {
00320     fl_alert("Unable to load molecule.");
00321     return;
00322   }
00323 
00324   // Clear the filename input, set the filetype back to automatic, and 
00325   // change the molecule to the most recent one loaded, if any.  If we
00326   // didn't do this, when you went to select a new molecule, the old 
00327   // filetype would be retained, instead of being chosen from the filename
00328   // extension.  It seems less surprising this way.
00329 
00330   molchooser->value(0);
00331   for (int m=0; m<app->num_molecules(); m++) {
00332     if (molid == app->molecule_id(m)) {
00333       molchooser->value(m+1);
00334     }
00335   }
00336   filenameinput->value("");
00337   filetypechooser->value(0);
00338   update_checkboxes();
00339 }
00340       
00341 void FileChooserFltkMenu::make_window() {
00342   size(450,250);
00343 
00344   { 
00345     { Fl_Choice* o = molchooser = new Fl_Choice(109, 10, 320, 25, "Load files for: ");
00346       o->box(FL_THIN_UP_BOX);
00347       o->down_box(FL_BORDER_BOX);
00348       o->color(FL_PALEGREEN);
00349       o->selection_color(0);
00350     }
00351     filenameinput = new Fl_Input(85, 40, 270, 25, "Filename: ");
00352     filenameinput->callback(filenameinput_cb, this);
00353     filenameinput->when(FL_WHEN_ENTER_KEY_ALWAYS);
00354     filenameinput->selection_color(FL_YELLOW);
00355 
00356     VMDFLTKTOOLTIP(filenameinput, "Enter a filename, or a 4-character PDB accession code")
00357 
00358     browsebutton = new Fl_Button(365, 40, 65, 25, "Browse...");
00359     browsebutton->callback(browse_cb, this);
00360     browsebutton->when(FL_WHEN_ENTER_KEY_ALWAYS | FL_WHEN_RELEASE);
00361     { Fl_Choice* o = filetypechooser = new Fl_Choice(20, 90, 300, 25, "Determine file type:");
00362       o->down_box(FL_BORDER_BOX);
00363       o->align(FL_ALIGN_TOP_LEFT);
00364       o->color(FL_PALEGREEN, FL_BLACK);
00365       o->callback(filetype_cb, this);
00366 
00367       VMDFLTKTOOLTIP(o, "Select the correct file type (if not already guessed correctly")
00368     }
00369     { Fl_Button* o = loadbutton = new Fl_Button(345, 90, 85, 25, "Load");
00370       VMDFLTKTOOLTIP(o, "Load the selected files")
00371       o->callback(load_cb, this);
00372     }
00373     { Fl_Group* o = timestepgroup = new Fl_Group(20, 145, 165, 95, "Frames: ");
00374       o->box(FL_ENGRAVED_FRAME);
00375       o->align(FL_ALIGN_TOP_LEFT);
00376       { Fl_Button* o = allatoncebutton = new Fl_Round_Button(30, 215, 150, 20, "Load all at once");
00377         o->down_box(FL_ROUND_DOWN_BOX);
00378         o->type(FL_RADIO_BUTTON);
00379       }
00380       { Fl_Button* o = loadinbackgroundbutton = new Fl_Round_Button(30, 195, 150, 20, "Load in background");
00381         o->down_box(FL_ROUND_DOWN_BOX);
00382         o->type(FL_RADIO_BUTTON);
00383       }
00384       { Fl_Input* o = firstinput = new Fl_Int_Input(25, 170, 45, 20, "First:");
00385         o->align(FL_ALIGN_TOP);
00386         o->selection_color(FL_YELLOW);
00387       }
00388       { Fl_Input* o = lastinput = new Fl_Int_Input(80, 170, 45, 20, "Last:");
00389         o->align(FL_ALIGN_TOP);
00390         o->selection_color(FL_YELLOW);
00391       }
00392       { Fl_Input* o = strideinput = new Fl_Int_Input(135, 170, 45, 20, "Stride:");
00393         o->align(FL_ALIGN_TOP);
00394         o->selection_color(FL_YELLOW);
00395       }
00396       o->end();
00397       datasetbrowser = new Fl_Multi_Browser(195, 145, 235, 95, "Volumetric Datasets");
00398       datasetbrowser->align(5);
00399       datasetbrowser->color(FL_DARKCYAN, FL_YELLOW);
00400     }
00401     Fl_Window::end();
00402   }
00403 }
00404 
00405 FileChooserFltkMenu::FileChooserFltkMenu(VMDApp *vmdapp)
00406 : VMDFltkMenu("files", "Molecule File Browser", vmdapp) {
00407 
00408   make_window();
00409 
00410   command_wanted(Command::PLUGIN_UPDATE);
00411   command_wanted(Command::MOL_NEW);
00412   command_wanted(Command::MOL_DEL);
00413   command_wanted(Command::MOL_RENAME);
00414 
00415   update_molchooser();
00416   update_filetypes();
00417   update_checkboxes();
00418 }
00419 
00420 
00421 int FileChooserFltkMenu::selectmol(int molno) {
00422   update_molchooser(molno);
00423   return TRUE;
00424 }
00425 
00426 
00427 int FileChooserFltkMenu::act_on_command(int type, Command *cmd) {
00428   switch (type) {
00429     case Command::PLUGIN_UPDATE:
00430       update_filetypes();
00431       break;
00432     case Command::MOL_NEW:
00433     case Command::MOL_DEL:
00434     case Command::MOL_RENAME:
00435       update_molchooser();
00436       break;
00437     default:
00438       return 0;
00439   }
00440   return 1;
00441 }

Generated on Tue Oct 7 01:26:10 2008 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002