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

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

Generated on Fri Apr 19 02:44:23 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002