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: GraphicsFltkMenu.C,v $ 00013 * $Author: johns $ $Locker: $ $State: Exp $ 00014 * $Revision: 1.164 $ $Date: 2020年07月08日 04:21:12 $ 00015 * 00016 *************************************************************************** 00017 * DESCRIPTION: 00018 * generated by Fast Light User Interface Designer (fluid) version 1.0011 00019 ***************************************************************************/ 00020 00021 #include "GraphicsFltkMenu.h" 00022 #include "GraphicsFltkReps.h" 00023 #include "Command.h" 00024 #include "MoleculeList.h" 00025 #include "Molecule.h" 00026 #include "VMDApp.h" 00027 #include "AtomRep.h" 00028 #include "AtomColor.h" 00029 #include "MaterialList.h" 00030 #include "FL/forms.H" 00031 #include "FL/Fl_Tabs.H" 00032 #include "FL/Fl_Box.H" 00033 #include "FL/Fl_Float_Input.H" 00034 #include "SelectionBuilder.h" 00035 #include "CmdMol.h" 00036 #include "CommandQueue.h" 00037 #include "VMDDisplayList.h" // for PBC #defines 00038 #include "VolumetricData.h" 00039 #include "Scene.h" 00040 00041 // XXX enable new color tab, or not 00042 // #define REPCOLORTAB 1 00043 00044 static const int widths[] = { 110, 100, 200, 0 }; 00045 00046 static void add_rep_to_browser(DrawMolItem *d, Fl_Browser *browser, int replace) { 00047 char repbuf[20]; 00048 const char *sel_str; 00049 strncpy(repbuf, d->atomRep->cmdStr, 20); 00050 repbuf[19] = '0円'; 00051 char *firstspace = strchr(repbuf, ' '); 00052 if (firstspace) { 00053 *firstspace = '0円'; 00054 } 00055 00056 if (!d->atomRep->is_volumetric()) 00057 sel_str = d->atomSel->cmdStr; 00058 else 00059 sel_str = "<volume>"; 00060 00061 char *buf = (char *)malloc(strlen(repbuf) + strlen(d->atomColor->cmdStr) 00062 + strlen(sel_str) + 20); 00063 const char *color = d->displayed() ? VMDMENU_REP_ACTIVE : VMDMENU_REP_INACTIVE; 00064 sprintf(buf,"%s%s\t%s%s\t%s%s", color, repbuf, color, d->atomColor->cmdStr, 00065 color, sel_str); 00066 if (replace > 0) 00067 browser->text(replace, buf); 00068 else 00069 browser->add(buf); 00070 free(buf); 00071 } 00072 00073 00074 // 00075 // Find the array index of a string that matches the name of the given menu 00076 // item. XXX Only checks leaf node menu names, not full pathnames currently 00077 // 00078 static int find_name_string_from_menuname(const char *mn, const char **names, int num) { 00079 // FLTK 1.1.4 00080 int i, strindex; 00081 for (strindex=-1, i=0; i < num; i++) { 00082 // find leaf menu name from full menu path 00083 const char *colstr; 00084 if ((colstr = strrchr(AtomColorMenuName[i], '/')) == NULL) 00085 colstr = AtomColorMenuName[i]; 00086 else 00087 colstr++; 00088 00089 // compare leaf submenu item name against left color mode name 00090 if (!strcmp(colstr, mn)) { 00091 strindex=i; 00092 break; 00093 } 00094 } 00095 00096 return strindex; 00097 } 00098 00099 00102 class myBrowser : public Fl_Hold_Browser { 00103 public: 00104 myBrowser(VMDApp *anApp, GraphicsFltkMenu *aMenu, 00105 int ix, int iy, int iw, int ih) 00106 : Fl_Hold_Browser(ix, iy, iw, ih), app(anApp), menu(aMenu) {} 00107 int handle(int type) { 00108 // toggle the highlighted rep on/off when double clicked... 00109 if (type == FL_PUSH && Fl::event_button() == FL_LEFT_MOUSE && 00110 Fl::event_clicks()) { 00111 // ...but ignore double clicks on the scrollbar. We distinguish these 00112 // events by checking that x value is inside the text bounding box. 00113 int bx, by, bw, bh; 00114 bbox(bx, by, bw, bh); 00115 if (Fl::event_x() < bx+bw) { 00116 Fl::event_is_click(0); 00117 int molid = app->molecule_id(menu->molindex); 00118 int rep = value()-1; 00119 app->molrep_show(molid, rep, !app->molrep_is_shown(molid, rep)); 00120 } 00121 return 0; 00122 } 00123 return Fl_Hold_Browser::handle(type); 00124 } 00125 private: 00126 VMDApp *app; 00127 GraphicsFltkMenu *menu; 00128 }; 00129 00132 class PBCControls : public Fl_Group { 00133 Fl_Check_Button *plusx, *plusy, *plusz, *minusx, *minusy, *minusz, *self; 00134 Fl_Counter *ncounter; 00135 public: 00136 PBCControls(int ix, int iy, int iw, int ih, const char *myname) 00137 : Fl_Group(ix, iy, iw, ih, myname) { 00138 Fl_Box *b = new Fl_Box(ix+30, iy+20, 190, 25, "Select periodic images to draw:"); 00139 b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); 00140 plusx = new Fl_Check_Button(ix+50, iy+50, 70, 25, "+X"); 00141 plusx->callback(cb, this); 00142 plusy = new Fl_Check_Button(ix+50, iy+80, 70, 25, "+Y"); 00143 plusy->callback(cb, this); 00144 plusz = new Fl_Check_Button(ix+50, iy+110, 70, 25, "+Z"); 00145 plusz->callback(cb, this); 00146 minusx = new Fl_Check_Button(ix+140, iy+50, 70, 25, "-X"); 00147 minusx->callback(cb, this); 00148 minusy = new Fl_Check_Button(ix+140, iy+80, 70, 25, "-Y"); 00149 minusy->callback(cb, this); 00150 minusz = new Fl_Check_Button(ix+140, iy+110, 70, 25, "-Z"); 00151 minusz->callback(cb, this); 00152 self = new Fl_Check_Button(ix+50, iy+140, 70, 25, "Self"); 00153 self->callback(cb, this); 00154 ncounter = new Fl_Counter(ix+50, iy+190, CTRWIDTH, CTRHEIGHT, 00155 "Number of images"); 00156 ncounter->precision(0); 00157 ncounter->minimum(1); 00158 ncounter->step(1); 00159 ncounter->lstep(5); 00160 ncounter->align(FL_ALIGN_TOP); 00161 ncounter->when(FL_WHEN_RELEASE); 00162 ncounter->callback(cb, this); 00163 end(); 00164 update(0, 1); 00165 } 00166 static void cb(Fl_Widget *, void *v) { ((PBCControls *)v)->do_callback(); } 00167 00168 // update checkboxes to reflect given pbc state 00169 void update(int pbc, int n) { 00170 plusx->value(pbc & PBC_X); 00171 plusy->value(pbc & PBC_Y); 00172 plusz->value(pbc & PBC_Z); 00173 minusx->value(pbc & PBC_OPX); 00174 minusy->value(pbc & PBC_OPY); 00175 minusz->value(pbc & PBC_OPZ); 00176 self->value(! (pbc & PBC_NOSELF)); 00177 ncounter->value((double)n); 00178 } 00179 00180 // Return current pbc state 00181 int state() const { 00182 int pbc = PBC_NONE; 00183 if (plusx->value()) pbc |= PBC_X; 00184 if (plusy->value()) pbc |= PBC_Y; 00185 if (plusz->value()) pbc |= PBC_Z; 00186 if (minusx->value()) pbc |= PBC_OPX; 00187 if (minusy->value()) pbc |= PBC_OPY; 00188 if (minusz->value()) pbc |= PBC_OPZ; 00189 if (!self->value()) pbc |= PBC_NOSELF; 00190 return pbc; 00191 } 00192 00193 // Return number of periodic images 00194 int num_images() const { return (int)ncounter->value(); } 00195 }; 00196 00197 void GraphicsFltkMenu::pbc_cb(Fl_Widget *w, void *v) { 00198 GraphicsFltkMenu *self = (GraphicsFltkMenu *)v; 00199 PBCControls *control = (PBCControls *)w; 00200 self->set_pbc(control->state(), control->num_images()); 00201 } 00202 00203 void GraphicsFltkMenu::multiframeinput_cb(Fl_Widget *, void *v) { 00204 GraphicsFltkMenu *menu = (GraphicsFltkMenu *)v; 00205 if (!menu->auto_update()) return; 00206 if (menu->molindex < 0 || menu->repindex < 0) return; 00207 int molid = menu->app->molecule_id(menu->molindex); 00208 00209 if (!menu->app->molrep_set_drawframes(molid, menu->repindex, menu->create_multiframecmd())) 00210 fl_alert("The frame selection you typed could not be understood."); 00211 } 00212 00213 static void autoupdate_cb(Fl_Widget *w, void *v) { 00214 Fl_Button *b = (Fl_Button *)w; 00215 ((GraphicsFltkMenu *)v)->set_autoupdate(b->value()); 00216 } 00217 static void colorupdate_cb(Fl_Widget *w, void *v) { 00218 Fl_Button *b = (Fl_Button *)w; 00219 ((GraphicsFltkMenu *)v)->set_colorupdate(b->value()); 00220 } 00221 00222 static void colorscale_minmax_cb(Fl_Widget *, void *v) { 00223 GraphicsFltkMenu *self = (GraphicsFltkMenu *)v; 00224 self->use_colorscale_minmax(); 00225 } 00226 static void colorscale_auto_cb(Fl_Widget *, void *v) { 00227 GraphicsFltkMenu *self = (GraphicsFltkMenu *)v; 00228 self->use_colorscale_auto(); 00229 } 00230 00231 GraphicsFltkMenu::GraphicsFltkMenu(VMDApp *vmdapp) 00232 : VMDFltkMenu("graphics", "Graphical Representations", vmdapp) { 00233 app = vmdapp; 00234 molindex = -1; 00235 lastmolindex = -1; 00236 repindex = -1; 00237 00238 #if defined(REPCOLORTAB) 00239 int grwwidth = 365; 00240 #else 00241 int grwwidth = 315; 00242 #endif 00243 00244 size(grwwidth - 2, 650); 00245 size_range(grwwidth, 650); 00246 { //Fl_Window* o = new Fl_Window(grwwidth, 541); 00247 //w = o; 00248 //o->user_data((void*)(this)); 00249 { Fl_Box* o = repframe = new Fl_Box(5, 55, grwwidth - 10, 170); 00250 o->box(FL_ENGRAVED_FRAME); 00251 } 00252 Fl_Group *q = new Fl_Group(3, 5, grwwidth - 5, 45); 00253 q->resizable(NULL); 00254 { Fl_Choice* o = molchooser = new Fl_Choice(5, 25, grwwidth - 10, 25, "Selected Molecule"); 00255 VMDFLTKTOOLTIP(o, "Select which molecule to create representations for") 00256 o->color(VMDMENU_CHOOSER_BG); 00257 o->selection_color(VMDMENU_CHOOSER_SEL); 00258 o->box(FL_THIN_UP_BOX); 00259 o->align(FL_ALIGN_TOP); 00260 o->callback(molchooser_cb, this); 00261 } 00262 q->end(); 00263 00264 Fl_Group *p = new Fl_Group(5, 60, grwwidth - 15, 50); 00265 p->resizable(NULL); 00266 createnewbutton = new Fl_Button(10, 65, 100, 25, "Create Rep"); 00267 #if defined(VMDMENU_WINDOW) 00268 createnewbutton->color(VMDMENU_WINDOW, FL_GRAY); 00269 #endif 00270 VMDFLTKTOOLTIP(createnewbutton, "Create new copy of selected representation") 00271 createnewbutton->callback(createnew_cb, this); 00272 { Fl_Button* o = deleterepbutton = new Fl_Button(grwwidth - 110, 65, 100, 25, "Delete Rep"); 00273 #if defined(VMDMENU_WINDOW) 00274 deleterepbutton->color(VMDMENU_WINDOW, FL_GRAY); 00275 #endif 00276 VMDFLTKTOOLTIP(deleterepbutton, "Delete selected representation") 00277 o->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE); 00278 o->callback(deleterep_cb, this); 00279 } 00280 new Fl_Box(13,95,110,20, "Style"); 00281 new Fl_Box(123,95,80,20, "Color"); 00282 new Fl_Box(208,95,100,20, "Selection"); 00283 p->end(); 00284 00285 { Fl_Browser* o = repbrowser = new myBrowser(app, this, 10, 115, grwwidth - 20, 100); 00286 VMDFLTKTOOLTIP(o, "Select representation to edit, double-click to toggle on/off") 00287 o->color(VMDMENU_BROWSER_BG); 00288 o->selection_color(VMDMENU_BROWSER_SEL); 00289 o->labeltype(FL_NO_LABEL); 00290 o->column_widths(widths); 00291 o->callback(repbrowser_cb, this); 00292 Fl_Group::current()->resizable(o); 00293 //o->resizable(o); 00294 } 00295 { Fl_Input* o = selectioninput = new Fl_Input(10, 245, grwwidth - 20, 30, "Selected Atoms"); 00296 VMDFLTKTOOLTIP(o, "Select atoms to include in graphical representation") 00297 o->align(FL_ALIGN_TOP); 00298 o->when(FL_WHEN_ENTER_KEY); 00299 o->color(VMDMENU_VALUE_BG); 00300 o->selection_color(VMDMENU_VALUE_SEL); 00301 o->callback(selectioninput_cb, this); 00302 } 00303 00304 Fl_Tabs *tabs = new Fl_Tabs(0, 280, grwwidth, 370); 00305 #if defined(VMDMENU_WINDOW) 00306 tabs->color(VMDMENU_WINDOW, FL_GRAY); 00307 tabs->selection_color(VMDMENU_WINDOW); 00308 #endif 00309 tabs->resizable(NULL); 00310 00311 Fl_Group *stylegroup = new Fl_Group(0, 300, grwwidth, 350, "Draw style"); 00312 #if defined(VMDMENU_WINDOW) 00313 stylegroup->color(VMDMENU_WINDOW, FL_GRAY); 00314 stylegroup->selection_color(VMDMENU_WINDOW); 00315 #endif 00316 00317 { Fl_Choice* o = colorchooser = new Fl_Choice(10, 320, 120, 25, "Coloring Method"); 00318 VMDFLTKTOOLTIP(o, "Select a coloring method for the molecular representation") 00319 o->color(VMDMENU_CHOOSER_BG); 00320 o->selection_color(VMDMENU_CHOOSER_SEL); 00321 o->box(FL_THIN_UP_BOX); 00322 o->align(FL_ALIGN_TOP); 00323 o->callback(colorchooser_cb, this); 00324 } 00325 { Fl_Choice* o = materialchooser = new Fl_Choice(180, 320, 120, 25, "Material"); 00326 VMDFLTKTOOLTIP(o, "Select a material for shading the molecular representation") 00327 o->color(VMDMENU_CHOOSER_BG); 00328 o->selection_color(VMDMENU_CHOOSER_SEL); 00329 o->box(FL_THIN_UP_BOX); 00330 o->align(FL_ALIGN_TOP); 00331 o->callback(materialchooser_cb, this); 00332 } 00333 { Fl_Choice* o = stylechooser = new Fl_Choice(10, 375, 120, 25, "Drawing Method"); 00334 VMDFLTKTOOLTIP(o, "Select a molecular representation drawing method") 00335 o->color(VMDMENU_CHOOSER_BG); 00336 o->selection_color(VMDMENU_CHOOSER_SEL); 00337 o->box(FL_THIN_UP_BOX); 00338 o->callback(repcontrol_cb, this); 00339 o->align(FL_ALIGN_TOP); 00340 } 00341 { Fl_Button* o = defaultbutton = new Fl_Button(180, 375, CTRWIDTH,CTRHEIGHT, "Default"); 00342 #if defined(VMDMENU_WINDOW) 00343 o->color(VMDMENU_WINDOW, FL_GRAY); 00344 #endif 00345 VMDFLTKTOOLTIP(o, "Reset controls to defaults for this drawing method") 00346 o->callback(default_cb, this); 00347 } 00348 00349 // color index chooser, hide initially only shown for ColorID method 00350 { Fl_Choice* o = colindexchooser = new Fl_Choice(130, 320, 50, 25); 00351 o->color(VMDMENU_CHOOSER_BG, VMDMENU_CHOOSER_SEL); 00352 for (int c=0; c<REGCLRS; c++) { 00353 char buf[128] = { 0 }; 00354 sprintf(buf, "%d %s", c, app->scene->color_name(c)); 00355 o->add(buf); 00356 } 00357 o->value(0); 00358 o->callback(colorchooser_cb, this); 00359 o->hide(); 00360 o->deactivate(); 00361 } 00362 00363 // volume index chooser, hide initially only shown for Volume method 00364 { Fl_Choice* o = volindexchooser = new Fl_Choice(130, 320, 50, 25); 00365 o->color(VMDMENU_CHOOSER_BG, VMDMENU_CHOOSER_SEL); 00366 o->value(0); 00367 o->callback(colorchooser_cb, this); 00368 o->hide(); 00369 o->deactivate(); 00370 } 00371 00372 { Fl_Check_Button* o = applyautobutton = new Fl_Check_Button(35, 620, 240, 25, "Apply Changes Automatically"); 00373 #if defined(VMDMENU_WINDOW) 00374 o->color(VMDMENU_WINDOW, FL_GRAY); 00375 #endif 00376 VMDFLTKTOOLTIP(applyautobutton, "Apply changes automatically as they are made") 00377 o->down_box(FL_DIAMOND_DOWN_BOX); 00378 o->align(132|FL_ALIGN_INSIDE); 00379 o->value(1); 00380 } 00381 applybutton = new Fl_Button(255, 620, 45, 25, "Apply"); 00382 VMDFLTKTOOLTIP(applybutton, "Apply representation changes now") 00383 applybutton->callback(apply_cb, this); 00384 00385 repcontrols.add_name("Lines",new GraphicsFltkRepLines(repcontrol_cb, this)); 00386 repcontrols.add_name("Bonds",new GraphicsFltkRepBonds(repcontrol_cb, this)); 00387 repcontrols.add_name("DynamicBonds",new GraphicsFltkRepDynamicBonds(repcontrol_cb, this)); 00388 repcontrols.add_name("HBonds",new GraphicsFltkRepHBonds(repcontrol_cb, this)); 00389 00390 repcontrols.add_name("Points",new GraphicsFltkRepPoints(repcontrol_cb, this)); 00391 repcontrols.add_name("VDW",new GraphicsFltkRepVDW(repcontrol_cb, this)); 00392 repcontrols.add_name("CPK",new GraphicsFltkRepCPK(repcontrol_cb, this)); 00393 repcontrols.add_name("Licorice",new GraphicsFltkRepLicorice(repcontrol_cb, this)); 00394 repcontrols.add_name("Trace",new GraphicsFltkRepTrace(repcontrol_cb, this)); 00395 repcontrols.add_name("Tube",new GraphicsFltkRepTube(repcontrol_cb, this)); 00396 repcontrols.add_name("Ribbons",new GraphicsFltkRepRibbons(repcontrol_cb, this)); 00397 repcontrols.add_name("NewRibbons",new GraphicsFltkRepNewRibbons(repcontrol_cb, this)); 00398 repcontrols.add_name("Cartoon",new GraphicsFltkRepCartoon(repcontrol_cb, this)); 00399 repcontrols.add_name("NewCartoon",new GraphicsFltkRepNewCartoon(repcontrol_cb, this)); 00400 00401 #ifdef VMDWITHCARBS 00402 repcontrols.add_name("PaperChain",new GraphicsFltkRepPaperChain(repcontrol_cb, this)); 00403 repcontrols.add_name("Twister",new GraphicsFltkRepTwister(repcontrol_cb, this)); 00404 #endif 00405 #ifdef VMDPOLYHEDRA 00406 repcontrols.add_name("Polyhedra",new GraphicsFltkRepPolyhedra(repcontrol_cb, this)); 00407 #endif 00408 #ifdef VMDQUICKSURF 00409 // special callback data structure to pass multiple pointers 00410 qsurfcbdata = new quicksurf_cbdata; 00411 qsurfcbdata->self = this; 00412 qsurfcbdata->qsurfrep = new GraphicsFltkRepQuickSurf(quicksurfrepcontrol_cb, qsurfcbdata); 00413 repcontrols.add_name("QuickSurf", qsurfcbdata->qsurfrep); 00414 #endif 00415 repcontrols.add_name("MSMS",new GraphicsFltkRepMSMS(repcontrol_cb, this)); 00416 #ifdef VMDNANOSHAPER 00417 repcontrols.add_name("NanoShaper",new GraphicsFltkRepNanoShaper(repcontrol_cb, this)); 00418 #endif 00419 repcontrols.add_name("Surf",new GraphicsFltkRepSurf(repcontrol_cb, this)); 00420 repcontrols.add_name("VolumeSlice",new GraphicsFltkRepVolumeSlice(repcontrol_cb, this)); 00421 00422 // special callback data structure to pass multiple pointers 00423 isosurfcbdata = new isosurface_cbdata; 00424 isosurfcbdata->self = this; 00425 isosurfcbdata->isorep = new GraphicsFltkRepIsosurface(isosurfacerepcontrol_cb, isosurfcbdata); 00426 repcontrols.add_name("Isosurface", isosurfcbdata->isorep); 00427 repcontrols.add_name("FieldLines", new GraphicsFltkRepFieldLines(repcontrol_cb, this)); 00428 00429 // special callback data structure to pass multiple pointers 00430 orbcbdata = new orbital_cbdata; 00431 orbcbdata->self = this; 00432 orbcbdata->orbrep = new GraphicsFltkRepOrbital(orbitalrepcontrol_cb, orbcbdata); 00433 repcontrols.add_name("Orbital", orbcbdata->orbrep); 00434 00435 repcontrols.add_name("Beads",new GraphicsFltkRepBeads(repcontrol_cb, this)); 00436 repcontrols.add_name("Dotted",new GraphicsFltkRepDotted(repcontrol_cb, this)); 00437 repcontrols.add_name("Solvent",new GraphicsFltkRepSolvent(repcontrol_cb, this)); 00438 #ifdef VMDLATTICECUBES 00439 repcontrols.add_name("LatticeCubes",new GraphicsFltkRepLatticeCubes(repcontrol_cb, this)); 00440 #endif 00441 00442 stylegroup->end(); 00443 selbuilder = new SelectionBuilder(0, 300, this, selectioninput, app->atomSelParser); 00444 #if defined(VMDMENU_WINDOW) 00445 selbuilder->color(VMDMENU_WINDOW, FL_GRAY); 00446 selbuilder->selection_color(VMDMENU_WINDOW); 00447 #endif 00448 selbuilder->end(); 00449 00450 #if defined(REPCOLORTAB) 00458 Fl_Group *colorgroup = new Fl_Group(0, 300, grwwidth, 295, "Color"); 00459 00460 Fl_Box *b2 = new Fl_Box(20, 380, 200, 25, "Color Scale Data Range:"); 00461 VMDFLTKTOOLTIP(b2, "Customize mapping of data to color scale by entering min and max values") 00462 b2->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); 00463 colorscale_min = new Fl_Float_Input(20, 405, 70, 20); 00464 colorscale_min->color(VMDMENU_VALUE_BG, VMDMENU_VALUE_SEL); 00465 colorscale_min->when(FL_WHEN_ENTER_KEY); 00466 colorscale_min->callback(colorscale_minmax_cb, this); 00467 00468 colorscale_max = new Fl_Float_Input(95, 405, 70, 20); 00469 colorscale_max->color(VMDMENU_VALUE_BG, VMDMENU_VALUE_SEL); 00470 colorscale_max->when(FL_WHEN_ENTER_KEY); 00471 colorscale_max->callback(colorscale_minmax_cb, this); 00472 00473 Fl_Button *b3 = new Fl_Button(170, 405, 50, 20, "Set"); 00474 #if defined(VMDMENU_WINDOW) 00475 b3->color(VMDMENU_WINDOW, FL_GRAY); 00476 #endif 00477 b3->callback(colorscale_minmax_cb, this); 00478 00479 Fl_Button *b4 = new Fl_Button(225, 405, 80, 20, "Autoscale"); 00480 #if defined(VMDMENU_WINDOW) 00481 b4->color(VMDMENU_WINDOW, FL_GRAY); 00482 #endif 00483 b4->callback(colorscale_auto_cb, this); 00484 00485 colorgroup->end(); 00486 #endif /* REPCOLORTAB */ 00487 00488 Fl_Group *animationgroup = new Fl_Group(0, 300, grwwidth, 295, "Trajectory"); 00489 #if defined(VMDMENU_WINDOW) 00490 animationgroup->color(VMDMENU_WINDOW, FL_GRAY); 00491 animationgroup->selection_color(VMDMENU_WINDOW); 00492 #endif 00493 00494 autoupdatebutton = new Fl_Check_Button(20, 320, 230, 25, "Update Selection Every Frame"); 00495 autoupdatebutton->callback(autoupdate_cb, this); 00496 autoupdatebutton->down_box(FL_DIAMOND_DOWN_BOX); 00497 autoupdatebutton->align(132 | FL_ALIGN_INSIDE); 00498 autoupdatebutton->value(0); 00499 00500 colorupdatebutton = new Fl_Check_Button(20, 350, 230, 25, "Update Color Every Frame"); 00501 colorupdatebutton->callback(colorupdate_cb, this); 00502 colorupdatebutton->down_box(FL_DIAMOND_DOWN_BOX); 00503 colorupdatebutton->align(132 | FL_ALIGN_INSIDE); 00504 colorupdatebutton->value(0); 00505 00506 #if !defined(REPCOLORTAB) 00507 Fl_Box *b2 = new Fl_Box(20, 380, 200, 25, "Color Scale Data Range:"); 00508 VMDFLTKTOOLTIP(b2, "Customize mapping of data to color scale by entering min and max values") 00509 b2->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); 00510 colorscale_min = new Fl_Float_Input(20, 405, 70, 20); 00511 colorscale_min->color(VMDMENU_VALUE_BG, VMDMENU_VALUE_SEL); 00512 colorscale_min->when(FL_WHEN_ENTER_KEY); 00513 colorscale_min->callback(colorscale_minmax_cb, this); 00514 colorscale_max = new Fl_Float_Input(95, 405, 70, 20); 00515 colorscale_max->color(VMDMENU_VALUE_BG, VMDMENU_VALUE_SEL); 00516 colorscale_max->when(FL_WHEN_ENTER_KEY); 00517 colorscale_max->callback(colorscale_minmax_cb, this); 00518 Fl_Button *b3 = new Fl_Button(170, 405, 50, 20, "Set"); 00519 #if defined(VMDMENU_WINDOW) 00520 b3->color(VMDMENU_WINDOW, FL_GRAY); 00521 #endif 00522 b3->callback(colorscale_minmax_cb, this); 00523 Fl_Button *b4 = new Fl_Button(225, 405, 80, 20, "Autoscale"); 00524 #if defined(VMDMENU_WINDOW) 00525 b4->color(VMDMENU_WINDOW, FL_GRAY); 00526 #endif 00527 b4->callback(colorscale_auto_cb, this); 00528 #endif 00529 00530 new Fl_Box(10, 440, 250, 25, "Draw Multiple Frames: (now, b:e, b:s:e)"); 00531 multiframeinput = new Fl_Input(20, 465, 250, 20); 00532 multiframeinput->align(FL_ALIGN_TOP); 00533 multiframeinput->when(FL_WHEN_ENTER_KEY); 00534 multiframeinput->color(VMDMENU_VALUE_BG); 00535 multiframeinput->selection_color(VMDMENU_VALUE_SEL); 00536 multiframeinput->callback(multiframeinput_cb, this); 00537 multiframeinput->value("now"); 00538 VMDFLTKTOOLTIP(multiframeinput, "Select the frames to be drawn simultaneously") 00539 00540 Fl_Box *b1 = new Fl_Box(30, 490, 300, 25, 00541 "Trajectory Smoothing Window Size:"); 00542 b1->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); 00543 smoothcounter = new ResolutionCounter(70, 515, NULL); 00544 smoothcounter->size(smoothcounter->w(), 20); 00545 smoothcounter->minimum(0); 00546 smoothcounter->callback(smooth_cb, this); 00547 00548 animationgroup->end(); 00549 00550 pbcControls = new PBCControls(0, 300, grwwidth, 295, "Periodic"); 00551 #if defined(VMDMENU_WINDOW) 00552 pbcControls->color(VMDMENU_WINDOW, FL_GRAY); 00553 pbcControls->selection_color(VMDMENU_WINDOW); 00554 #endif 00555 pbcControls->callback(pbc_cb, this); 00556 00557 tabs->end(); 00558 Fl_Window::end(); 00559 00560 for (int j=0; j<repcontrols.num(); j++) { 00561 repcontrols.data(j)->reset(); 00562 repcontrols.data(j)->hide(); 00563 } 00564 } 00565 00566 command_wanted(Command::MOL_NEW); 00567 command_wanted(Command::MOL_DEL); 00568 command_wanted(Command::MOL_ON); 00569 command_wanted(Command::MOL_RENAME); 00570 command_wanted(Command::MOL_VOLUME); 00571 command_wanted(Command::MOL_ADDREP); 00572 command_wanted(Command::MOL_DELREP); 00573 command_wanted(Command::MOL_MODREP); 00574 command_wanted(Command::MOL_MODREPITEM); 00575 command_wanted(Command::MOL_SHOWPERIODIC); 00576 command_wanted(Command::MOL_NUMPERIODIC); 00577 command_wanted(Command::MOL_DRAWFRAMES); 00578 command_wanted(Command::MOL_SCALEMINMAX); 00579 command_wanted(Command::MOL_SMOOTHREP); 00580 command_wanted(Command::MOL_SHOWREP); 00581 command_wanted(Command::MATERIAL_RENAME); 00582 command_wanted(Command::MATERIAL_ADD); 00583 command_wanted(Command::MATERIAL_DELETE); 00584 command_wanted(Command::MOL_REPSELUPDATE); 00585 command_wanted(Command::MOL_REPCOLORUPDATE); 00586 command_wanted(Command::ATOMSEL_ADDMACRO); 00587 command_wanted(Command::ATOMSEL_DELMACRO); 00588 00589 init_colorchooser(); 00590 init_materialchooser(); 00591 init_stylechooser(); 00592 00593 selbuilder->update_macrobrowser(); 00594 } 00595 00596 GraphicsFltkMenu::~GraphicsFltkMenu() { 00597 delete isosurfcbdata; 00598 delete orbcbdata; 00599 delete qsurfcbdata; 00600 } 00601 00602 int GraphicsFltkMenu::auto_update() const { 00603 return applyautobutton->value(); 00604 } 00605 00606 void GraphicsFltkMenu::init_colorchooser() { 00607 colorchooser->clear(); 00608 00609 // Add "pretty" menu names for use in the GUI, which also allows us 00610 // to add submenus and other organizational structure to the menu. 00611 // The cost of this is that we cannot compare indices between menus and 00612 // coloring modes, we have to match strings instead. 00613 for (int j=0; j<AtomColor::TOTAL; j++) 00614 colorchooser->add(AtomColorMenuName[j]); 00615 00616 colorchooser->value(0); // force init to first menu item 00617 00618 // set to "Name" coloring method by default 00619 set_chooser_from_string(AtomColorMenuName[AtomColor::NAME], colorchooser); 00620 } 00621 00622 void GraphicsFltkMenu::init_materialchooser() { 00623 materialchooser->clear(); 00624 for (int j=0; j<app->materialList->num(); j++) 00625 materialchooser->add(app->materialList->material_name(j)); 00626 materialchooser->value(0); 00627 } 00628 00629 void GraphicsFltkMenu::init_stylechooser() { 00630 stylechooser->clear(); 00631 for (int j=0; j<AtomRep::TOTAL; j++) 00632 stylechooser->add(AtomRepInfo[j].name); 00633 stylechooser->value(0); 00634 show_repcontrols(); 00635 } 00636 00637 void GraphicsFltkMenu::isosurfacerepcontrol_cb(Fl_Widget *w, void *v) { 00638 isosurface_cbdata *cbdata = (isosurface_cbdata *) v; 00639 GraphicsFltkMenu *menu = cbdata->self; 00640 GraphicsFltkRepIsosurface *iso = cbdata->isorep; 00641 00642 if (!strcmp(w->label(), "Drawing Method")) 00643 menu->show_repcontrols(); 00644 if (!menu->auto_update()) return; 00645 if (menu->molindex < 0 || menu->repindex < 0) return; 00646 int molid = menu->app->molecule_id(menu->molindex); 00647 00648 if (Fl::event_state(FL_BUTTON1 | FL_BUTTON2 | FL_BUTTON3)) { 00649 if (Fl::event_state(FL_SHIFT | FL_CTRL | FL_ALT | FL_META | FL_BUTTON2 | FL_BUTTON3)) { 00650 // drag callback, with a modifier key pressed 00651 // this allows the user to retain full resolution if they really want 00652 iso->set_grid_stepsize(1); 00653 } else { 00654 // drag callback, use a larger step size while dragging so that the 00655 // isosurface computes more quickly 00656 iso->set_grid_stepsize(2); 00657 } 00658 } else { 00659 // release callback 00660 iso->set_grid_stepsize(1); 00661 } 00662 menu->app->molrep_set_style(molid, menu->repindex, menu->create_repcmd()); 00663 } 00664 00665 00666 void GraphicsFltkMenu::orbitalrepcontrol_cb(Fl_Widget *w, void *v) { 00667 orbital_cbdata *cbdata = (orbital_cbdata *) v; 00668 GraphicsFltkMenu *menu = cbdata->self; 00669 GraphicsFltkRepOrbital *orb = cbdata->orbrep; 00670 00671 if (!strcmp(w->label(), "Drawing Method")) 00672 menu->show_repcontrols(); 00673 00674 // regenerate the excitation list whenever the wavefunction type is changed 00675 if (!strcmp(w->label(), "Wavefunction Type")) { 00676 orb->regen_excitationlist(); 00677 } 00678 00679 // regenerate the orbital list whenever wavefunction type, spin, or 00680 // excitation selections are changed. 00681 if (!strcmp(w->label(), "Wavefunction Type") || 00682 !strcmp(w->label(), "Spin") || 00683 !strcmp(w->label(), "Excitation")) { 00684 orb->regen_orbitallist(); 00685 } 00686 00687 // regenerate the orbital list whenever the user selects a different 00688 // range of orbitals using the "OrbList" counter 00689 if (!strcmp(w->label(), "OrbList")) { 00690 orb->regen_orbitallist(-1); 00691 } 00692 00693 // if the menu isn't set to apply changes automatically, then 00694 // we do nothing further and simply return 00695 if (!menu->auto_update()) return; 00696 00697 if (menu->molindex < 0 || menu->repindex < 0) return; 00698 int molid = menu->app->molecule_id(menu->molindex); 00699 00700 if (Fl::event_state(FL_BUTTON1 | FL_BUTTON2 | FL_BUTTON3)) { 00701 if (Fl::event_state(FL_SHIFT | FL_CTRL | FL_ALT | FL_META | FL_BUTTON2 | FL_BUTTON3)) { 00702 // drag callback, with a modifier key pressed 00703 // this allows the user to retain full resolution if they really want 00704 orb->set_grid_stepsize(1); 00705 } else { 00706 // drag callback, use a larger step size while dragging so that the 00707 // isosurface computes more quickly 00708 orb->set_grid_stepsize(2); 00709 } 00710 } else { 00711 // release callback 00712 orb->set_grid_stepsize(1); 00713 } 00714 menu->app->molrep_set_style(molid, menu->repindex, menu->create_repcmd()); 00715 } 00716 00717 00718 void GraphicsFltkMenu::quicksurfrepcontrol_cb(Fl_Widget *w, void *v) { 00719 quicksurf_cbdata *cbdata = (quicksurf_cbdata *) v; 00720 GraphicsFltkMenu *menu = cbdata->self; 00721 GraphicsFltkRepQuickSurf *qsurf = cbdata->qsurfrep; 00722 00723 if (!strcmp(w->label(), "Drawing Method")) 00724 menu->show_repcontrols(); 00725 00726 // if the menu isn't set to apply changes automatically, then 00727 // we do nothing further and simply return 00728 if (!menu->auto_update()) return; 00729 00730 if (menu->molindex < 0 || menu->repindex < 0) return; 00731 int molid = menu->app->molecule_id(menu->molindex); 00732 00733 if (Fl::event_state(FL_BUTTON1 | FL_BUTTON2 | FL_BUTTON3)) { 00734 if (Fl::event_state(FL_SHIFT | FL_CTRL | FL_ALT | FL_META | FL_BUTTON2 | FL_BUTTON3)) { 00735 // drag callback, with a modifier key pressed 00736 // this allows the user to retain full resolution if they really want 00737 qsurf->set_gridspacing_multiplier(1.0f); 00738 } else { 00739 // drag callback, use a larger grid spacing while dragging so that the 00740 // density map computes more quickly 00741 qsurf->set_gridspacing_multiplier(2.0f); 00742 } 00743 } else { 00744 // release callback 00745 qsurf->set_gridspacing_multiplier(1.0f); 00746 } 00747 00748 // regenerate the parameters when the resolution slider is changed 00749 if (!strcmp(w->label(), "Resolution")) { 00750 qsurf->resolution_changed(); 00751 } 00752 00753 menu->app->molrep_set_style(molid, menu->repindex, menu->create_repcmd()); 00754 } 00755 00756 00757 void GraphicsFltkMenu::molchooser_cb(Fl_Widget *w, void *v) { 00758 Fl_Choice *choice = (Fl_Choice *)w; 00759 GraphicsFltkMenu *menu = (GraphicsFltkMenu *)v; 00760 menu->molindex = choice->value(); 00761 menu->update_molchooser(); 00762 } 00763 00764 void GraphicsFltkMenu::repbrowser_cb(Fl_Widget *w, void *v) { 00765 Fl_Hold_Browser *b = (Fl_Hold_Browser *)w; 00766 GraphicsFltkMenu *menu = (GraphicsFltkMenu *)v; 00767 menu->repindex = b->value()-1; 00768 menu->update_rep(); 00769 } 00770 00771 void GraphicsFltkMenu::repcontrol_cb(Fl_Widget *w, void *v) { 00772 GraphicsFltkMenu *menu = (GraphicsFltkMenu *)v; 00773 if (!strcmp(w->label(), "Drawing Method")) 00774 menu->show_repcontrols(); 00775 if (!menu->auto_update()) return; 00776 if (menu->molindex < 0 || menu->repindex < 0) return; 00777 int molid = menu->app->molecule_id(menu->molindex); 00778 menu->app->molrep_set_style(molid, menu->repindex, menu->create_repcmd()); 00779 } 00780 00781 void GraphicsFltkMenu::colorchooser_cb(Fl_Widget *w, void *v) { 00782 GraphicsFltkMenu *menu = (GraphicsFltkMenu *)v; 00783 menu->colindex_visible(); 00784 menu->volindex_visible(); 00785 if (!menu->auto_update()) return; 00786 if (menu->molindex < 0 || menu->repindex < 0) return; 00787 int molid = menu->app->molecule_id(menu->molindex); 00788 menu->app->molrep_set_color(molid, menu->repindex, menu->create_colorcmd()); 00789 } 00790 00791 void GraphicsFltkMenu::selectioninput_cb(Fl_Widget *, void *v) { 00792 GraphicsFltkMenu *menu = (GraphicsFltkMenu *)v; 00793 if (!menu->auto_update()) return; 00794 if (menu->molindex < 0 || menu->repindex < 0) return; 00795 int molid = menu->app->molecule_id(menu->molindex); 00796 if (!menu->app->molrep_set_selection(molid, menu->repindex, menu->create_selcmd())) 00797 fl_alert("The atom selection you typed could not be understood."); 00798 } 00799 00800 void GraphicsFltkMenu::materialchooser_cb(Fl_Widget *, void *v) { 00801 GraphicsFltkMenu *menu = (GraphicsFltkMenu *)v; 00802 if (!menu->auto_update()) return; 00803 if (menu->molindex < 0 || menu->repindex < 0) return; 00804 int molid = menu->app->molecule_id(menu->molindex); 00805 menu->app->molrep_set_material(molid, menu->repindex, menu->create_matcmd()); 00806 } 00807 00808 void GraphicsFltkMenu::createnew_cb(Fl_Widget *w, void *v) { 00809 GraphicsFltkMenu *menu = (GraphicsFltkMenu *)v; 00810 00811 menu->app->molecule_set_color(menu->create_colorcmd()); 00812 menu->app->molecule_set_style(menu->create_repcmd()); 00813 menu->app->molecule_set_selection(menu->create_selcmd()); 00814 menu->app->molecule_set_material(menu->create_matcmd()); 00815 int molid = menu->app->molecule_id(menu->molindex); 00816 menu->app->molecule_addrep(molid); 00817 } 00818 00819 void GraphicsFltkMenu::deleterep_cb(Fl_Widget *w, void *v) { 00820 GraphicsFltkMenu *menu = (GraphicsFltkMenu *)v; 00821 int molid = menu->app->molecule_id(menu->molindex); 00822 menu->app->molrep_delete(molid, menu->repindex); 00823 } 00824 00825 void GraphicsFltkMenu::apply_cb(Fl_Widget *w, void *v) { 00826 GraphicsFltkMenu *menu = (GraphicsFltkMenu *)v; 00827 if (menu->molindex < 0 || menu->repindex < 0) return; 00828 00829 int molid = menu->app->molecule_id(menu->molindex); 00830 menu->app->molecule_set_color(menu->create_colorcmd()); 00831 menu->app->molecule_set_style(menu->create_repcmd()); 00832 menu->app->molecule_set_selection(menu->create_selcmd()); 00833 menu->app->molecule_set_material(menu->create_matcmd()); 00834 menu->app->molecule_modrep(molid, menu->repindex); 00835 } 00836 00837 void GraphicsFltkMenu::default_cb(Fl_Widget *, void *v) { 00838 GraphicsFltkMenu *menu = (GraphicsFltkMenu *)v; 00839 menu->reset_rep(); 00840 GraphicsFltkMenu::apply_cb(0, menu); 00841 } 00842 00843 void GraphicsFltkMenu::smooth_cb(Fl_Widget *, void *v) { 00844 GraphicsFltkMenu *menu = (GraphicsFltkMenu *)v; 00845 int molid = menu->app->molecule_id(menu->molindex); 00846 menu->app->molrep_set_smoothing(molid, menu->repindex, 00847 (int)menu->smoothcounter->value()); 00848 } 00849 00850 void GraphicsFltkMenu::use_colorscale_minmax() { 00851 if (molindex >= 0 && repindex >= 0) { 00852 int molid = app->molecule_id(molindex); 00853 float min = (float) atof(colorscale_min->value()); 00854 float max = (float) atof(colorscale_max->value()); 00855 if (!app->molrep_set_scaleminmax(molid, repindex, min, max)) { 00856 fl_alert("Could not set color scale data range with values %s-%s", 00857 colorscale_min->value(), colorscale_max->value()); 00858 } 00859 } 00860 } 00861 00862 void GraphicsFltkMenu::use_colorscale_auto() { 00863 if (molindex >= 0 && repindex >= 0) { 00864 int molid = app->molecule_id(molindex); 00865 if (!app->molrep_reset_scaleminmax(molid, repindex)) { 00866 fl_alert("Could not autoscale color scale data range."); 00867 } else { // update Min/Max text fields 00868 float min=0, max=0; 00869 char buf[128] = { 0 }; // must hold potentially huge FP numbers 00870 app->molrep_get_scaleminmax(molid, repindex, &min, &max); 00871 sprintf(buf, "%3.2f", min); 00872 colorscale_min->value(buf); 00873 sprintf(buf, "%3.2f", max); 00874 colorscale_max->value(buf); 00875 } 00876 } 00877 } 00878 00879 void GraphicsFltkMenu::update_selection(const char *s) { 00880 if (s) { 00881 selectioninput->value(s); 00882 selectioninput->do_callback(); 00883 } else { 00884 int id = app->molecule_id(molindex); 00885 const char *txt = app->molrep_get_selection(id, repindex); 00886 if (txt) { 00887 selectioninput->value(s); 00888 // XXX this causes the user to see an error box for no good reason 00889 // selectioninput->do_callback(); 00890 } 00891 } 00892 } 00893 00894 const char *GraphicsFltkMenu::selectiontext() const { 00895 return selectioninput->value(); 00896 } 00897 00898 void GraphicsFltkMenu::reset_rep() { 00899 int typecode = repcontrols.typecode(stylechooser->text()); 00900 // assert(typecode >= 0); 00901 repcontrols.data(typecode)->reset(); 00902 } 00903 00904 void GraphicsFltkMenu::update_molchooser() { 00905 fill_fltk_molchooser(molchooser, app, NULL); 00906 volindex_update(); 00907 00908 if (molindex >= 0) { 00909 Molecule *m = app->moleculeList->molecule(molindex); 00910 00911 #if 0 00912 // disable volumetric coloring/reps if no volume data loaded 00913 int volmode = 0; // no flags by default, item active 00914 if (m->num_volume_data() < 1) { 00915 volmode = FL_MENU_INACTIVE; 00916 } 00917 colorchooser->mode(find_menu_from_string(AtomColorName[AtomColor::VOLUME], colorchooser->menu()), volmode); 00918 stylechooser->mode(AtomRep::VOLSLICE, volmode); 00919 stylechooser->mode(AtomRep::ISOSURFACE, volmode); 00920 stylechooser->mode(AtomRep::FIELDLINES, volmode); 00921 #endif 00922 00923 molchooser->value(molindex); 00924 for (int k=0; k<repcontrols.num(); k++) { 00925 if (repcontrols.data(k)->is_volumetric()) { 00926 GraphicsFltkRepVolumetric *rep = 00927 (GraphicsFltkRepVolumetric *)repcontrols.data(k); 00928 rep->dataset_clear(); 00929 for (int j=0; j<m->num_volume_data(); j++) { 00930 VolumetricData *data = m->modify_volume_data(j); 00931 float datamin, datamax; 00932 data->datarange(datamin, datamax); 00933 rep->dataset_append(data->name, datamin, datamax); 00934 } 00935 } 00936 00937 // deal with Orbital reps 00938 if (repcontrols.data(k)->is_orbital()) { 00939 GraphicsFltkRepOrbital *rep = 00940 (GraphicsFltkRepOrbital *)repcontrols.data(k); 00941 00942 // update the list of available wavefunction types 00943 rep->regen_wavefunctypes(); 00944 00945 // regenerate the orbital chooser contents based on the 00946 // currently selected wavefunction type, spin, and excitation 00947 rep->regen_orbitallist(); 00948 } 00949 } 00950 } else { 00951 molchooser->redraw(); 00952 } 00953 selbuilder->use_molecule(app->moleculeList->molecule(molindex)); 00954 app->highlighted_molid = app->molecule_id(molindex); 00955 update_repindex(); 00956 update_repbrowser(); 00957 } 00958 00959 void GraphicsFltkMenu::update_repbrowser(bool remember_position) { 00960 int vposition = repbrowser->position(); 00961 repbrowser->clear(); 00962 Molecule *mol = app->moleculeList->molecule(molindex); 00963 if (!mol) return; 00964 00965 for (int j=0; j<mol->components(); j++) { 00966 DrawMolItem *d = mol->component(j); 00967 add_rep_to_browser(d, repbrowser, 0); 00968 } 00969 // assert(repindex < repbrowser->size()); 00970 if (repindex >= 0) { 00971 repbrowser->select(repindex+1); 00972 if (remember_position) 00973 repbrowser->position(vposition); 00974 } 00975 update_rep(); 00976 } 00977 00978 void GraphicsFltkMenu::update_rep() { 00979 if (molindex >= 0 && repindex >= 0) { 00980 Molecule *m = app->moleculeList->molecule(molindex); 00981 DrawMolItem *d = m->component(repindex); 00982 00983 // colors 00984 AtomColor *ac = d->atomColor; 00985 00986 // find the named menu item, set it active if a match is found 00987 set_chooser_from_string(AtomColorMenuName[ac->method()], colorchooser); 00988 00989 // volume texturing 00990 volindex_visible(); 00991 if (ac->method() == AtomColor::VOLUME){ 00992 volindexchooser->value(ac->volume_index()); 00993 } 00994 00995 // coloring method 00996 colindex_visible(); 00997 if (ac->method() == AtomColor::COLORID){ 00998 colindexchooser->value(ac->color_index()); 00999 } 01000 01001 colorupdatebutton->value(ac->do_update); 01002 float min=0, max=0; 01003 char buf[128] = { 0 }; // must hold potentially huge FP numbers 01004 ac->get_colorscale_minmax(&min, &max); 01005 sprintf(buf, "%3.2f", min); 01006 colorscale_min->value(buf); 01007 sprintf(buf, "%3.2f", max); 01008 colorscale_max->value(buf); 01009 01010 materialchooser->value(d->curr_material()); 01011 AtomRep *ar = d->atomRep; 01012 if (stylechooser->value() != ar->method()) { 01013 stylechooser->value(ar->method()); 01014 show_repcontrols(); 01015 } 01016 repcontrols.data(stylechooser->text())->set_values(ar); 01017 AtomSel *as = d->atomSel; 01018 selectioninput->value(as->cmdStr); 01019 if (ar->is_volumetric()) selectioninput->deactivate(); 01020 else selectioninput->activate(); 01021 selbuilder->set_selection(as->cmdStr); 01022 autoupdatebutton->value(as->do_update); 01023 smoothcounter->value((double)d->get_smoothing()); 01024 multiframeinput->value(d->get_drawframes()); 01025 update_pbc(); 01026 } 01027 app->highlighted_rep = repindex; 01028 } 01029 01030 // update the pbc controls for the current rep 01031 void GraphicsFltkMenu::update_pbc() { 01032 if (molindex >= 0 && repindex >= 0) { 01033 Molecule *m = app->moleculeList->molecule(molindex); 01034 const DrawMolItem *d = m->component(repindex); 01035 int pbc = d->get_pbc(); 01036 int n = d->get_pbc_images(); 01037 pbcControls->update(pbc, n); 01038 } 01039 } 01040 01041 // set pbc values for the current rep, if any 01042 void GraphicsFltkMenu::set_pbc(int pbc, int n) { 01043 if (molindex >= 0 && repindex >= 0) { 01044 Molecule *m = app->moleculeList->molecule(molindex); 01045 int id = m->id(); 01046 app->molrep_set_pbc(id, repindex, pbc); 01047 app->molrep_set_pbc_images(id, repindex, n); 01048 } 01049 } 01050 01051 void GraphicsFltkMenu::set_autoupdate(int on) { 01052 if (molindex >= 0 && repindex >= 0) { 01053 int id = app->molecule_id(molindex); 01054 app->molrep_set_selupdate(id, repindex, on); 01055 } 01056 } 01057 01058 void GraphicsFltkMenu::set_colorupdate(int on) { 01059 if (molindex >= 0 && repindex >= 0) { 01060 int id = app->molecule_id(molindex); 01061 app->molrep_set_colorupdate(id, repindex, on); 01062 } 01063 } 01064 01065 void GraphicsFltkMenu::update_repindex() { 01066 // auto-grow the rep index array as needed, initializing reps to -1 01067 while (molactiverep.num() <= lastmolindex) { 01068 molactiverep.append(-1); 01069 } 01070 01071 // save active repindex for last molecule accessed before we update 01072 Molecule *oldmol = app->moleculeList->molecule(lastmolindex); 01073 if (oldmol) { 01074 molactiverep[lastmolindex] = repindex; 01075 } 01076 01077 // see if new molecule exists 01078 Molecule *mol = app->moleculeList->molecule(molindex); 01079 if (!mol) { 01080 repindex = -1; 01081 return; 01082 } 01083 01084 // auto-grow the rep index array as needed, initializing reps to -1 01085 while (molactiverep.num() <= molindex) { 01086 molactiverep.append(-1); 01087 } 01088 01089 // retrieve previous rep index for this molecule 01090 repindex = molactiverep[molindex]; 01091 lastmolindex = molindex; 01092 01093 // bounds check the repindex before returning 01094 int n = mol->components(); 01095 if (n > 0 && repindex == -1) { 01096 repindex = 0; 01097 return; 01098 } 01099 if (repindex >= n) { 01100 repindex = n-1; 01101 } 01102 } 01103 01104 void GraphicsFltkMenu::show_repcontrols() { 01105 for (int j=0; j<repcontrols.num(); j++) 01106 repcontrols.data(j)->hide(); 01107 01108 int typecode = repcontrols.typecode(stylechooser->text()); 01109 // assert(typecode >= 0); 01110 repcontrols.data(typecode)->show(); 01111 redraw(); 01112 } 01113 01114 char *GraphicsFltkMenu::create_repcmd() { 01115 int typecode = repcontrols.typecode(stylechooser->text()); 01116 // assert(typecode >= 0); 01117 return (char *)repcontrols.data(typecode)->repcmd(); 01118 } 01119 01120 char *GraphicsFltkMenu::create_colorcmd() { 01121 // find the coloring method mode that matches the currently selected 01122 // colorchooser item name 01123 int colorval = find_name_string_from_menuname(colorchooser->text(), AtomColorMenuName, AtomColor::TOTAL); 01124 01125 // if we got a valid color name index, set the color command text 01126 if (colorval >= 0) { 01127 if (colorval == AtomColor::COLORID) { 01128 sprintf(colorcmdbuf, "%s %d", AtomColorName[colorval], 01129 colindexchooser->value()); 01130 } else if (colorval == AtomColor::VOLUME) { 01131 sprintf(colorcmdbuf, "%s %d", AtomColorName[colorval], 01132 volindexchooser->value()); 01133 } else { 01134 strcpy(colorcmdbuf, AtomColorName[colorval]); 01135 } 01136 } else { 01137 colorcmdbuf[0] = '0円'; 01138 } 01139 01140 return colorcmdbuf; 01141 } 01142 01143 char *GraphicsFltkMenu::create_selcmd() { 01144 return (char *)(selectioninput->value()); 01145 } 01146 01147 char *GraphicsFltkMenu::create_matcmd() { 01148 return (char *)(materialchooser->text()); 01149 } 01150 01151 char *GraphicsFltkMenu::create_multiframecmd() { 01152 return (char *)(multiframeinput->value()); 01153 } 01154 01155 void GraphicsFltkMenu::colindex_visible() { 01156 // compare menu names to check for a match, since indices aren't correlated 01157 if (!strcmp(AtomColorMenuName[AtomColor::COLORID], colorchooser->text())) { 01158 colindexchooser->show(); 01159 colindexchooser->activate(); 01160 } else { 01161 colindexchooser->hide(); 01162 colindexchooser->deactivate(); 01163 } 01164 } 01165 01166 void GraphicsFltkMenu::volindex_visible() { 01167 // compare menu names to check for a match, since indices aren't correlated 01168 if (!strcmp(AtomColorMenuName[AtomColor::VOLUME], colorchooser->text())) { 01169 volindexchooser->show(); 01170 volindexchooser->activate(); 01171 } else { 01172 volindexchooser->hide(); 01173 volindexchooser->deactivate(); 01174 } 01175 } 01176 01177 void GraphicsFltkMenu::volindex_update() { 01178 int newvolid = volindexchooser->value(); 01179 volindexchooser->clear(); 01180 01181 // XXX This code makes the short-term assumption that volume ID's are 01182 // sequentially numbered with no gaps, presently true but ultimately 01183 // this will break once volumes can be deleted. Needs to use an extra 01184 // GUI index to volume index mapping array to be correct long-term, much 01185 // like we do with molecules. 01186 if (molindex >= 0) { 01187 Molecule *m = app->moleculeList->molecule(molindex); 01188 for (int j=0; j<m->num_volume_data(); j++) { 01189 char volnamebuf[80]; 01190 const VolumetricData *data = m->get_volume_data(j); 01191 01192 memset(volnamebuf, 0, sizeof(volnamebuf)); 01193 sprintf(volnamebuf, "%d: ", j); 01194 strncpy(volnamebuf+strlen(volnamebuf), data->name, (sizeof(volnamebuf) - strlen(volnamebuf) - 2)); 01195 01196 // Fltk doesn't allow adding a menu item with the same name as 01197 // an existing item, so we use replace, which also avoids 01198 // problems with the escape characters interpreted by add() 01199 int ind = volindexchooser->add("foobar"); 01200 volindexchooser->replace(ind, volnamebuf); 01201 } 01202 01203 // range-check the old volume index against what we have now 01204 // if the old index is now out of range, set it to zero. 01205 if ((newvolid < 0) || (newvolid >= m->num_volume_data())) 01206 newvolid = 0; 01207 volindexchooser->value(newvolid); 01208 } 01209 } 01210 01211 int GraphicsFltkMenu::act_on_command(int type, Command *cmd) { 01212 if (type == Command::MOL_NEW || type == Command::MOL_DEL || 01213 type == Command::MOL_VOLUME || type == Command::MOL_RENAME) { 01214 Molecule *mol = app->moleculeList->top(); 01215 if (mol) 01216 molindex = app->moleculeList->mol_index_from_id(mol->id()); 01217 else 01218 molindex = -1; 01219 update_repindex(); 01220 update_molchooser(); 01221 } else if (type == Command::MOL_ON) { 01222 update_molchooser(); 01223 01224 } else if (type == Command::MOL_ADDREP || type == Command::MOL_DELREP || 01225 type == Command::MOL_MODREP || type == Command::MOL_MODREPITEM || 01226 type == Command::MOL_DRAWFRAMES || 01227 type == Command::MOL_SCALEMINMAX || 01228 type == Command::MOL_SHOWREP || 01229 type == Command::MOL_SMOOTHREP) { 01230 if (type == Command::MOL_DELREP) { 01231 int delrep = ((CmdMolDeleteRep *)cmd)->repn; 01232 if (delrep < repindex) --repindex; 01233 } else if (type == Command::MOL_ADDREP) { 01234 // make update_repindex highlight the last rep 01235 repindex = 99999; 01236 } 01237 01238 // Keep the browser line at the same position unless we're adding 01239 // or deleting representations. 01240 bool remember_position = true; 01241 if (type == Command::MOL_ADDREP || type == Command::MOL_DELREP) 01242 remember_position = false; 01243 update_repindex(); 01244 update_repbrowser(remember_position); 01245 } else if (type == Command::MATERIAL_RENAME 01246 || type == Command::MATERIAL_ADD 01247 || type == Command::MATERIAL_DELETE) { 01248 int cur = materialchooser->value(); 01249 MaterialList *mlist = app->materialList; 01250 materialchooser->clear(); 01251 for (int m=0; m<mlist->num(); m++) { 01252 materialchooser->add(mlist->material_name(m)); 01253 } 01254 if (type != Command::MATERIAL_DELETE) { 01255 materialchooser->value(cur); 01256 } else { 01257 if (molindex >= 0 && repindex >= 0) { 01258 Molecule *mol = app->moleculeList->molecule(molindex); 01259 DrawMolItem *d = mol->component(repindex); 01260 materialchooser->value(d->curr_material()); 01261 } else { 01262 materialchooser->value(0); 01263 } 01264 } 01265 } else if (type == Command::MOL_REPSELUPDATE || 01266 type == Command::MOL_REPCOLORUPDATE) { 01267 update_rep(); 01268 } else if (type == Command::ATOMSEL_ADDMACRO || 01269 type == Command::ATOMSEL_DELMACRO) { 01270 selbuilder->update_macrobrowser(); 01271 01272 } else if (type == Command::MOL_SHOWPERIODIC || 01273 type == Command::MOL_NUMPERIODIC) { 01274 update_pbc(); 01275 } else { 01276 return FALSE; 01277 } 01278 return TRUE; 01279 } 01280 01281 01282 int GraphicsFltkMenu::selectmol(int selmol) { 01283 if (selmol >= 0 && selmol < molchooser->size()-1) 01284 molindex = selmol; 01285 update_molchooser(); 01286 return TRUE; 01287 } 01288