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
00041 void FileChooserFltkMenu::browse_files() {
00042 char mask[4096];
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;
00053
00054
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, ',');
00061 if (extnext) {
00062 *extnext = '\0';
00063 extnext++;
00064 } else {
00065 extnext = extbuf + extlen;
00066 }
00067
00068 if (cnt == 0) {
00069 sprintf(mask, "*.%s", extcur);
00070 }
00071
00072
00073 #if 0
00074 else {
00075 char tmpmask[256];
00076 sprintf(tmpmask, ",*.%s", extcur);
00077 strcat(mask, tmpmask);
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
00110
00111
00112 if (filetypechooser->value() > 0) {
00113 update_checkboxes();
00114 return;
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
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
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
00148
00149
00150 void FileChooserFltkMenu::update_filetypes() {
00151 PluginList plugins;
00152 int n;
00153
00154
00155 filetypechooser->clear();
00156 filetypechooser->add("Automatically");
00157
00158
00159
00160
00161 n = app->list_plugins(plugins, "mol file reader");
00162
00163
00164 qsort(&(plugins[0]), n, sizeof(vmdplugin_t *), compare_plugin_name);
00165
00166
00167 for (int j=0; j<n; j++) {
00168 vmdplugin_t *p = plugins[j];
00169 filetypechooser->add(p->prettyname, 0, NULL, p);
00170 }
00171
00172
00173
00174
00175
00176 plugins.clear();
00177 n = app->list_plugins(plugins, "mol file converter");
00178
00179
00180 qsort(&(plugins[0]), n, sizeof(vmdplugin_t *), compare_plugin_name);
00181
00182
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);
00188 delete [] buf;
00189 }
00190
00191
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
00203
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
00275 if (!filename || !strlen(filename)) {
00276 fl_alert("Please select a file.");
00277 return;
00278 }
00279
00280
00281 if (filetypechooser->value() == 0) {
00282 const char *filetype = app->guess_filetype(filename);
00283 if (filetype) {
00284 if (menu != NULL) {
00285
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() ? -1 : 1;
00314
00315 ResizeArray<int> setids;
00316 for (int j=0; j<datasetbrowser->size(); j++) {
00317 if (datasetbrowser->selected(j+1)) {
00318 setids.append(j);
00319 }
00320 }
00321 spec.nvolsets = setids.num();
00322 spec.setids = &(setids[0]);
00323
00324 molid = app->molecule_load(molid, filename, filetype, &spec);
00325 spec.setids = NULL;
00326 if (molid < 0) {
00327 fl_alert("Unable to load molecule.");
00328 return;
00329 }
00330
00331
00332
00333
00334
00335
00336
00337 molchooser->value(0);
00338 for (int m=0; m<app->num_molecules(); m++) {
00339 if (molid == app->molecule_id(m)) {
00340 molchooser->value(m+1);
00341 }
00342 }
00343 filenameinput->value("");
00344 filetypechooser->value(0);
00345 update_checkboxes();
00346 }
00347
00348
00349 void FileChooserFltkMenu::make_window() {
00350 size(450,250);
00351
00352 {
00353 { Fl_Choice* o = molchooser = new Fl_Choice(109, 10, 320, 25, "Load files for: ");
00354 o->box(FL_THIN_UP_BOX);
00355 o->down_box(FL_BORDER_BOX);
00356 o->color(VMDMENU_CHOOSER_BG);
00357 o->selection_color(VMDMENU_CHOOSER_SEL);
00358 }
00359 filenameinput = new Fl_Input(85, 40, 270, 25, "Filename: ");
00360 filenameinput->callback(filenameinput_cb, this);
00361 filenameinput->when(FL_WHEN_ENTER_KEY_ALWAYS);
00362 filenameinput->selection_color(VMDMENU_VALUE_SEL);
00363
00364 VMDFLTKTOOLTIP(filenameinput, "Enter a filename, or a 4-character PDB accession code")
00365
00366 browsebutton = new Fl_Button(365, 40, 65, 25, "Browse...");
00367 #if defined(VMDMENU_WINDOW)
00368 browsebutton->color(VMDMENU_WINDOW, FL_GRAY);
00369 #endif
00370 browsebutton->callback(browse_cb, this);
00371 browsebutton->when(FL_WHEN_ENTER_KEY_ALWAYS | FL_WHEN_RELEASE);
00372 { Fl_Choice* o = filetypechooser = new Fl_Choice(20, 90, 300, 25, "Determine file type:");
00373 o->down_box(FL_BORDER_BOX);
00374 o->align(FL_ALIGN_TOP_LEFT);
00375 o->color(VMDMENU_CHOOSER_BG, VMDMENU_CHOOSER_SEL);
00376 o->callback(filetype_cb, this);
00377
00378 VMDFLTKTOOLTIP(o, "Select the correct file type (if not already guessed correctly")
00379 }
00380 { Fl_Button* o = loadbutton = new Fl_Button(345, 90, 85, 25, "Load");
00381 #if defined(VMDMENU_WINDOW)
00382 o->color(VMDMENU_WINDOW, FL_GRAY);
00383 #endif
00384 VMDFLTKTOOLTIP(o, "Load the selected files")
00385 o->callback(load_cb, this);
00386 }
00387 { Fl_Group* o = timestepgroup = new Fl_Group(20, 145, 165, 95, "Frames: ");
00388 o->box(FL_ENGRAVED_FRAME);
00389 o->align(FL_ALIGN_TOP_LEFT);
00390 { Fl_Button* o = allatoncebutton = new Fl_Round_Button(30, 215, 150, 20, "Load all at once");
00391 o->down_box(FL_ROUND_DOWN_BOX);
00392 o->type(FL_RADIO_BUTTON);
00393 }
00394 { Fl_Button* o = loadinbackgroundbutton = new Fl_Round_Button(30, 195, 150, 20, "Load in background");
00395 o->down_box(FL_ROUND_DOWN_BOX);
00396 o->type(FL_RADIO_BUTTON);
00397 }
00398 { Fl_Input* o = firstinput = new Fl_Int_Input(25, 170, 45, 20, "First:");
00399 o->align(FL_ALIGN_TOP);
00400 o->selection_color(VMDMENU_VALUE_SEL);
00401 }
00402 { Fl_Input* o = lastinput = new Fl_Int_Input(80, 170, 45, 20, "Last:");
00403 o->align(FL_ALIGN_TOP);
00404 o->selection_color(VMDMENU_VALUE_SEL);
00405 }
00406 { Fl_Input* o = strideinput = new Fl_Int_Input(135, 170, 45, 20, "Stride:");
00407 o->align(FL_ALIGN_TOP);
00408 o->selection_color(VMDMENU_VALUE_SEL);
00409 }
00410 o->end();
00411 datasetbrowser = new Fl_Multi_Browser(195, 145, 235, 95, "Volumetric Datasets");
00412 datasetbrowser->align(5);
00413 datasetbrowser->color(VMDMENU_BROWSER_BG, VMDMENU_BROWSER_SEL);
00414 }
00415 Fl_Window::end();
00416 }
00417 }
00418
00419
00420 FileChooserFltkMenu::FileChooserFltkMenu(VMDApp *vmdapp)
00421 : VMDFltkMenu("files", "Molecule File Browser", vmdapp) {
00422
00423 make_window();
00424
00425 command_wanted(Command::PLUGIN_UPDATE);
00426 command_wanted(Command::MOL_NEW);
00427 command_wanted(Command::MOL_DEL);
00428 command_wanted(Command::MOL_RENAME);
00429
00430 update_molchooser();
00431 update_filetypes();
00432 update_checkboxes();
00433 }
00434
00435
00436 int FileChooserFltkMenu::selectmol(int molno) {
00437 update_molchooser(molno);
00438 return TRUE;
00439 }
00440
00441
00442 int FileChooserFltkMenu::act_on_command(int type, Command *cmd) {
00443 switch (type) {
00444 case Command::PLUGIN_UPDATE:
00445 update_filetypes();
00446 break;
00447 case Command::MOL_NEW:
00448 case Command::MOL_DEL:
00449 case Command::MOL_RENAME:
00450 update_molchooser();
00451 break;
00452 default:
00453 return 0;
00454 }
00455 return 1;
00456 }