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: SaveTrajectoryFltkMenu.C,v $ 00013 * $Author: johns $ $Locker: $ $State: Exp $ 00014 * $Revision: 1.42 $ $Date: 2020年07月23日 03:27:52 $ 00015 * 00016 *************************************************************************** 00017 * DESCRIPTION: 00018 * Window to allow the user to save sets of trajectory frames etc. 00019 ***************************************************************************/ 00020 00021 #include "SaveTrajectoryFltkMenu.h" 00022 #include "Command.h" 00023 #include "VMDApp.h" 00024 #include "MolFilePlugin.h" 00025 #include "frame_selector.h" 00026 #include "CmdAnimate.h" 00027 #include "AtomSel.h" 00028 #include "MoleculeList.h" 00029 #include "VolumetricData.h" 00030 00031 #include <stdio.h> 00032 #include <FL/Fl.H> 00033 #include <FL/forms.H> 00034 #include <FL/Fl_Window.H> 00035 #include <FL/Fl_Hold_Browser.H> 00036 #include <FL/Fl_Return_Button.H> 00037 #include <FL/Fl_Button.H> 00038 #include <FL/Fl_Choice.H> 00039 #include <FL/Fl_Int_Input.H> 00040 #include <FL/Fl_Multi_Browser.H> 00041 #include "utilities.h" 00042 00043 static void save_cb(Fl_Widget *, void *v) { 00044 ((SaveTrajectoryFltkMenu *)v)->do_save(); 00045 } 00046 00047 void SaveTrajectoryFltkMenu::do_save() { 00048 int ind = molchooser->value()-1; 00049 if (ind < 0) { 00050 fl_alert("Please select a molecule first."); 00051 return; 00052 } 00053 int molid = app->molecule_id(ind); 00054 if (molid < 0) return; 00055 // Make sure the user selected a file type 00056 if (filetypechooser->value() < 0) { 00057 fl_alert("Please select a file type first."); 00058 return; 00059 } 00060 00061 const char *filetype = filetypechooser->text(); 00062 char mask[20]; 00063 sprintf(mask, "*.%s", (const char *)filetypechooser->mvalue()->user_data()); 00064 00065 // read and check selected frames 00066 const char *firststr = firstinput->value(); 00067 const char *laststr = lastinput->value(); 00068 const char *stridestr = strideinput->value(); 00069 int max = app->molecule_numframes(molid)-1; 00070 int first = strlen(firststr) ? atoi(firststr) : 0; 00071 int last = strlen(laststr) ? atoi(laststr) : max; 00072 int stride = strlen(stridestr) ? atoi(stridestr) : 1; 00073 int waitfor = allatoncebutton->value() ? 00074 FileSpec::WAIT_ALL : FileSpec::WAIT_BACK; 00075 00076 if (first < 0) first=0; 00077 if (last > max) last=max; 00078 if (stride < 1) stride=1; 00079 00080 if ((last-first)/stride < 0) { 00081 fl_alert("No timesteps selected; trajectory file will not be written."); 00082 return; 00083 } 00084 00085 // check that selected atoms is valid 00086 const char *seltext = selectinput->value(); 00087 AtomSel *atomsel = NULL; 00088 if (strlen(seltext)) { 00089 atomsel = new AtomSel(app, app->atomSelParser, molid); 00090 if (atomsel->change(seltext, app->moleculeList->mol_from_id(molid)) != AtomSel::PARSE_SUCCESS) { 00091 delete atomsel; 00092 fl_alert("Invalid atom selection: %s", seltext); 00093 return; 00094 } 00095 } 00096 00097 char *fname = app->vmd_choose_file( 00098 "Choose filename to save trajectory", mask, filetype, 1); 00099 if (fname) { 00100 FileSpec spec; 00101 spec.first = first; 00102 spec.last = last; 00103 spec.stride = stride; 00104 spec.waitfor = waitfor; 00105 if (atomsel) { 00106 spec.selection = atomsel->on; 00107 } 00108 if (app->molecule_savetrajectory(molid, fname, filetype, &spec) < 0) { 00110 fl_alert("Error writing trajectory file."); 00111 } 00112 delete [] fname; 00113 } 00114 delete atomsel; 00115 } 00116 00117 static void molchooser_cb(Fl_Widget *, void *v) { 00118 ((SaveTrajectoryFltkMenu *)v)->molchooser_activate_selection(); 00119 } 00120 00121 void SaveTrajectoryFltkMenu::molchooser_activate_selection() { 00122 int m; 00123 selected_molid = app->molecule_id(molchooser->value()-1); 00124 if (selected_molid < 0) return; 00125 00126 // update frames 00127 int numframes = app->molecule_numframes(selected_molid); 00128 firstinput->value("0"); 00129 { 00130 char buf[32]; 00131 sprintf(buf, "%d", numframes-1); 00132 lastinput->value(buf); 00133 } 00134 strideinput->value("1"); 00135 00136 // update volumetric datasets 00137 Molecule *mol = app->moleculeList->mol_from_id(selected_molid); 00138 datasetbrowser->clear(); 00139 for (m=0; m<mol->num_volume_data(); m++) { 00140 datasetbrowser->add(mol->get_volume_data(m)->name); 00141 } 00142 00143 // update reps in repchooser 00144 repchooser->clear(); 00145 repchooser->add("Current selections:"); 00146 for (m=0; m<app->num_molreps(selected_molid); m++) { 00147 repchooser->add(app->molrep_get_selection(selected_molid, m)); 00148 } 00149 repchooser->value(0); 00150 } 00151 00152 static void repchooser_cb(Fl_Widget *w, void *v) { 00153 Fl_Choice *c = (Fl_Choice *)w; 00154 if (c->value()) 00155 ((SaveTrajectoryFltkMenu *)v)->select_atoms(c->text()); 00156 } 00157 00158 void SaveTrajectoryFltkMenu::select_atoms(const char *sel) { 00159 selectinput->value(sel); 00160 } 00161 00162 SaveTrajectoryFltkMenu::SaveTrajectoryFltkMenu(VMDApp *vmdapp) 00163 : VMDFltkMenu("save", "Save Trajectory", vmdapp) { 00164 00165 size(450, 250); 00166 { Fl_Choice* o = molchooser = new Fl_Choice(120, 10, 320, 25, "Save data from: "); 00167 o->box(FL_THIN_UP_BOX); 00168 o->down_box(FL_BORDER_BOX); 00169 o->color(VMDMENU_CHOOSER_BG); 00170 o->selection_color(VMDMENU_CHOOSER_SEL); 00171 o->callback(molchooser_cb, this); 00172 } 00173 { Fl_Input *o = selectinput = new Fl_Input(120, 45, 295, 25, "Selected atoms:"); 00174 o->selection_color(VMDMENU_VALUE_SEL); 00175 } 00176 { Fl_Choice* o = repchooser = new Fl_Choice(415, 45, 25, 25); 00177 o->down_box(FL_BORDER_BOX); 00178 o->align(FL_ALIGN_TOP_LEFT); 00179 o->color(VMDMENU_CHOOSER_BG, VMDMENU_CHOOSER_SEL); 00180 o->callback(repchooser_cb, this); 00181 } 00182 { Fl_Choice* o = filetypechooser = new Fl_Choice(20, 90, 115, 25, "File type:"); 00183 o->down_box(FL_BORDER_BOX); 00184 o->align(FL_ALIGN_TOP_LEFT); 00185 o->color(VMDMENU_CHOOSER_BG, VMDMENU_CHOOSER_SEL); 00186 } 00187 savebutton = new Fl_Return_Button(345, 90, 95, 25, "Save..."); 00188 savebutton->callback(save_cb, this); 00189 { Fl_Group* o = timestepgroup = new Fl_Group(20, 145, 165, 95, "Frames: "); 00190 o->box(FL_ENGRAVED_FRAME); 00191 o->align(FL_ALIGN_TOP_LEFT); 00192 { Fl_Button* o = saveinbackgroundbutton = new Fl_Round_Button(30, 215, 150, 20, "Save in background"); 00193 o->down_box(FL_ROUND_DOWN_BOX); 00194 o->type(FL_RADIO_BUTTON); 00195 } 00196 { Fl_Button* o = allatoncebutton = new Fl_Round_Button(30, 195, 150, 20, "Save all at once"); 00197 o->down_box(FL_ROUND_DOWN_BOX); 00198 o->type(FL_RADIO_BUTTON); 00199 } 00200 { Fl_Input* o = firstinput = new Fl_Int_Input(25, 170, 45, 20, "First:"); 00201 o->align(FL_ALIGN_TOP); 00202 o->selection_color(VMDMENU_VALUE_SEL); 00203 } 00204 { Fl_Input* o = lastinput = new Fl_Int_Input(80, 170, 45, 20, "Last:"); 00205 o->align(FL_ALIGN_TOP); 00206 o->selection_color(VMDMENU_VALUE_SEL); 00207 } 00208 { Fl_Input* o = strideinput = new Fl_Int_Input(135, 170, 45, 20, "Stride:"); 00209 o->align(FL_ALIGN_TOP); 00210 o->selection_color(VMDMENU_VALUE_SEL); 00211 } 00212 o->end(); 00213 datasetbrowser = new Fl_Multi_Browser(195, 145, 240, 95, "Volumetric Datasets"); 00214 datasetbrowser->align(5); 00215 datasetbrowser->color(VMDMENU_BROWSER_BG, VMDMENU_BROWSER_SEL); 00216 } 00217 end(); 00218 00219 allatoncebutton->value(1); 00220 selected_molid = -1; 00221 datasetbrowser->deactivate(); 00222 00223 command_wanted(Command::PLUGIN_UPDATE); 00224 command_wanted(Command::MOL_NEW); 00225 command_wanted(Command::MOL_RENAME); 00226 command_wanted(Command::MOL_DEL); 00227 command_wanted(Command::MOL_ADDREP); 00228 command_wanted(Command::MOL_DELREP); 00229 command_wanted(Command::MOL_MODREP); 00230 command_wanted(Command::MOL_MODREPITEM); 00231 command_wanted(Command::ANIM_DELETE); 00232 } 00233 00234 // This rebuilds the molecule chooser menu and selects the item 00235 // corresponding to the previouly selected molid 00236 void SaveTrajectoryFltkMenu::update_molchooser(int type) { 00237 if (type == Command::MOL_NEW || 00238 type == Command::MOL_DEL || 00239 type == Command::MOL_RENAME) { 00240 // don't regen the molecule list for rep changes 00241 fill_fltk_molchooser(molchooser, app, "No Molecule Selected"); 00242 } 00243 00244 molchooser->value(0); 00245 #if 1 00246 int m = app->molecule_index_from_id(selected_molid); 00247 if (m >= 0) { 00248 molchooser->value(m); 00249 molchooser_activate_selection(); 00250 } 00251 #else 00252 for (int m=1; m<molchooser->size()-1; m++) { 00253 int tmpid = app->molecule_id(m-1); 00254 if (tmpid == selected_molid) { 00255 molchooser->value(m); 00256 molchooser_activate_selection(); 00257 break; 00258 } 00259 } 00260 #endif 00261 } 00262 00263 00264 // XXX just like FilesFltkMenu - maybe we should be subclassing or something 00265 int SaveTrajectoryFltkMenu::act_on_command(int type, Command *command) { 00266 switch(type) { 00267 case Command::PLUGIN_UPDATE: 00268 { 00269 filetypechooser->clear(); 00270 PluginList plugins; 00271 int n = app->list_plugins(plugins, "mol file reader"); 00272 for (int p=0; p<n; p++) { 00273 MolFilePlugin m(plugins[p]); 00274 if (m.can_write_timesteps()) 00275 filetypechooser->add(m.name(), 0, 0, (void *)m.extension()); 00276 } 00277 00278 // set the chooser to the first item initially, update from there 00279 filetypechooser->value(0); 00280 00281 // Make PDB the default filetype, if we can find it in the menu 00282 // XXX Current code is listing them using extensions rather than the 00283 // pretty names. 00284 // XXX This should be updated to use the built-in FLTK routines 00285 // for FLTK versions 1.1.7 and newer. 00286 #if 1 00287 set_chooser_from_string("pdb", filetypechooser); 00288 #else 00289 Fl_Menu_Item *pdbitem = NULL; 00290 pdbitem = filetypechooser->find_item("pdb"); 00291 if (pdbitem) 00292 filetypechooser->value(pdbitem); // set "pdb" as default 00293 #endif 00294 } 00295 break; 00296 00297 case Command::MOL_NEW: 00298 case Command::MOL_DEL: 00299 case Command::MOL_RENAME: 00300 case Command::MOL_ADDREP: 00301 case Command::MOL_DELREP: 00302 case Command::MOL_MODREP: 00303 case Command::MOL_MODREPITEM: 00304 update_molchooser(type); 00305 break; 00306 00307 case Command::ANIM_DELETE: 00308 if (selected_molid == ((CmdAnimDelete*)command)->whichMol) 00309 molchooser_activate_selection(); //to update the number of frames 00310 break; 00311 00312 default: 00313 return 0; 00314 } 00315 00316 return 1; 00317 } 00318 00319 00320 int SaveTrajectoryFltkMenu::selectmol(int molindex) { 00321 if (molindex < 0 || molindex >= app->num_molecules()) 00322 molchooser->value(0); 00323 else { 00324 molchooser->value(molindex+1); 00325 molchooser_activate_selection(); 00326 } 00327 return TRUE; 00328 } 00329 00330