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] = { 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;
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] = { 0 };
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() ?
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;
00327 if (molid < 0) {
00328 fl_alert("Unable to load molecule.");
00329 return;
00330 }
00331
00332
00333
00334
00335
00336
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 }