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: GraphicsFltkReps.h,v $ 00013 * $Author: johns $ $Locker: $ $State: Exp $ 00014 * $Revision: 1.141 $ $Date: 2020年10月28日 17:42:35 $ 00015 * 00016 *************************************************************************** 00017 * DESCRIPTION: 00018 * generated by Fast Light User Interface Designer (fluid) version 1.0011 00019 ***************************************************************************/ 00020 00021 #include <stdio.h> 00022 #include <stdlib.h> 00023 #include <math.h> 00024 #include "FL/forms.H" 00025 #include "FL/Fl_Counter.H" 00026 #include "FL/Fl_Value_Slider.H" 00027 #include "FL/Fl_Float_Input.H" 00028 #include "FL/Fl_Tabs.H" 00029 #include "AtomRep.h" 00030 #include "Molecule.h" 00031 #include "VMDApp.h" 00032 #include "MoleculeList.h" 00033 00034 00038 class GraphicsFltkRep : public Fl_Group { 00039 protected: 00040 GraphicsFltkRep() 00041 : Fl_Group(10, 380, 295, 235) {} 00042 virtual void do_reset() {} 00043 00044 char cmdbuf[256]; 00045 00046 public: 00047 virtual int is_volumetric() { return 0; } 00048 virtual int is_orbital() { return 0; } 00049 virtual const char *repcmd() = 0; 00050 virtual void set_values(AtomRep *) = 0; 00051 void reset() { do_reset(); } 00052 }; 00053 00054 00055 #define CTRWIDTH 120 00056 #define CTRWIDTHSM 80 00057 #define CTRHEIGHT 25 00058 00060 class RadiusCounter : public Fl_Counter { 00061 public: 00062 RadiusCounter(int x, int y, const char *nm) 00063 : Fl_Counter(x, y, CTRWIDTH, CTRHEIGHT, nm) { 00064 minimum(0); 00065 precision(1); 00066 step(.1); 00067 lstep(1); 00068 align(FL_ALIGN_LEFT); 00069 when(FL_WHEN_RELEASE); 00070 } 00071 }; 00072 00073 00075 class GridResCounter : public Fl_Counter { 00076 public: 00077 GridResCounter(int x, int y, const char *nm) 00078 : Fl_Counter(x, y, CTRWIDTH, CTRHEIGHT, nm) { 00079 minimum(0.05); 00080 precision(3); 00081 step(0.005); 00082 lstep(0.025); 00083 align(FL_ALIGN_LEFT); 00084 when(FL_WHEN_RELEASE); 00085 } 00086 }; 00087 00088 00090 class DeltaCounter : public Fl_Counter { 00091 public: 00092 DeltaCounter(int x, int y, const char *nm) 00093 : Fl_Counter(x, y, CTRWIDTH, CTRHEIGHT, nm) { 00094 minimum(0.05); 00095 precision(3); 00096 step(0.005); 00097 lstep(0.025); 00098 align(FL_ALIGN_LEFT); 00099 when(FL_WHEN_RELEASE); 00100 } 00101 }; 00102 00103 00105 class ResolutionCounter : public Fl_Counter { 00106 public: 00107 ResolutionCounter(int x, int y, const char *nm) 00108 : Fl_Counter(x, y, CTRWIDTH, CTRHEIGHT, nm) { 00109 minimum(1); 00110 precision(0); 00111 step(1); 00112 lstep(5); 00113 align(FL_ALIGN_LEFT); 00114 when(FL_WHEN_RELEASE); 00115 } 00116 }; 00117 00118 00120 class StepCounter : public Fl_Counter { 00121 public: 00122 StepCounter(int x, int y, const char *nm) 00123 : Fl_Counter(x, y, 90, CTRHEIGHT, nm) { 00124 minimum(1); 00125 precision(0); 00126 step(1); 00127 lstep(4); 00128 align(FL_ALIGN_LEFT); 00129 when(FL_WHEN_RELEASE); 00130 } 00131 }; 00132 00133 00135 class RepChoice : public Fl_Choice { 00136 public: 00137 RepChoice(int x, int y, const char *nm) 00138 : Fl_Choice(x, y, CTRWIDTH, CTRHEIGHT, nm) { 00139 color(VMDMENU_CHOOSER_BG); 00140 selection_color(VMDMENU_CHOOSER_SEL); 00141 align(FL_ALIGN_LEFT); 00142 } 00143 int setvalue(int newvalue) { 00144 if (newvalue >= 0 && newvalue < size()) 00145 return Fl_Choice::value(newvalue); 00146 return value(); 00147 } 00148 }; 00149 00151 class RepChoiceSmall : public Fl_Choice { 00152 public: 00153 RepChoiceSmall(int x, int y, const char *nm) 00154 : Fl_Choice(x, y, CTRWIDTHSM, CTRHEIGHT, nm) { 00155 color(VMDMENU_CHOOSER_BG); 00156 selection_color(VMDMENU_CHOOSER_SEL); 00157 align(FL_ALIGN_LEFT); 00158 } 00159 int setvalue(int newvalue) { 00160 if (newvalue >= 0 && newvalue < size()) 00161 return Fl_Choice::value(newvalue); 00162 return value(); 00163 } 00164 }; 00165 00166 00168 class IsoSlider : public Fl_Value_Slider { 00169 public: 00170 IsoSlider(int x, int y, const char *nm) 00171 : Fl_Value_Slider(x, y, CTRWIDTH+90, CTRHEIGHT, nm) { 00172 color(VMDMENU_SLIDER_BG); 00173 align(FL_ALIGN_LEFT); 00174 type(FL_HOR_SLIDER); 00175 } 00176 }; 00177 00179 class ShortSlider : public Fl_Value_Slider { 00180 public: 00181 ShortSlider(int x, int y, const char *nm) 00182 : Fl_Value_Slider(x, y, CTRWIDTH+50, CTRHEIGHT, nm) { 00183 color(VMDMENU_SLIDER_BG); 00184 align(FL_ALIGN_LEFT); 00185 type(FL_HOR_SLIDER); 00186 } 00187 }; 00188 00190 class GraphicsFltkRepLines : public GraphicsFltkRep { 00191 public: 00192 GraphicsFltkRepLines(Fl_Callback *cb, void *v) { 00193 thickness = new ResolutionCounter(x()+170, y()+120, "Thickness"); 00194 thickness->callback(cb, v); 00195 Fl_Group::end(); 00196 } 00197 const char *repcmd() { 00198 sprintf(cmdbuf, "Lines %f", thickness->value()); 00199 return cmdbuf; 00200 } 00201 void set_values(AtomRep *rep) { 00202 thickness->value(rep->get_data(AtomRep::LINETHICKNESS)); 00203 } 00204 00205 protected: 00206 void do_reset() { 00207 thickness->value(1); 00208 } 00209 00210 private: 00211 Fl_Counter *thickness; 00212 }; 00213 00214 00216 class GraphicsFltkRepBonds : public GraphicsFltkRep { 00217 public: 00218 GraphicsFltkRepBonds(Fl_Callback *cb, void *v) { 00219 radius = new RadiusCounter(x()+170, y()+90, "Bond Radius"); 00220 resolution= new ResolutionCounter(x()+170,y()+120,"Bond Resolution"); 00221 radius->callback(cb, v); 00222 resolution->callback(cb, v); 00223 Fl_Group::end(); 00224 } 00225 const char *repcmd() { 00226 sprintf(cmdbuf, "Bonds %f %f", radius->value(), resolution->value()); 00227 return cmdbuf; 00228 } 00229 void set_values(AtomRep *rep) { 00230 radius->value(rep->get_data(AtomRep::BONDRAD)); 00231 resolution->value(rep->get_data(AtomRep::BONDRES)); 00232 } 00233 00234 protected: 00235 void do_reset() { 00236 radius->value(0.3); 00237 resolution->value(12); 00238 } 00239 00240 protected: 00241 Fl_Counter *radius; 00242 Fl_Counter *resolution; 00243 }; 00244 00245 00247 class GraphicsFltkRepDynamicBonds : public GraphicsFltkRep { 00248 private: 00249 Fl_Counter *distance; 00250 Fl_Counter *radius; 00251 Fl_Counter *resolution; 00252 public: 00253 GraphicsFltkRepDynamicBonds(Fl_Callback *cb, void *v) { 00254 distance = new RadiusCounter(x()+170,y()+60,"Distance Cutoff"); 00255 distance->callback(cb, v); 00256 radius = new RadiusCounter(x()+170, y()+90, "Bond Radius"); 00257 radius->callback(cb, v); 00258 resolution= new ResolutionCounter(x()+170,y()+120,"Bond Resolution"); 00259 resolution->callback(cb, v); 00260 Fl_Group::end(); 00261 } 00262 protected: 00263 void do_reset() { 00264 distance->value(1.6); 00265 radius->value(0.3); 00266 resolution->value(12.0); 00267 } 00268 public: 00269 const char *repcmd() { 00270 sprintf(cmdbuf, "DynamicBonds %f %f %f", distance->value(), radius->value(), 00271 resolution->value()); 00272 return cmdbuf; 00273 } 00274 void set_values(AtomRep *rep) { 00275 distance->value(rep->get_data(AtomRep::SPHERERAD)); 00276 radius->value(rep->get_data(AtomRep::BONDRAD)); 00277 resolution->value(rep->get_data(AtomRep::BONDRES)); 00278 } 00279 }; 00280 00281 00283 class GraphicsFltkRepCPK : public GraphicsFltkRep { 00284 public: 00285 GraphicsFltkRepCPK(Fl_Callback *cb, void *v) { 00286 bradius = new RadiusCounter(x()+170,y()+90,"Bond Radius"); 00287 bresolution= new ResolutionCounter(x()+170,y()+120,"Bond Resolution"); 00288 bradius->callback(cb, v); 00289 bresolution->callback(cb, v); 00290 00291 sradius = new RadiusCounter(x()+170,y()+30,"Sphere Scale"); 00292 sresolution= new ResolutionCounter(x()+170,y()+60,"Sphere Resolution"); 00293 sradius->callback(cb, v); 00294 sresolution->callback(cb, v); 00295 00296 Fl_Group::end(); 00297 } 00298 00299 const char *repcmd() { 00300 sprintf(cmdbuf, "CPK %f %f %f %f", sradius->value(), bradius->value(), 00301 sresolution->value(), bresolution->value()); 00302 return cmdbuf; 00303 } 00304 void set_values(AtomRep *rep) { 00305 bradius->value(rep->get_data(AtomRep::BONDRAD)); 00306 bresolution->value(rep->get_data(AtomRep::BONDRES)); 00307 sradius->value(rep->get_data(AtomRep::SPHERERAD)); 00308 sresolution->value(rep->get_data(AtomRep::SPHERERES)); 00309 } 00310 00311 protected: 00312 void do_reset() { 00313 bradius->value(0.3); 00314 bresolution->value(12); 00315 sradius->value(1.0); 00316 sresolution->value(12); 00317 } 00318 00319 private: 00320 Fl_Counter *bradius; 00321 Fl_Counter *bresolution; 00322 Fl_Counter *sradius; 00323 Fl_Counter *sresolution; 00324 }; 00325 00326 00328 class GraphicsFltkRepPoints : public GraphicsFltkRep { 00329 public: 00330 GraphicsFltkRepPoints(Fl_Callback *cb, void *v) { 00331 size = new ResolutionCounter(x()+170, y()+120, "Size"); 00332 size->callback(cb, v); 00333 Fl_Group::end(); 00334 } 00335 const char *repcmd() { 00336 sprintf(cmdbuf, "Points %f", size->value()); 00337 return cmdbuf; 00338 } 00339 void set_values(AtomRep *rep) { 00340 size->value(rep->get_data(AtomRep::LINETHICKNESS)); 00341 } 00342 00343 protected: 00344 void do_reset() { 00345 size->value(1); 00346 } 00347 00348 private: 00349 Fl_Counter *size; 00350 }; 00351 00352 00353 #if defined(VMDLATTICECUBES) 00354 00355 class GraphicsFltkRepLatticeCubes : public GraphicsFltkRep { 00356 public: 00357 GraphicsFltkRepLatticeCubes(Fl_Callback *cb, void *v) { 00358 radius = new RadiusCounter(x()+170,y()+90,"Sphere Scale"); 00359 radius->callback(cb, v); 00360 Fl_Group::end(); 00361 } 00362 00363 const char *repcmd() { 00364 sprintf(cmdbuf, "LatticeCubes %f", radius->value()); 00365 return cmdbuf; 00366 } 00367 void set_values(AtomRep *rep) { 00368 radius->value(rep->get_data(AtomRep::SPHERERAD)); 00369 } 00370 00371 protected: 00372 void do_reset() { 00373 radius->value(1.0); 00374 } 00375 00376 protected: 00377 Fl_Counter *radius; 00378 }; 00379 #endif 00380 00381 00383 class GraphicsFltkRepVDW : public GraphicsFltkRep { 00384 public: 00385 GraphicsFltkRepVDW(Fl_Callback *cb, void *v) { 00386 radius = new RadiusCounter(x()+170,y()+90,"Sphere Scale"); 00387 resolution= new ResolutionCounter(x()+170,y()+120,"Sphere Resolution"); 00388 radius->callback(cb, v); 00389 resolution->callback(cb, v); 00390 Fl_Group::end(); 00391 } 00392 00393 const char *repcmd() { 00394 sprintf(cmdbuf, "VDW %f %f", radius->value(), resolution->value()); 00395 return cmdbuf; 00396 } 00397 void set_values(AtomRep *rep) { 00398 radius->value(rep->get_data(AtomRep::SPHERERAD)); 00399 resolution->value(rep->get_data(AtomRep::SPHERERES)); 00400 } 00401 00402 protected: 00403 void do_reset() { 00404 radius->value(1.0); 00405 resolution->value(12); 00406 } 00407 00408 protected: 00409 Fl_Counter *radius; 00410 Fl_Counter *resolution; 00411 }; 00412 00413 00415 class GraphicsFltkRepBeads : public GraphicsFltkRepVDW { 00416 public: 00417 GraphicsFltkRepBeads(Fl_Callback *cb, void *v) 00418 : GraphicsFltkRepVDW(cb, v) {} 00419 const char *repcmd() { 00420 sprintf(cmdbuf, "Beads %f %f", radius->value(), resolution->value()); 00421 return cmdbuf; 00422 } 00423 }; 00424 00425 00427 class GraphicsFltkRepDotted : public GraphicsFltkRepVDW { 00428 public: 00429 GraphicsFltkRepDotted(Fl_Callback *cb, void *v) 00430 : GraphicsFltkRepVDW(cb, v) {} 00431 const char *repcmd() { 00432 sprintf(cmdbuf, "Dotted %f %f", radius->value(), resolution->value()); 00433 return cmdbuf; 00434 } 00435 }; 00436 00437 00439 class GraphicsFltkRepTrace : public GraphicsFltkRepBonds { 00440 public: 00441 GraphicsFltkRepTrace(Fl_Callback *cb, void *v) 00442 : GraphicsFltkRepBonds(cb, v) {} 00443 const char *repcmd() { 00444 sprintf(cmdbuf, "Trace %f %f", radius->value(), resolution->value()); 00445 return cmdbuf; 00446 } 00447 }; 00448 00449 00451 class GraphicsFltkRepLicorice : public GraphicsFltkRepBonds { 00452 private: 00453 Fl_Counter *sresolution; 00454 public: 00455 GraphicsFltkRepLicorice(Fl_Callback *cb, void *v) 00456 : GraphicsFltkRepBonds(cb, v) { 00457 Fl_Group::begin(); 00458 sresolution= new ResolutionCounter(x()+170,y()+60,"Sphere Resolution"); 00459 sresolution->callback(cb, v); 00460 00461 Fl_Group::end(); 00462 } 00463 protected: 00464 void do_reset() { 00465 GraphicsFltkRepBonds::do_reset(); 00466 resolution->value(12); 00467 sresolution->value(12); 00468 } 00469 public: 00470 const char *repcmd() { 00471 sprintf(cmdbuf, "Licorice %f %f %f", radius->value(), sresolution->value(), 00472 resolution->value()); 00473 return cmdbuf; 00474 } 00475 void set_values(AtomRep *rep) { 00476 GraphicsFltkRepBonds::set_values(rep); 00477 sresolution->value(rep->get_data(AtomRep::SPHERERES)); 00478 } 00479 }; 00480 00481 00482 #ifdef VMDPOLYHEDRA 00483 00484 class GraphicsFltkRepPolyhedra : public GraphicsFltkRep { 00485 private: 00486 Fl_Counter *distance; 00487 public: 00488 GraphicsFltkRepPolyhedra(Fl_Callback *cb, void *v) { 00489 distance = new RadiusCounter(x()+170,y()+60,"Distance Cutoff"); 00490 distance->callback(cb, v); 00491 Fl_Group::end(); 00492 } 00493 protected: 00494 void do_reset() { 00495 distance->value(1.6); 00496 } 00497 public: 00498 const char *repcmd() { 00499 sprintf(cmdbuf, "Polyhedra %f", distance->value()); 00500 return cmdbuf; 00501 } 00502 void set_values(AtomRep *rep) { 00503 distance->value(rep->get_data(AtomRep::SPHERERAD)); 00504 } 00505 }; 00506 #endif 00507 00509 class GraphicsFltkRepTube : public GraphicsFltkRepBonds { 00510 public: 00511 GraphicsFltkRepTube(Fl_Callback *cb, void *v) 00512 : GraphicsFltkRepBonds(cb, v) { 00513 radius->label("Radius"); 00514 resolution->label("Resolution"); 00515 } 00516 const char *repcmd() { 00517 sprintf(cmdbuf, "Tube %f %f", radius->value(), resolution->value()); 00518 return cmdbuf; 00519 } 00520 }; 00521 00522 00524 class GraphicsFltkRepRibbons : public GraphicsFltkRepBonds { 00525 protected: 00526 Fl_Counter *thickness; 00527 public: 00528 GraphicsFltkRepRibbons(Fl_Callback *cb, void *v) 00529 : GraphicsFltkRepBonds(cb, v) { 00530 radius->label("Radius"); 00531 resolution->label("Resolution"); 00532 Fl_Group::begin(); 00533 thickness = new ResolutionCounter(x()+170,y()+60,"Width"); 00534 thickness->callback(cb, v); 00535 Fl_Group::end(); 00536 } 00537 protected: 00538 void do_reset() { 00539 GraphicsFltkRepBonds::do_reset(); 00540 thickness->value(2); 00541 } 00542 public: 00543 const char *repcmd() { 00544 sprintf(cmdbuf, "Ribbons %f %f %f", radius->value(), resolution->value(), 00545 thickness->value()); 00546 return cmdbuf; 00547 } 00548 void set_values(AtomRep *rep) { 00549 GraphicsFltkRepBonds::set_values(rep); 00550 thickness->value(rep->get_data(AtomRep::LINETHICKNESS)); 00551 } 00552 }; 00553 00554 00556 class GraphicsFltkRepNewRibbons : public GraphicsFltkRep { 00557 private: 00558 RepChoice *basis; 00559 IsoSlider *thickness, *ratio; 00560 ResolutionCounter *resolution; 00561 public: 00562 GraphicsFltkRepNewRibbons(Fl_Callback *cb, void *v) { 00563 00564 Fl_Group::begin(); 00565 thickness = new IsoSlider(x()+80, y()+90, "Thickness"); 00566 thickness->callback(cb, v); 00567 thickness->minimum(0.1); 00568 thickness->maximum(10.0); 00569 00570 resolution= new ResolutionCounter(x()+170,y()+120,"Resolution"); 00571 resolution->callback(cb, v); 00572 resolution->maximum(50.0); 00573 00574 ratio= new IsoSlider(x()+80, y()+60, "Aspect Ratio"); 00575 ratio->callback(cb, v); 00576 ratio->minimum(1.0); 00577 ratio->maximum(10.0); 00578 00579 basis = new RepChoice(x()+170,y()+30,"Spline Style"); 00580 basis->add("Catmull-Rom"); 00581 basis->add("B-Spline"); 00582 basis->callback(cb, v); 00583 Fl_Group::end(); 00584 } 00585 protected: 00586 void do_reset() { 00587 thickness->value(0.3); 00588 resolution->value(12); 00589 ratio->value(3); 00590 basis->value(0); 00591 } 00592 public: 00593 const char *repcmd() { 00594 sprintf(cmdbuf, "NewRibbons %f %f %f %d", thickness->value(), 00595 resolution->value(), ratio->value(), basis->value()); 00596 return cmdbuf; 00597 } 00598 void set_values(AtomRep *rep) { 00599 ratio->value(rep->get_data(AtomRep::LINETHICKNESS)); 00600 basis->value((int)rep->get_data(AtomRep::SPHERERAD)); 00601 thickness->value(rep->get_data(AtomRep::BONDRAD)); 00602 resolution->value(rep->get_data(AtomRep::BONDRES)); 00603 } 00604 }; 00605 00606 00608 class GraphicsFltkRepCartoon : public GraphicsFltkRepRibbons { 00609 public: 00610 GraphicsFltkRepCartoon(Fl_Callback *cb, void *v) 00611 : GraphicsFltkRepRibbons(cb, v) { 00612 radius->label("Helix/Coil Radius"); 00613 resolution->label("Helix/Coil Resolution"); 00614 thickness->label("Beta Sheet Thickness"); 00615 } 00616 const char *repcmd() { 00617 sprintf(cmdbuf, "Cartoon %f %f %f", radius->value(), resolution->value(), 00618 thickness->value()); 00619 return cmdbuf; 00620 } 00621 protected: 00622 void do_reset() { 00623 radius->value(2.1); 00624 resolution->value(24.0); 00625 thickness->value(5.0); 00626 } 00627 }; 00628 00629 00631 class GraphicsFltkRepNewCartoon : public GraphicsFltkRep { 00632 private: 00633 RepChoice *basis; 00634 IsoSlider *thickness, *ratio; 00635 ResolutionCounter *resolution; 00636 public: 00637 GraphicsFltkRepNewCartoon(Fl_Callback *cb, void *v) { 00638 00639 Fl_Group::begin(); 00640 thickness = new IsoSlider(x()+80, y()+90, "Thickness"); 00641 thickness->callback(cb, v); 00642 thickness->minimum(0.1); 00643 thickness->maximum(10.0); 00644 00645 resolution= new ResolutionCounter(x()+170,y()+120,"Resolution"); 00646 resolution->callback(cb, v); 00647 resolution->maximum(50.0); 00648 00649 ratio= new IsoSlider(x()+80, y()+60, "Aspect Ratio"); 00650 ratio->callback(cb, v); 00651 ratio->minimum(1.0); 00652 ratio->maximum(10.0); 00653 00654 basis = new RepChoice(x()+170,y()+30,"Spline Style"); 00655 basis->add("Catmull-Rom"); 00656 basis->add("B-Spline"); 00657 basis->callback(cb, v); 00658 Fl_Group::end(); 00659 } 00660 protected: 00661 void do_reset() { 00662 thickness->value(0.3); 00663 resolution->value(10); 00664 ratio->value(4.1); 00665 basis->value(0); 00666 } 00667 public: 00668 const char *repcmd() { 00669 sprintf(cmdbuf, "NewCartoon %f %f %f %d", thickness->value(), 00670 resolution->value(), ratio->value(), basis->value()); 00671 return cmdbuf; 00672 } 00673 void set_values(AtomRep *rep) { 00674 ratio->value(rep->get_data(AtomRep::LINETHICKNESS)); 00675 basis->value((int)rep->get_data(AtomRep::SPHERERAD)); 00676 thickness->value(rep->get_data(AtomRep::BONDRAD)); 00677 resolution->value(rep->get_data(AtomRep::BONDRES)); 00678 } 00679 }; 00680 00681 #ifdef VMDWITHCARBS 00682 00684 class GraphicsFltkRepWithRingSize : public GraphicsFltkRep { 00685 protected: 00686 ResolutionCounter *max_ring_size; 00687 Fl_Callback *parentcb; 00688 void *parentdata; 00689 00690 static void sync_cb(Fl_Widget *, void *v) { 00691 GraphicsFltkRepWithRingSize *self = (GraphicsFltkRepWithRingSize *)v; 00692 GraphicsFltkMenu *menu = (GraphicsFltkMenu *) self->parentdata; 00693 00694 int max_ring_size = (int)self->max_ring_size->value(); 00695 00696 Molecule *m = menu->app->moleculeList->molecule(menu->molindex); 00697 00698 for (int i=0; i<m->components(); i++) { 00699 DrawMolItem *d = m->component(i); 00700 AtomRep *ar = d->atomRep; 00701 00702 if (ar->method() == AtomRep::RINGS_PAPERCHAIN || ar->method() == AtomRep::RINGS_TWISTER) { 00703 GraphicsFltkRepWithRingSize *rep; 00704 00705 if (ar->method() == AtomRep::RINGS_PAPERCHAIN) 00706 rep = (GraphicsFltkRepWithRingSize *) menu->repcontrols.data("PaperChain"); 00707 else 00708 rep = (GraphicsFltkRepWithRingSize *) menu->repcontrols.data("Twister"); 00709 00710 rep->set_values(ar); 00711 rep->max_ring_size->value(max_ring_size); 00712 ar->change(rep->repcmd()); 00713 d->force_recalc(d->MOL_REGEN); 00714 } 00715 } 00716 00717 // Don't call parent since we've already updated ourselves. 00718 // (self->parentcb)(self->max_ring_size, self->parentdata); 00719 } 00720 }; 00721 00723 class GraphicsFltkRepPaperChain : public GraphicsFltkRepWithRingSize { 00724 private: 00725 ShortSlider *bipyramid_height; 00726 public: 00727 GraphicsFltkRepPaperChain(Fl_Callback *cb, void *v) { 00728 parentcb = cb; 00729 parentdata = v; 00730 00731 Fl_Group::begin(); 00732 00733 bipyramid_height = new ShortSlider(x()+120, y()+30, "Bipyramid Height"); 00734 bipyramid_height->callback(cb, v); 00735 bipyramid_height->minimum(0.1); 00736 bipyramid_height->maximum(10.0); 00737 00738 max_ring_size = new ResolutionCounter(x()+150, y()+60, "Max. Ring Size"); 00739 max_ring_size->callback(sync_cb,this); 00740 max_ring_size->minimum(2); 00741 max_ring_size->maximum(500); 00742 00743 Fl_Group::end(); 00744 } 00745 protected: 00746 void do_reset() { 00747 bipyramid_height->value(1.0); 00748 max_ring_size->value(10); 00749 } 00750 public: 00751 const char *repcmd() { 00752 sprintf(cmdbuf, "PaperChain %f %f", bipyramid_height->value(), 00753 max_ring_size->value()); 00754 return cmdbuf; 00755 } 00756 void set_values(AtomRep *rep) { 00757 bipyramid_height->value(rep->get_data(AtomRep::LINETHICKNESS)); 00758 max_ring_size->value((int)rep->get_data(AtomRep::ISOSTEPSIZE)); 00759 } 00760 }; 00761 00763 class GraphicsFltkRepTwister : public GraphicsFltkRepWithRingSize { 00764 private: 00765 RepChoice *start_end_centroid; 00766 RepChoice *hide_shared_links; 00767 ResolutionCounter *rib_steps; 00768 ShortSlider *rib_width; 00769 ShortSlider *rib_height; 00770 ResolutionCounter *max_path_length; 00771 00772 public: 00773 GraphicsFltkRepTwister(Fl_Callback *cb, void *v) { 00774 parentcb = cb; 00775 parentdata = v; 00776 00777 Fl_Group::begin(); 00778 00779 start_end_centroid = new RepChoice(x()+150, y()+30, "Start Ribbons At"); 00780 start_end_centroid->callback(cb,v); 00781 start_end_centroid->add("Ring Edge"); 00782 start_end_centroid->add("Ring Centroid"); 00783 00784 hide_shared_links = new RepChoice(x()+150, y()+60,"Hide Shared Links"); 00785 hide_shared_links->callback(cb,v); 00786 hide_shared_links->add("No"); 00787 hide_shared_links->add("Yes"); 00788 00789 rib_steps = new ResolutionCounter(x()+150, y()+90, "Steps in Ribbon"); 00790 rib_steps->callback(cb,v); 00791 rib_steps->minimum(5); 00792 rib_steps->maximum(500); 00793 00794 max_ring_size = new ResolutionCounter(x()+150, y()+120, "Max. Ring Size"); 00795 max_ring_size->callback(sync_cb,this); 00796 max_ring_size->minimum(2); 00797 max_ring_size->maximum(500); 00798 00799 max_path_length = new ResolutionCounter(x()+150, y()+150, "Max. Linking Distance"); 00800 max_path_length->callback(cb,v); 00801 max_path_length->minimum(1); 00802 max_path_length->maximum(500); 00803 00804 rib_width = new ShortSlider(x()+110, y()+180, "Ribbon Width"); 00805 rib_width->callback(cb,v); 00806 rib_width->minimum(0.01); 00807 rib_width->maximum(10.0); 00808 00809 rib_height = new ShortSlider(x()+110, y()+210, "Ribbon Height"); 00810 rib_height->callback(cb,v); 00811 rib_height->minimum(0.01); 00812 rib_height->maximum(10.0); 00813 00814 Fl_Group::end(); 00815 } 00816 protected: 00817 void do_reset() { 00818 start_end_centroid->value(1); 00819 hide_shared_links->value(0); 00820 rib_steps->value(10); 00821 rib_width->value(0.3); 00822 rib_height->value(0.05); 00823 max_ring_size->value(10); 00824 max_path_length->value(5); 00825 } 00826 public: 00827 const char *repcmd() { 00828 sprintf(cmdbuf, "Twister %f %f %f %f %f %f %f", (float) start_end_centroid->value(), 00829 (float) hide_shared_links->value(), 00830 (float) rib_steps->value(), 00831 rib_width->value(), rib_height->value(), 00832 max_ring_size->value(), max_path_length->value()); 00833 return cmdbuf; 00834 } 00835 void set_values(AtomRep *rep) { 00836 start_end_centroid->value((int)rep->get_data(AtomRep::LINETHICKNESS)); 00837 hide_shared_links->value((int)rep->get_data(AtomRep::BONDRES)); 00838 rib_steps->value((int)rep->get_data(AtomRep::SPHERERAD)); 00839 rib_width->value(rep->get_data(AtomRep::BONDRAD)); 00840 rib_height->value(rep->get_data(AtomRep::SPHERERES)); 00841 max_ring_size->value((int)rep->get_data(AtomRep::ISOSTEPSIZE)); 00842 max_path_length->value((int)rep->get_data(AtomRep::ISOLINETHICKNESS)); 00843 } 00844 }; 00845 00846 #endif 00847 00849 class GraphicsFltkRepSolvent : public GraphicsFltkRep { 00850 private: 00851 RepChoice *method; 00852 Fl_Counter *detail; 00853 Fl_Counter *probe; 00854 public: 00855 GraphicsFltkRepSolvent(Fl_Callback *cb, void *v) { 00856 method = new RepChoice(x()+170,y()+60,"Representation Method"); 00857 method->add("Points"); 00858 method->add("Crosses"); 00859 method->add("Mesh"); 00860 detail = new ResolutionCounter(x()+170,y()+90,"Detail Level"); 00861 detail->maximum(13); 00862 probe = new RadiusCounter(x()+170,y()+120,"Probe Radius"); 00863 method->callback(cb, v); 00864 detail->callback(cb, v); 00865 probe->callback(cb, v); 00866 Fl_Group::end(); 00867 } 00868 protected: 00869 void do_reset() { 00870 method->value(0); 00871 detail->value(7.0); 00872 probe->value(0); 00873 } 00874 public: 00875 const char *repcmd() { 00876 sprintf(cmdbuf, "Solvent %f %f %f", probe->value(), detail->value(), 00877 (float)(method->value()+1)); 00878 return cmdbuf; 00879 } 00880 void set_values(AtomRep *rep) { 00881 method->setvalue((int)rep->get_data(AtomRep::LINETHICKNESS)-1); 00882 detail->value(rep->get_data(AtomRep::SPHERERES)); 00883 probe->value(rep->get_data(AtomRep::SPHERERAD)); 00884 } 00885 }; 00886 00887 00889 class GraphicsFltkRepMSMS : public GraphicsFltkRep { 00890 private: 00891 Fl_Counter *density; 00892 Fl_Counter *probe; 00893 RepChoice *method; 00894 RepChoice *whichatoms; 00895 public: 00896 GraphicsFltkRepMSMS(Fl_Callback *cb, void *v) { 00897 density = new RadiusCounter(x()+170,y()+90,"Sample Density"); 00898 density->minimum(0.1); 00899 density->maximum(30.0); 00900 density->callback(cb, v); 00901 probe = new RadiusCounter(x()+170,y()+120, "Probe Radius"); 00902 probe->minimum(0.1); 00903 probe->maximum(8.0); 00904 probe->callback(cb, v); 00905 method = new RepChoice(x()+170,y()+60,"Representation Method"); 00906 method->add("Solid Surface"); 00907 method->add("Wireframe"); 00908 method->callback(cb, v); 00909 whichatoms = new RepChoice(x()+170,y()+30, "Which Atoms"); 00910 whichatoms->add("Selected"); 00911 whichatoms->add("All"); 00912 whichatoms->callback(cb, v); 00913 Fl_Group::end(); 00914 } 00915 protected: 00916 void do_reset() { 00917 density->value(1.5); 00918 probe->value(1.5); 00919 method->value(0); 00920 whichatoms->value(0); 00921 } 00922 public: 00923 const char *repcmd() { 00924 sprintf(cmdbuf, "MSMS %f %f %f %f", probe->value(), density->value(), 00925 (float)whichatoms->value(), (float)method->value()); 00926 return cmdbuf; 00927 } 00928 void set_values(AtomRep *rep) { 00929 density->value(rep->get_data(AtomRep::SPHERERES)); 00930 probe->value(rep->get_data(AtomRep::SPHERERAD)); 00931 method->setvalue((int)rep->get_data(AtomRep::BONDRES)); 00932 whichatoms->setvalue((int)rep->get_data(AtomRep::LINETHICKNESS)); 00933 } 00934 }; 00935 00936 00938 class GraphicsFltkRepNanoShaper : public GraphicsFltkRep { 00939 private: 00940 RepChoice *surftype; 00941 RepChoice *method; 00942 Fl_Counter *gspacing; 00943 Fl_Counter *probe; 00944 Fl_Counter *skin; 00945 Fl_Counter *blob; 00946 00947 public: 00948 GraphicsFltkRepNanoShaper(Fl_Callback *cb, void *v) { 00949 surftype = new RepChoice(x()+170,y()+30, "Surface Type"); 00950 surftype->add("SES"); 00951 surftype->add("Skin"); 00952 surftype->add("Blobby"); 00953 surftype->callback(cb, v); 00954 method = new RepChoice(x()+170,y()+60,"Representation Method"); 00955 method->add("Solid Surface"); 00956 method->add("Wireframe"); 00957 method->callback(cb, v); 00958 gspacing = new RadiusCounter(x()+170,y()+90,"Grid Spacing"); 00959 gspacing->minimum(0.1); 00960 gspacing->maximum(30.0); 00961 gspacing->callback(cb, v); 00962 00963 probe = new RadiusCounter(x()+170,y()+120, "SES Probe Radius"); 00964 probe->minimum(0.1); 00965 probe->maximum(8.0); 00966 probe->callback(cb, v); 00967 00968 skin = new RadiusCounter(x()+170,y()+150, "Skin Parameter"); 00969 skin->minimum(0.01); 00970 skin->maximum(0.99); 00971 skin->callback(cb, v); 00972 00973 blob = new RadiusCounter(x()+170,y()+180, "Blob Parameter"); 00974 blob->minimum(-5.0); 00975 blob->maximum(-0.5); 00976 blob->callback(cb, v); 00977 00978 Fl_Group::end(); 00979 } 00980 protected: 00981 void do_reset() { 00982 surftype->value(0); // SES 00983 method->value(0); 00984 gspacing->value(0.5); 00985 probe->value(1.4); 00986 probe->activate(); 00987 skin->value(0.45); 00988 skin->deactivate(); 00989 blob->value(-2.5); 00990 blob->deactivate(); 00991 } 00992 public: 00993 const char *repcmd() { 00994 sprintf(cmdbuf, "NanoShaper %f %f %f %f %f %f", 00995 (float)surftype->value(), (float)method->value(), 00996 gspacing->value(), probe->value(), skin->value(), blob->value()); 00997 return cmdbuf; 00998 } 00999 01000 void set_values(AtomRep *rep) { 01001 int sftype = int(rep->get_data(AtomRep::LINETHICKNESS)); 01002 surftype->setvalue(sftype); 01003 01004 method->setvalue((int)rep->get_data(AtomRep::BONDRES)); 01005 gspacing->value(rep->get_data(AtomRep::GRIDSPACING)); 01006 probe->value(rep->get_data(AtomRep::SPHERERAD)); 01007 skin->value(rep->get_data(AtomRep::SPHERERES)); 01008 blob->value(rep->get_data(AtomRep::BONDRAD)); 01009 01010 switch (sftype) { 01011 default: 01012 case 0: // SES 01013 probe->activate(); 01014 skin->deactivate(); 01015 blob->deactivate(); 01016 break; 01017 01018 case 1: // Skin 01019 probe->deactivate(); 01020 skin->activate(); 01021 blob->deactivate(); 01022 break; 01023 01024 case 2: // Blob 01025 probe->deactivate(); 01026 skin->deactivate(); 01027 blob->activate(); 01028 break; 01029 } 01030 } 01031 }; 01032 01033 01035 class GraphicsFltkRepHBonds : public GraphicsFltkRep { 01036 private: 01037 Fl_Counter *distance; 01038 Fl_Counter *angle; 01039 Fl_Counter *thickness; 01040 public: 01041 GraphicsFltkRepHBonds(Fl_Callback *cb, void *v) { 01042 distance = new RadiusCounter(x()+170,y()+60,"Distance Cutoff"); 01043 distance->callback(cb, v); 01044 angle = new RadiusCounter(x()+170,y()+90,"Angle Cutoff"); 01045 angle->precision(0); 01046 angle->step(1); 01047 angle->lstep(10); 01048 angle->callback(cb, v); 01049 thickness = new ResolutionCounter(x()+170,y()+120, "Line Thickness"); 01050 thickness->callback(cb, v); 01051 Fl_Group::end(); 01052 } 01053 protected: 01054 void do_reset() { 01055 distance->value(3.0); 01056 angle->value(20.0); 01057 thickness->value(1.0); 01058 } 01059 public: 01060 const char *repcmd() { 01061 sprintf(cmdbuf, "HBonds %f %f %f", distance->value(), angle->value(), 01062 thickness->value()); 01063 return cmdbuf; 01064 } 01065 void set_values(AtomRep *rep) { 01066 distance->value(rep->get_data(AtomRep::BONDRAD)); 01067 angle->value(rep->get_data(AtomRep::SPHERERAD)); 01068 thickness->value(rep->get_data(AtomRep::LINETHICKNESS)); 01069 } 01070 }; 01071 01072 01073 01074 // QuickSurf callback data structure containing multiple pointers 01075 class GraphicsFltkRepQuickSurf; 01076 01077 class quicksurf_cbdata { 01078 public: 01079 GraphicsFltkMenu *self; 01080 GraphicsFltkRepQuickSurf *qsurfrep; 01081 }; 01082 01084 class GraphicsFltkRepQuickSurf : public GraphicsFltkRep { 01085 private: 01086 Fl_Value_Slider *resolution; 01087 RepChoice *quality; 01088 Fl_Counter *radscale; 01089 Fl_Counter *gridspacing; 01090 Fl_Counter *isovalue; 01091 float gridspacingmult; 01092 01093 public: 01094 GraphicsFltkRepQuickSurf(Fl_Callback *cb, void *v) { 01095 gridspacingmult = 1.0f; 01096 resolution = new IsoSlider(x()+80, y()+60, "Resolution"); 01097 resolution->minimum(0.5); 01098 resolution->maximum(8); 01099 resolution->callback(cb, v); 01100 resolution->when(FL_WHEN_CHANGED | FL_WHEN_RELEASE_ALWAYS); 01101 radscale = new RadiusCounter(x()+170,y()+90,"Radius Scale"); 01102 radscale->minimum(0.1); 01103 radscale->callback(cb, v); 01104 isovalue = new RadiusCounter(x()+170,y()+120,"Density Isovalue"); 01105 isovalue->minimum(0.1); 01106 isovalue->maximum(20); 01107 isovalue->callback(cb, v); 01108 gridspacing = new RadiusCounter(x()+170,y()+150,"Grid Spacing"); 01109 gridspacing->minimum(0.5); 01110 gridspacing->callback(cb, v); 01111 quality = new RepChoice(x()+170,y()+180, "Surface Quality"); 01112 quality->add("Low"); 01113 quality->add("Medium"); 01114 quality->add("High"); 01115 quality->add("Max"); 01116 quality->callback(cb, v); 01117 Fl_Group::end(); 01118 } 01119 01120 void set_gridspacing_multiplier(float mult) { 01121 gridspacingmult = mult; 01122 } 01123 01124 void resolution_changed() { 01125 float val = (float) resolution->value(); 01126 float res = val; 01127 01128 int qual = quality->value(); 01129 switch (qual) { 01130 case 0: res *= 2.0f; break; 01131 01132 case 1: res *= 1.0f; break; 01133 01134 case 2: 01135 case 3: 01136 default: res /= 2.0f; break; 01137 } 01138 01139 float density = 0.5f; 01140 if (val > 3.0f) { 01141 density = 30.0f*(val-3.0f)+6.0f*powf((val-3.0f),2.0f)+10.0f*powf(val-3.0f,0.5f)+23.0f; 01142 } else if (val > 1) { 01143 density = 254.83f * expf(-1.018f * val) - 01144 5071.0f * powf(val, -0.0189f) + 4980.0f; 01145 } else { 01146 density = val; 01147 } 01148 01149 radscale->value(val); 01150 isovalue->value(density); 01151 gridspacing->value(res * gridspacingmult); 01152 } 01153 01154 protected: 01155 void do_reset() { 01156 resolution->value(1.0); 01157 radscale->value(1.0); 01158 gridspacing->value(1.0); 01159 isovalue->value(0.5); 01160 quality->value(1); 01161 } 01162 public: 01163 const char *repcmd() { 01164 sprintf(cmdbuf, "QuickSurf %f %f %f %f", 01165 radscale->value(), isovalue->value(), gridspacing->value(), 01166 (float)quality->value()); 01167 return cmdbuf; 01168 } 01169 void set_values(AtomRep *rep) { 01170 radscale->value(rep->get_data(AtomRep::SPHERERAD)); 01171 isovalue->value(rep->get_data(AtomRep::BONDRAD)); 01172 gridspacing->value(rep->get_data(AtomRep::GRIDSPACING)); 01173 quality->setvalue((int)rep->get_data(AtomRep::BONDRES)); 01174 } 01175 }; 01176 01177 01179 class GraphicsFltkRepSurf : public GraphicsFltkRep { 01180 private: 01181 Fl_Counter *probe; 01182 RepChoice *method; 01183 public: 01184 GraphicsFltkRepSurf(Fl_Callback *cb, void *v) { 01185 probe = new RadiusCounter(x()+170,y()+120,"Probe Radius"); 01186 probe->minimum(0.1); 01187 probe->callback(cb, v); 01188 method = new RepChoice(x()+170,y()+90, "Representation Method"); 01189 method->add("Solid Surface"); 01190 method->add("Wireframe"); 01191 method->callback(cb, v); 01192 Fl_Group::end(); 01193 } 01194 protected: 01195 void do_reset() { 01196 probe->value(1.4); 01197 method->value(0); 01198 } 01199 public: 01200 const char *repcmd() { 01201 sprintf(cmdbuf, "Surf %f %f", probe->value(), (float)method->value()); 01202 return cmdbuf; 01203 } 01204 void set_values(AtomRep *rep) { 01205 probe->value(rep->get_data(AtomRep::SPHERERAD)); 01206 method->setvalue((int)rep->get_data(AtomRep::BONDRES)); 01207 } 01208 }; 01209 01210 01215 class GraphicsFltkRepVolumetric: public GraphicsFltkRep { 01216 protected: 01217 RepChoice *dataset; 01218 01220 struct minmax { 01221 double minval, maxval; 01222 minmax(double themin=0, double themax=0) : minval(themin), maxval(themax) {} 01223 int operator==(const minmax &v) { 01224 return (minval == v.minval && maxval == v.maxval); 01225 } 01226 }; 01227 ResizeArray<minmax> minmaxlist; 01228 01229 GraphicsFltkRepVolumetric(Fl_Callback *cb, void *v) { 01230 dataset = new RepChoice(x()+170, y()+30, "Vol"); 01231 dataset->callback(cb, v); 01232 } 01233 virtual void do_dataset_clear() {} 01234 virtual void do_dataset_append(const char *, double, double) {} 01235 01236 public: 01237 int is_volumetric() { return 1; } 01238 void dataset_clear() { 01239 dataset->clear(); 01240 dataset->deactivate(); 01241 minmaxlist.clear(); 01242 do_dataset_clear(); 01243 } 01244 void dataset_append(const char *nm, double newmin, double newmax) { 01245 // Fltk doesn't allow adding a menu item with the same name as 01246 // an existing item, so we use replace, which also avoids 01247 // problems with the escape characters interpreted by add() 01248 int ind = dataset->add("foobar"); 01249 char *datalabel = new char[strlen(nm)+32]; 01250 sprintf(datalabel, "vol%d: %s", ind, nm); 01251 dataset->replace(ind, datalabel); 01252 delete[] datalabel; 01253 01254 minmaxlist.append(minmax(newmin, newmax)); 01255 dataset->value(int(minmaxlist.num())-1); 01256 do_dataset_append(nm, newmin, newmax); 01257 dataset->activate(); 01258 } 01259 }; 01260 01261 01262 01263 // isosurface callback data structure containing multiple pointers 01264 class GraphicsFltkRepIsosurface; 01265 01266 class isosurface_cbdata { 01267 public: 01268 GraphicsFltkMenu *self; 01269 GraphicsFltkRepIsosurface *isorep; 01270 }; 01271 01273 class GraphicsFltkRepIsosurface : public GraphicsFltkRepVolumetric { 01274 private: 01275 Fl_Slider *isovalue; 01276 Fl_Float_Input *isoinput; 01277 Fl_Float_Input *isomininput, *isomaxinput; 01278 Fl_Counter *resolution; 01279 Fl_Counter *thickness; 01280 RepChoice *method; 01281 RepChoice *boundary; 01282 Fl_Callback *parentcb; 01283 void *parentdata; 01284 int gridstepsize; 01285 01286 static void datasetchanged_cb(Fl_Widget *w, void *v) { 01287 GraphicsFltkRepIsosurface *self = (GraphicsFltkRepIsosurface *)v; 01288 if (self->minmaxlist.num() > 0) { 01289 minmax &m = self->minmaxlist[self->dataset->value()]; 01290 self->isovalue->range(m.minval, m.maxval); 01291 } else { 01292 self->isovalue->range(0, 1); 01293 } 01294 (self->parentcb)(w, self->parentdata); 01295 } 01296 01297 static void inputcb(Fl_Widget *, void *v) { 01298 GraphicsFltkRepIsosurface *self = (GraphicsFltkRepIsosurface *)v; 01299 char *endptr = NULL; 01300 const char *strval = self->isoinput->value(); 01301 double val = strtod(strval, &endptr); 01302 if (endptr != strval) { 01303 // valid conversion performed 01304 self->isovalue->value(val); 01305 (self->parentcb)(self->isovalue, self->parentdata); 01306 } 01307 } 01308 01309 static void minmaxinputcb(Fl_Widget *, void *v) { 01310 GraphicsFltkRepIsosurface *self = (GraphicsFltkRepIsosurface *)v; 01311 // parse values in input fields 01312 char *endptr = NULL; 01313 const char *minstrval = self->isomininput->value(); 01314 double minval = strtod(minstrval, &endptr); 01315 if (endptr == minstrval) return; // invalid 01316 const char *maxstrval = self->isomaxinput->value(); 01317 double maxval = strtod(maxstrval, &endptr); 01318 if (endptr == maxstrval) return; // invalid 01319 01320 // fields are valid; update cached minmax 01321 if (self->minmaxlist.num() > 0) { 01322 minmax &m = self->minmaxlist[self->dataset->value()]; 01323 m.minval = minval; 01324 m.maxval = maxval; 01325 } 01326 01327 // update the slider itself. If we made the value change, trigger 01328 // appropriate callbacks. 01329 self->isovalue->range(minval, maxval); 01330 if (self->isovalue->value() < minval) { 01331 self->isovalue->value(minval); 01332 slidercb(NULL, v); 01333 } else if (self->isovalue->value() > maxval) { 01334 self->isovalue->value(maxval); 01335 slidercb(NULL, v); 01336 } else { 01337 self->setInputFromSlider(); 01338 } 01339 } 01340 01341 void setInputFromSlider() { 01342 char buf[128] = { 0 }; 01343 sprintf(buf, "%8g", (float)isovalue->value()); 01344 isoinput->value(buf); 01345 sprintf(buf, "%8g", (float)isovalue->minimum()); 01346 isomininput->value(buf); 01347 sprintf(buf, "%8g", (float)isovalue->maximum()); 01348 isomaxinput->value(buf); 01349 } 01350 01351 static void slidercb(Fl_Widget *, void *v) { 01352 GraphicsFltkRepIsosurface *self = (GraphicsFltkRepIsosurface *)v; 01353 self->setInputFromSlider(); 01354 (self->parentcb)(self->isovalue, self->parentdata); 01355 } 01356 01357 protected: 01358 void do_dataset_clear() { 01359 isovalue->deactivate(); 01360 isoinput->deactivate(); 01361 boundary->deactivate(); 01362 method->deactivate(); 01363 resolution->deactivate(); 01364 thickness->deactivate(); 01365 } 01366 void do_dataset_append(const char *, double min, double max) { 01367 isovalue->activate(); 01368 isoinput->activate(); 01369 boundary->activate(); 01370 method->activate(); 01371 resolution->activate(); 01372 thickness->activate(); 01373 isovalue->range(min,max); 01374 setInputFromSlider(); 01375 } 01376 void do_reset() { 01377 set_grid_stepsize(1); 01378 resolution->value(1); 01379 thickness->value(1); 01380 method->value(2); 01381 boundary->value(2); 01382 dataset->value(0); 01383 } 01384 01385 public: 01386 GraphicsFltkRepIsosurface(Fl_Callback *cb, void *v) 01387 : GraphicsFltkRepVolumetric(datasetchanged_cb, this) { 01388 parentcb = cb; 01389 parentdata = v; 01390 01391 resolution= new StepCounter(x()+35,y()+90, "Step"); 01392 resolution->callback(cb, v); 01393 thickness= new StepCounter(x()+35,y()+120, "Size"); 01394 thickness->callback(cb, v); 01395 method = new RepChoice(x()+170,y()+90,"Draw"); 01396 method->add("Solid Surface"); 01397 method->add("Wireframe"); 01398 method->add("Points"); 01399 method->add("Shaded Points"); 01400 method->callback(cb, v); 01401 boundary = new RepChoice(x()+170, y()+120, "Show"); 01402 boundary->add("Isosurface"); 01403 boundary->add("Box"); 01404 boundary->add("Box+Isosurface"); 01405 boundary->callback(cb, v); 01406 isovalue = new Fl_Slider(x()+135,y()+60, 155, CTRHEIGHT, ""); 01407 isovalue->type(FL_HOR_SLIDER); 01408 isovalue->color(VMDMENU_SLIDER_BG); 01409 isovalue->when(FL_WHEN_CHANGED); 01410 isovalue->callback(slidercb, this); 01411 isoinput = new Fl_Float_Input(x()+60, y()+60, 70, CTRHEIGHT, "Isovalue"); 01412 isoinput->when(FL_WHEN_ENTER_KEY); 01413 isoinput->selection_color(VMDMENU_VALUE_SEL); 01414 isoinput->callback(inputcb, this); 01415 isovalue->when(FL_WHEN_CHANGED | FL_WHEN_RELEASE_ALWAYS); 01416 01417 isomininput = new Fl_Float_Input(x()+45, y()+30, 45, CTRHEIGHT, "Range"); 01418 isomininput->when(FL_WHEN_ENTER_KEY); 01419 isomininput->selection_color(VMDMENU_VALUE_SEL); 01420 isomininput->callback(minmaxinputcb, this); 01421 isomaxinput = new Fl_Float_Input(x()+90, y()+30, 45, CTRHEIGHT); 01422 isomaxinput->when(FL_WHEN_ENTER_KEY); 01423 isomaxinput->selection_color(VMDMENU_VALUE_SEL); 01424 isomaxinput->callback(minmaxinputcb, this); 01425 01426 Fl_Group::end(); 01427 } 01428 const char *repcmd() { 01429 if (dataset->size() > 0) { 01430 sprintf(cmdbuf, "Isosurface %f %d %d %d %d %d", 01431 (float) isovalue->value(), 01432 (int) dataset->value(), 01433 (int) boundary->value(), 01434 (int) method->value(), 01435 gridstepsize + (int) resolution->value() - 1, 01436 (int) thickness->value()); 01437 } else { 01438 sprintf(cmdbuf, "Isosurface"); 01439 } 01440 return cmdbuf; 01441 } 01442 void set_values(AtomRep *rep) { 01443 dataset->setvalue((int)rep->get_data(AtomRep::SPHERERES)); 01444 // minmax needs to update whenever dataset is changed or 01445 // the selected rep is switched 01446 if (minmaxlist.num() > 0) { 01447 minmax &m = minmaxlist[dataset->value()]; 01448 isovalue->range(m.minval, m.maxval); 01449 } else { 01450 isovalue->range(0, 1); 01451 } 01452 isovalue->value(rep->get_data(AtomRep::SPHERERAD)); 01453 method->setvalue((int)rep->get_data(AtomRep::BONDRES)); 01454 boundary->setvalue((int)rep->get_data(AtomRep::LINETHICKNESS)); 01455 resolution->value(rep->get_data(AtomRep::ISOSTEPSIZE) - gridstepsize + 1); 01456 thickness->value(rep->get_data(AtomRep::ISOLINETHICKNESS)); 01457 setInputFromSlider(); 01458 } 01459 void set_grid_stepsize(int step) { 01460 gridstepsize = step; 01461 } 01462 }; 01463 01464 01466 class GraphicsFltkRepVolumeSlice : public GraphicsFltkRepVolumetric { 01467 private: 01468 Fl_Value_Slider *slice; 01469 RepChoice *axis; 01470 RepChoice *quality; // texture filtering mode 01471 01472 protected: 01473 void do_dataset_clear() { 01474 slice->deactivate(); 01475 axis->deactivate(); 01476 quality->deactivate(); 01477 } 01478 void do_dataset_append(const char *, double, double) { 01479 slice->activate(); 01480 axis->activate(); 01481 quality->activate(); 01482 } 01483 void do_reset() { 01484 slice->value(0.5); 01485 axis->value(0); 01486 quality->value(2); 01487 } 01488 public: 01489 GraphicsFltkRepVolumeSlice(Fl_Callback *cb, void *v) 01490 : GraphicsFltkRepVolumetric(cb, v) { 01491 slice = new IsoSlider(x()+80, y()+60, "Slice Offset"); 01492 slice->callback(cb, v); 01493 axis = new RepChoice(x()+170, y()+90, "Slice Axis"); 01494 axis->add("X"); 01495 axis->add("Y"); 01496 axis->add("Z"); 01497 axis->callback(cb, v); 01498 quality = new RepChoice(x()+170,y()+120, "Render Quality"); 01499 quality->add("Low"); 01500 quality->add("Medium"); 01501 quality->add("High"); 01502 quality->callback(cb, v); 01503 Fl_Group::end(); 01504 } 01505 const char *repcmd() { 01506 if (dataset->size() > 0) { 01507 sprintf(cmdbuf, "VolumeSlice %f %f %f %f", slice->value(), 01508 (float)dataset->value(), (float)axis->value(), 01509 (float)quality->value()); 01510 } else { 01511 sprintf(cmdbuf, "VolumeSlice"); 01512 } 01513 return cmdbuf; 01514 } 01515 void set_values(AtomRep *rep) { 01516 dataset->setvalue((int)rep->get_data(AtomRep::SPHERERES)); 01517 slice->value(rep->get_data(AtomRep::SPHERERAD)); 01518 axis->setvalue((int)rep->get_data(AtomRep::LINETHICKNESS)); 01519 quality->setvalue((int)rep->get_data(AtomRep::BONDRES)); 01520 } 01521 }; 01522 01523 01524 01525 // orbital callback data structure containing multiple pointers 01526 class GraphicsFltkRepOrbital; 01527 01528 class orbital_cbdata { 01529 public: 01530 GraphicsFltkMenu *self; 01531 GraphicsFltkRepOrbital *orbrep; 01532 }; 01533 01534 01536 class GraphicsFltkRepOrbital : public GraphicsFltkRep { 01537 protected: 01538 RepChoice *wavefnctype; 01539 RepChoiceSmall *wavefncspin; 01540 RepChoiceSmall *wavefncexcitation; 01541 RepChoiceSmall *orbitalindex; 01542 01544 struct minmax { 01545 double minval, maxval; 01546 minmax(double themin=0, double themax=0) : minval(themin), maxval(themax) {} 01547 int operator==(const minmax &v) { 01548 return (minval == v.minval && maxval == v.maxval); 01549 } 01550 }; 01551 ResizeArray<minmax> minmaxlist; 01552 01553 01554 public: 01555 int is_orbital() { return 1; } 01556 void dataset_clear() { 01557 orbitalindex->clear(); 01558 orbitalindex->deactivate(); 01559 minmaxlist.clear(); 01560 do_dataset_clear(); 01561 } 01562 void dataset_append(const char *nm, double newmin, double newmax) { 01563 // Fltk doesn't allow adding a menu item with the same name as 01564 // an existing item, so we use replace, which also avoids 01565 // problems with the escape characters interpreted by add() 01566 int ind = orbitalindex->add("foobar"); 01567 char *datalabel = new char[strlen(nm)+32]; 01568 sprintf(datalabel, "%s", nm); 01569 orbitalindex->replace(ind, datalabel); 01570 delete[] datalabel; 01571 01572 minmaxlist.append(minmax(newmin, newmax)); 01573 orbitalindex->value(int(minmaxlist.num())-1); 01574 do_dataset_append(nm, newmin, newmax); 01575 orbitalindex->activate(); 01576 } 01577 01578 void regen_wavefunctypes() { 01579 int i; 01580 orbital_cbdata *cbdata = (orbital_cbdata *) parentdata; 01581 GraphicsFltkMenu *menu = (GraphicsFltkMenu *) cbdata->self; 01582 Molecule *m = menu->app->moleculeList->molecule(menu->molindex); 01583 int firstvalidwaveftype=-1; 01584 int firstvalidwavefspin=-1; 01585 01586 if (m != NULL && m->qm_data != NULL) { 01587 // loop over wavefunction types and enable/disable them 01588 // based on their availability for the current molecule. 01589 for (i=0; i<7; i++) { 01590 if (m->qm_data->has_wavef_guitype(i)) { 01591 wavefnctype->mode(i, 0); // activate choice 01592 if (firstvalidwaveftype < 0) 01593 firstvalidwaveftype=i; // record first valid type 01594 } else { 01595 wavefnctype->mode(i, FL_MENU_INACTIVE); // deactivate choice 01596 } 01597 } 01598 01599 // loop over wavefunction spins and enable/disable them 01600 // based on their availability for the current molecule. 01601 for (i=0; i<2; i++) { 01602 if (m->qm_data->has_wavef_spin(i)) { 01603 wavefncspin->mode(i, 0); 01604 if (firstvalidwavefspin < 0) 01605 firstvalidwavefspin=i; // record first valid spin 01606 } else { 01607 wavefncspin->mode(i, FL_MENU_INACTIVE); 01608 } 01609 } 01610 } else { 01611 // no qm data or no molecule, so all types/spins disabled 01612 for (i=0; i<7; i++) 01613 wavefnctype->mode(i, FL_MENU_INACTIVE); 01614 for (i=0; i<2; i++) 01615 wavefncspin->mode(i, FL_MENU_INACTIVE); 01616 } 01617 01618 // automatically set the wavefunction type control to the first valid type 01619 if (firstvalidwaveftype >= 0) 01620 wavefnctype->value(firstvalidwaveftype); 01621 01622 // automatically set the wavefunction spin control to the first valid spin 01623 if (firstvalidwavefspin >= 0) 01624 wavefncspin->value(firstvalidwavefspin); 01625 01626 // regenerate the excitation chooser as well 01627 regen_excitationlist(); 01628 } 01629 01630 void regen_excitationlist() { 01631 orbital_cbdata *cbdata = (orbital_cbdata *) parentdata; 01632 GraphicsFltkMenu *menu = (GraphicsFltkMenu *) cbdata->self; 01633 Molecule *m = menu->app->moleculeList->molecule(menu->molindex); 01634 01635 int wftype = (int) wavefnctype->value(); 01636 if (m != NULL && m->qm_data != NULL && 01637 m->qm_data->has_wavef_guitype(wftype)) { 01638 int maxexcitations = m->qm_data->get_highest_excitation(wftype); 01639 wavefncexcitation->clear(); 01640 wavefncexcitation->deactivate(); 01641 01642 // regenerate the contents of the excitation chooser based 01643 // on the currently selected wavefunction type 01644 int i; 01645 for (i=0; i<=maxexcitations; i++) { 01646 char excitationstr[64]; 01647 sprintf(excitationstr, "%d", i); 01648 wavefncexcitation->add(excitationstr); 01649 } 01650 01651 // toggle excitations active/inactive in the GUI 01652 int firstvalidexcitation=-1; 01653 for (i=0; i<=maxexcitations; i++) { 01654 if (m->qm_data->find_wavef_id_from_gui_specs(wftype, GUI_WAVEF_SPIN_ALPHA, i)>=0 || 01655 m->qm_data->find_wavef_id_from_gui_specs(wftype, GUI_WAVEF_SPIN_BETA, i)>=0) { 01656 // record the first valid excitation for this wavefunction type 01657 if (firstvalidexcitation < 0) 01658 firstvalidexcitation=i; 01659 wavefncexcitation->mode(i, 0); // enable in the GUI 01660 } else { 01661 wavefncexcitation->mode(i, FL_MENU_INACTIVE); // disable in the GUI 01662 } 01663 } 01664 01665 // automatically set the excitation control to the first valid 01666 // excitation we find (if any) 01667 if (firstvalidexcitation >= 0) 01668 wavefncexcitation->value(firstvalidexcitation); 01669 wavefncexcitation->activate(); 01670 } 01671 } 01672 01673 void regen_orbitallist(int orblistcenter=10) { 01674 dataset_clear(); 01675 orbital_cbdata *cbdata = (orbital_cbdata *) parentdata; 01676 GraphicsFltkMenu *menu = (GraphicsFltkMenu *) cbdata->self; 01677 Molecule *m = menu->app->moleculeList->molecule(menu->molindex); 01678 if (m != NULL && m->qm_data != NULL) { 01679 char namestr[80]; 01680 01681 int waveid = 0; 01682 int wftype = (int) wavefnctype->value(); 01683 int wfspin = (int) wavefncspin->value(); 01684 int wfexcitation = (int) wavefncexcitation->value(); 01685 01686 // convert GUI selections of wavefunction type, spin, and excitation 01687 // into the correct internal wavefunction ID tag 01688 waveid = m->qm_data->find_wavef_id_from_gui_specs(wftype, wfspin, wfexcitation); 01689 01690 if (waveid < 0) { 01691 orbitalindex->activate(); 01692 return; 01693 } 01694 01695 // get 1-based maximum orbital index 01696 int molmaxorb = m->qm_data->get_max_avail_orbitals(waveid); 01697 01698 // set maximum orbital list center value for selected wavefunction 01699 // (1-based index) 01700 orbitallistcounter->maximum(molmaxorb); 01701 01702 // check for orblistcenter for -1, and read from orbitallistcounter 01703 if (orblistcenter == -1) 01704 orblistcenter = (int) orbitallistcounter->value(); 01705 else 01706 orbitallistcounter->value(orblistcenter); 01707 01708 // clamp orblistcenter close to valid range 01709 if (orblistcenter > (molmaxorb-10)) 01710 orblistcenter = molmaxorb-10; 01711 if (orblistcenter < 10) 01712 orblistcenter = 10; 01713 01714 int maxorb = orblistcenter+10; 01715 int minorb = orblistcenter-10; 01716 01717 // clamp range of orbital list precisely 01718 if (minorb < 1) 01719 minorb=1; 01720 if (maxorb > molmaxorb) 01721 maxorb=molmaxorb; 01722 01723 // set class minimum chooser index info 01724 orbitalminindex = minorb - 1; // use 0-based indexing here 01725 01726 #if 0 01727 // XXX not ready for prime time yet. 01728 // query the HOMO for the zeroth timestep and use it when listing 01729 // the orbitals, as the current implementation doesn't sort the 01730 // orbitals differently for different timesteps, so the HOMO index 01731 // for timestep zero will also be correct for the others. 01732 int HOMO = -1; // init with sentinel so it's only listed if we've got it 01733 Timestep *ts = m->get_frame(0); // timestep zero 01734 if (ts != NULL && ts->qm_timestep != NULL && 01735 ts->qm_timestep->get_num_wavef()) { 01736 int tmp = ts->qm_timestep->get_homo(waveid); 01737 HOMO = ts->qm_timestep->get_orbital_id_from_index(waveid, tmp); 01738 printf("HOMO: %d\n", HOMO); 01739 } else { 01740 printf("HOMO not set: %d\n", HOMO); 01741 } 01742 #endif 01743 01744 // regenerate list of orbitals (1-based) 01745 // returned GUI indices are 0-based 01746 int j; 01747 for (j=minorb; j<=maxorb; j++) { 01748 #if 1 01749 sprintf(namestr, "%3d", j); 01750 #else 01751 if (HOMO == j) 01752 sprintf(namestr, "%3d (HOMO)", j); // tag HOMO specially 01753 else 01754 sprintf(namestr, "%3d", j); // others currently just list their ID 01755 #endif 01756 01757 dataset_append(namestr, -0.1, 0.1); 01758 } 01759 for (j=minorb; j<=maxorb; j++) { 01760 // check whether this orbital exists or not 01761 // GUI indices are 0-based 01762 if (m->qm_data->has_orbital(waveid, j)) 01763 orbitalindex->mode(j-1, 0); // enable in the GUI 01764 else 01765 orbitalindex->mode(j-1, FL_MENU_INACTIVE); // disable in the GUI 01766 } 01767 01768 orbitalindex->value(0); 01769 orbitalindex->activate(); 01770 } else { 01771 orbitalindex->value(0); 01772 orbitalindex->activate(); 01773 } 01774 } 01775 01776 01777 private: 01778 Fl_Slider *isovalue; 01779 Fl_Float_Input *isoinput; 01780 Fl_Float_Input *isomininput, *isomaxinput; 01781 Fl_Counter *resolution; 01782 Fl_Counter *thickness; 01783 RepChoice *method; 01784 Fl_Callback *parentcb; 01785 void *parentdata; 01786 RepChoice *boundary; 01787 int gridstepsize; 01788 Fl_Counter *orbitallistcounter; 01789 int orbitalminindex; 01790 01791 static void datasetchanged_cb(Fl_Widget *w, void *v) { 01792 GraphicsFltkRepOrbital *self = (GraphicsFltkRepOrbital *)v; 01793 if (self->minmaxlist.num() > 0) { 01794 minmax &m = self->minmaxlist[self->orbitalindex->value()]; 01795 self->isovalue->range(m.minval, m.maxval); 01796 } else { 01797 self->isovalue->range(0, 1); 01798 } 01799 (self->parentcb)(w, self->parentdata); 01800 } 01801 01802 static void inputcb(Fl_Widget *, void *v) { 01803 GraphicsFltkRepOrbital *self = (GraphicsFltkRepOrbital *)v; 01804 char *endptr = NULL; 01805 const char *strval = self->isoinput->value(); 01806 double val = strtod(strval, &endptr); 01807 if (endptr != strval) { 01808 // valid conversion performed 01809 self->isovalue->value(val); 01810 (self->parentcb)(self->isovalue, self->parentdata); 01811 } 01812 } 01813 01814 static void minmaxinputcb(Fl_Widget *, void *v) { 01815 GraphicsFltkRepOrbital *self = (GraphicsFltkRepOrbital *)v; 01816 // parse values in input fields 01817 char *endptr = NULL; 01818 const char *minstrval = self->isomininput->value(); 01819 double minval = strtod(minstrval, &endptr); 01820 if (endptr == minstrval) return; // invalid 01821 const char *maxstrval = self->isomaxinput->value(); 01822 double maxval = strtod(maxstrval, &endptr); 01823 if (endptr == maxstrval) return; // invalid 01824 01825 // fields are valid; update cached minmax 01826 if (self->minmaxlist.num() > 0) { 01827 minmax &m = self->minmaxlist[self->orbitalindex->value()]; 01828 m.minval = minval; 01829 m.maxval = maxval; 01830 } 01831 01832 // update the slider itself. If we made the value change, trigger 01833 // appropriate callbacks. 01834 self->isovalue->range(minval, maxval); 01835 if (self->isovalue->value() < minval) { 01836 self->isovalue->value(minval); 01837 slidercb(NULL, v); 01838 } else if (self->isovalue->value() > maxval) { 01839 self->isovalue->value(maxval); 01840 slidercb(NULL, v); 01841 } else { 01842 self->setInputFromSlider(); 01843 } 01844 } 01845 01846 void setInputFromSlider() { 01847 char buf[128] = { 0 }; 01848 sprintf(buf, "%8g", (float)isovalue->value()); 01849 isoinput->value(buf); 01850 sprintf(buf, "%8g", (float)isovalue->minimum()); 01851 isomininput->value(buf); 01852 sprintf(buf, "%8g", (float)isovalue->maximum()); 01853 isomaxinput->value(buf); 01854 } 01855 01856 static void slidercb(Fl_Widget *, void *v) { 01857 GraphicsFltkRepOrbital *self = (GraphicsFltkRepOrbital *)v; 01858 self->setInputFromSlider(); 01859 (self->parentcb)(self->isovalue, self->parentdata); 01860 } 01861 01862 protected: 01863 void do_dataset_clear() { 01864 isovalue->deactivate(); 01865 isoinput->deactivate(); 01866 boundary->deactivate(); 01867 method->deactivate(); 01868 resolution->deactivate(); 01869 thickness->deactivate(); 01870 orbitallistcounter->deactivate(); 01871 } 01872 void do_dataset_append(const char *, double min, double max) { 01873 isovalue->activate(); 01874 isoinput->activate(); 01875 boundary->activate(); 01876 method->activate(); 01877 resolution->activate(); 01878 thickness->activate(); 01879 orbitallistcounter->activate(); 01880 isovalue->range(min,max); 01881 setInputFromSlider(); 01882 } 01883 void do_reset() { 01884 set_grid_stepsize(1); 01885 resolution->value(0.075); 01886 thickness->value(1); 01887 orbitallistcounter->minimum(1); 01888 orbitallistcounter->value(10); 01889 orbitallistcounter->step(10); 01890 orbitallistcounter->lstep(50); 01891 method->value(0); 01892 boundary->value(0); 01893 wavefnctype->value(0); 01894 wavefncspin->value(0); 01895 wavefncexcitation->value(0); 01896 orbitalindex->value(0); 01897 isovalue->value(0.05); 01898 01899 // regenerate GUI selectors 01900 regen_wavefunctypes(); 01901 regen_orbitallist(); 01902 } 01903 01904 public: 01905 GraphicsFltkRepOrbital(Fl_Callback *cb, void *v) { 01906 parentcb = cb; 01907 parentdata = v; 01908 gridstepsize = 1; 01909 orbitalminindex = 0; 01910 01911 int gx = x(); 01912 int gy = y(); 01913 01914 // The order of wavefunction type indexes is hard-coded and cannot 01915 // be changed safely without introducing extra mapping logic 01916 wavefnctype = new RepChoice(gx+170, gy+30, "Wavefunction Type"); 01917 wavefnctype->add("Canonical"); 01918 wavefnctype->add("GVB geminal pairs"); 01919 wavefnctype->add("MCSCF natural"); 01920 wavefnctype->add("MCSCF optimized"); 01921 wavefnctype->add("CI natural"); 01922 wavefnctype->add("Localized"); 01923 wavefnctype->add("Other"); 01924 wavefnctype->callback(cb, v); 01925 01926 wavefncspin = new RepChoiceSmall(gx+65, gy+60, "Spin"); 01927 wavefncspin->add("Alpha"); 01928 wavefncspin->add("Beta"); 01929 wavefncspin->callback(cb, v); 01930 01931 wavefncexcitation = new RepChoiceSmall(gx+65, gy+90, "Excitation"); 01932 int i; 01933 for (i=0; i<11; i++) { 01934 char excitationstr[64]; 01935 sprintf(excitationstr, "%d", i); 01936 wavefncexcitation->add(excitationstr); 01937 } 01938 wavefncexcitation->callback(cb, v); 01939 01940 gy+=60; 01941 01942 orbitallistcounter= new StepCounter(gx+200,gy, "OrbList"); 01943 orbitallistcounter->callback(cb, v); 01944 orbitalindex = new RepChoiceSmall(gx+210, gy+30, "Orbital"); 01945 orbitalindex->callback(cb, v); 01946 01947 resolution= new GridResCounter(gx+170,gy+150, "Grid Spacing"); 01948 resolution->callback(cb, v); 01949 thickness= new StepCounter(gx+40,gy+120, "Size"); 01950 thickness->callback(cb, v); 01951 method = new RepChoice(gx+170,gy+90,"Draw"); 01952 method->add("Solid Surface"); 01953 method->add("Wireframe"); 01954 method->add("Points"); 01955 method->add("Shaded Points"); 01956 method->callback(cb, v); 01957 boundary = new RepChoice(gx+170, gy+120, "Show"); 01958 boundary->add("Isosurface"); 01959 boundary->add("Box"); 01960 boundary->add("Box+Isosurface"); 01961 boundary->callback(cb, v); 01962 isovalue = new Fl_Slider(gx+150,gy+60, 140, CTRHEIGHT, ""); 01963 isovalue->type(FL_HOR_SLIDER); 01964 isovalue->color(VMDMENU_SLIDER_BG); 01965 isovalue->when(FL_WHEN_CHANGED); 01966 isovalue->callback(slidercb, this); 01967 isoinput = new Fl_Float_Input(gx+80, gy+60, 70, CTRHEIGHT, "Isovalue"); 01968 isoinput->when(FL_WHEN_ENTER_KEY); 01969 isoinput->selection_color(VMDMENU_SLIDER_SEL); 01970 isoinput->callback(inputcb, this); 01971 isovalue->when(FL_WHEN_CHANGED | FL_WHEN_RELEASE_ALWAYS); 01972 01973 isomininput = new Fl_Float_Input(gx+40, gy+90, 45, CTRHEIGHT, "Range"); 01974 isomininput->when(FL_WHEN_ENTER_KEY); 01975 isomininput->selection_color(VMDMENU_VALUE_SEL); 01976 isomininput->callback(minmaxinputcb, this); 01977 isomaxinput = new Fl_Float_Input(gx+85, gy+90, 45, CTRHEIGHT); 01978 isomaxinput->when(FL_WHEN_ENTER_KEY); 01979 isomaxinput->selection_color(VMDMENU_VALUE_SEL); 01980 isomaxinput->callback(minmaxinputcb, this); 01981 01982 Fl_Group::end(); 01983 } 01984 const char *repcmd() { 01985 sprintf(cmdbuf, "Orbital %f %d %d %d %.3f %d %d %d %d %d", 01986 (float) isovalue->value(), 01987 (int) (orbitalindex->value() + orbitalminindex + 1), // 1-based 01988 (int) boundary->value(), 01989 (int) method->value(), 01990 (float) resolution->value(), 01991 (int) thickness->value(), 01992 (int) wavefnctype->value(), 01993 (int) wavefncspin->value(), 01994 (int) wavefncexcitation->value(), 01995 gridstepsize); 01996 return cmdbuf; 01997 } 01998 void set_values(AtomRep *rep) { 01999 int oldtype = wavefnctype->value(); 02000 int oldspin = wavefncspin->value(); 02001 int oldexcitation = wavefncexcitation->value(); 02002 02003 int newtype = (int) rep->get_data(AtomRep::WAVEFNCTYPE); 02004 int newspin = (int) rep->get_data(AtomRep::WAVEFNCSPIN); 02005 int newexcitation = (int) rep->get_data(AtomRep::WAVEFNCEXCITATION); 02006 02007 // Only regenerate the orbital list when required, otherwise 02008 // the updates interfere with the isovalue slider operation. 02009 if (oldtype != newtype || oldspin != newspin || 02010 oldexcitation != newexcitation) { 02011 wavefnctype->setvalue(newtype); 02012 wavefncspin->setvalue(newspin); 02013 02014 if (oldtype != newtype) { 02015 // regenerate the excitation chooser contents based on the 02016 // currently selected wavefunction type 02017 regen_excitationlist(); 02018 } 02019 wavefncexcitation->setvalue(newexcitation); 02020 } 02021 02022 // regenerate the orbital index list if the wavefunction has 02023 // changed, or if a text command has gone beyond the range of 02024 // the existing orbital list. 02025 int oldorbidx = orbitalindex->value() + orbitalminindex + 1; // 1-based 02026 int neworbidx = (int)rep->get_data(AtomRep::SPHERERES); 02027 if (oldtype != newtype || oldspin != newspin || 02028 oldexcitation != newexcitation || 02029 abs(neworbidx-oldorbidx) > 10) { 02030 // regenerate the orbital chooser contents based on the 02031 // currently selected wavefunction type, spin, and excitation 02032 regen_orbitallist(neworbidx); 02033 } 02034 orbitalindex->setvalue(neworbidx - orbitalminindex - 1); // 0-based 02035 02036 // minmax needs to update whenever dataset is changed or 02037 // the selected rep is switched 02038 if (minmaxlist.num() > 0) { 02039 minmax &m = minmaxlist[orbitalindex->value()]; 02040 isovalue->range(m.minval, m.maxval); 02041 } else { 02042 isovalue->range(0, 1); 02043 } 02044 isovalue->value(rep->get_data(AtomRep::SPHERERAD)); 02045 method->setvalue((int)rep->get_data(AtomRep::BONDRES)); 02046 boundary->setvalue((int)rep->get_data(AtomRep::LINETHICKNESS)); 02047 resolution->value(rep->get_data(AtomRep::GRIDSPACING)); 02048 thickness->value(rep->get_data(AtomRep::ISOLINETHICKNESS)); 02049 set_grid_stepsize((int) rep->get_data(AtomRep::ISOSTEPSIZE)); 02050 setInputFromSlider(); 02051 } 02052 void set_grid_stepsize(int step) { 02053 if (step < 1) 02054 step=1; 02055 02056 gridstepsize = step; 02057 } 02058 }; 02059 02060 02061 02062 02064 class GraphicsFltkRepFieldLines : public GraphicsFltkRepVolumetric { 02065 private: 02066 Fl_Counter *thickness; 02067 Fl_Counter *delta; 02068 Fl_Value_Slider *gradmag; 02069 Fl_Value_Slider *minlen; 02070 Fl_Value_Slider *maxlen; 02071 RepChoiceSmall *drawstyle; 02072 RepChoiceSmall *seedmethod; 02073 02074 protected: 02075 void do_dataset_clear() { 02076 gradmag->deactivate(); 02077 minlen->deactivate(); 02078 maxlen->deactivate(); 02079 thickness->deactivate(); 02080 delta->deactivate(); 02081 drawstyle->activate(); 02082 seedmethod->activate(); 02083 } 02084 void do_dataset_append(const char *, double, double) { 02085 gradmag->activate(); 02086 minlen->activate(); 02087 maxlen->activate(); 02088 thickness->activate(); 02089 delta->activate(); 02090 drawstyle->activate(); 02091 seedmethod->activate(); 02092 } 02093 void do_reset() { 02094 gradmag->value(1.8); 02095 minlen->value(10); 02096 maxlen->value(50); 02097 thickness->value(1); 02098 delta->value(0.25); 02099 drawstyle->value(0); 02100 seedmethod->value(0); 02101 } 02102 02103 public: 02104 GraphicsFltkRepFieldLines(Fl_Callback *cb, void *v) 02105 : GraphicsFltkRepVolumetric(cb, v) { 02106 02107 drawstyle = new RepChoiceSmall(x()+40,y()+60,"Style"); 02108 drawstyle->add("Line"); 02109 drawstyle->add("Tube"); 02110 drawstyle->add("Spheres"); 02111 drawstyle->callback(cb, v); 02112 02113 seedmethod = new RepChoiceSmall(x()+40,y()+90,"Seed"); 02114 seedmethod->add("Gradient"); 02115 seedmethod->add("Grid"); 02116 seedmethod->callback(cb, v); 02117 02118 thickness = new ResolutionCounter(x()+170, y()+60, "Size"); 02119 thickness->callback(cb, v); 02120 02121 delta = new DeltaCounter(x()+170, y()+90, "Delta"); 02122 delta->callback(cb, v); 02123 02124 gradmag = new IsoSlider(x()+80, y()+120, "GradientMag"); 02125 gradmag->callback(cb, v); 02126 minlen = new IsoSlider(x()+80, y()+150, "Min Length"); 02127 minlen->callback(cb, v); 02128 maxlen = new IsoSlider(x()+80, y()+180, "Max Length"); 02129 maxlen->callback(cb, v); 02130 02131 Fl_Group::end(); 02132 } 02133 const char *repcmd() { 02134 if (dataset->size() > 0) { 02135 sprintf(cmdbuf, "FieldLines %f %f %f %f %f %f %f %f", 02136 (float)dataset->value(), gradmag->value(), minlen->value(), 02137 maxlen->value(), thickness->value(), 02138 (float)drawstyle->value(), (float)seedmethod->value(), 02139 delta->value()); 02140 } else { 02141 sprintf(cmdbuf, "FieldLines"); 02142 } 02143 return cmdbuf; 02144 } 02145 void set_values(AtomRep *rep) { 02146 dataset->setvalue((int)rep->get_data(AtomRep::SPHERERES)); 02147 gradmag->range(0.05, 25.0); 02148 gradmag->value(rep->get_data(AtomRep::SPHERERAD)); 02149 minlen->range(1, 500.0); 02150 minlen->value(rep->get_data(AtomRep::BONDRAD)); 02151 maxlen->range(1, 500.0); 02152 maxlen->value(rep->get_data(AtomRep::BONDRES)); 02153 thickness->range(1, 10); 02154 thickness->value(rep->get_data(AtomRep::LINETHICKNESS)); 02155 delta->range(0.005, 4.0); 02156 delta->value(rep->get_data(AtomRep::FIELDLINEDELTA)); 02157 drawstyle->setvalue((int) rep->get_data(AtomRep::FIELDLINESTYLE)); 02158 seedmethod->setvalue((int) rep->get_data(AtomRep::FIELDLINESEEDUSEGRID)); 02159 } 02160 }; 02161 02162