00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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;
00052
00053
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, ',');
00060 if (extnext) {
00061 *extnext = '\0';
00062 extnext++;
00063 } else {
00064 extnext = extbuf + extlen;
00065 }
00066
00067 if (cnt == 0) {
00068 sprintf(mask, "*.%s", extcur);
00069 }
00070
00071
00072 #if 0
00073 else {
00074 char tmpmask[256];
00075 sprintf(tmpmask, ",*.%s", extcur);
00076 strcat(mask, tmpmask);
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
00107
00108
00109 if (filetypechooser->value() > 0) {
00110 update_checkboxes();
00111 return;
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
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
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
00145
00146
00147 void FileChooserFltkMenu::update_filetypes() {
00148 PluginList plugins;
00149 int n;
00150
00151
00152 filetypechooser->clear();
00153 filetypechooser->add("Automatically");
00154
00155
00156
00157
00158 n = app->list_plugins(plugins, "mol file reader");
00159
00160
00161 qsort(&(plugins[0]), n, sizeof(vmdplugin_t *), compare_plugin_name);
00162
00163
00164 for (int j=0; j<n; j++) {
00165 vmdplugin_t *p = plugins[j];
00166 filetypechooser->add(p->prettyname, 0, NULL, p);
00167 }
00168
00169
00170
00171
00172
00173 plugins.clear();
00174 n = app->list_plugins(plugins, "mol file converter");
00175
00176
00177 qsort(&(plugins[0]), n, sizeof(vmdplugin_t *), compare_plugin_name);
00178
00179
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);
00185 delete [] buf;
00186 }
00187
00188
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
00198
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
00268 if (!filename || !strlen(filename)) {
00269 fl_alert("Please select a file.");
00270 return;
00271 }
00272
00273
00274 if (filetypechooser->value() == 0) {
00275 const char *filetype = app->guess_filetype(filename);
00276 if (filetype) {
00277 if (menu != NULL) {
00278
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;
00319 if (molid < 0) {
00320 fl_alert("Unable to load molecule.");
00321 return;
00322 }
00323
00324
00325
00326
00327
00328
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 }