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 // generated by Fast Light User Interface Designer (fluid) version 1.0009 00010 00011 #include <stdio.h> 00012 #include <math.h> 00013 #include "GeometryFltkMenu.h" 00014 #include "GeometryList.h" 00015 #include "Command.h" 00016 #include "VMDApp.h" 00017 #include "PickList.h" 00018 #include "Atom.h" 00019 #include "Molecule.h" 00020 #include "MoleculeList.h" 00021 #include "FL/fl_draw.H" 00022 #include "FL/forms.H" 00023 #include "FL/Fl_Input.H" 00024 #include "TextEvent.h" 00025 #include "Inform.h" 00026 00027 #if defined(VMD_FLCHART_WORKAROUND) 00028 00031 class myFl_Chart : public Fl_Widget { 00032 protected: 00033 void draw(); 00034 00035 private: 00036 int num; 00037 float *values; 00038 float min, max; 00039 int imin, imax; 00040 00041 public: 00042 myFl_Chart(int, int, int, int, const char * = 0); 00043 ~myFl_Chart(); 00044 00045 void clear(); 00046 void set_data(const float *data, int n); 00047 }; 00048 00049 myFl_Chart::myFl_Chart(int x, int y, int w, int h, const char *l) 00050 : Fl_Widget(x,y,w,h,l) { 00051 box(FL_BORDER_BOX); 00052 align(FL_ALIGN_BOTTOM); 00053 num = 0; 00054 values = NULL; 00055 min = max = 0; 00056 imin = imax = 0; 00057 } 00058 00059 myFl_Chart::~myFl_Chart() { 00060 delete [] values; 00061 } 00062 00063 void myFl_Chart::clear() { 00064 delete [] values; 00065 values = NULL; 00066 num = 0; 00067 redraw(); 00068 } 00069 00070 void myFl_Chart::set_data(const float *data, int n) { 00071 if (n < 1) { 00072 clear(); 00073 return; 00074 } 00075 delete [] values; 00076 values = new float[n]; 00077 memcpy(values, data, n*sizeof(float)); 00078 num = n; 00079 min = max = data[0]; 00080 imin = imax = 0; 00081 for (int i=1; i<n; i++) { 00082 if (min > data[i]) { min = data[i]; imin = i; } 00083 if (max < data[i]) { max = data[i]; imax = i; } 00084 } 00085 redraw(); 00086 } 00087 00088 // Use Fltk's definition of rint, since Windows sees fit to omit rint 00089 // from its math library. This definition isn't correct for negative 00090 // arguments, but it's what's used in the original Fl_Chart class, 00091 // from which this code was derived, so I'll keep doing it there way. 00092 static double fltk_rint(double v) {return floor(v+.5);} 00093 00094 void myFl_Chart::draw() { 00095 int xx, yy, ww, hh; 00096 if (!num) return; 00097 xx = x()+9; 00098 yy = y()+9; 00099 ww = w()-2*9; 00100 hh = h()-2*9; 00101 00102 draw_box(); 00103 00104 double lh = fl_height(); // compensate for text height? 00105 double incr; 00106 int zeroh; 00107 if (min > 0) { 00108 incr = (hh-2*lh)/max; 00109 zeroh = yy+hh-9; 00110 } else if (max < 0) { 00111 incr = (hh-2*lh)/min; 00112 zeroh = yy-9; 00113 } else { 00114 incr = (hh-2*lh)/(max-min); 00115 zeroh = yy+hh+(int)fltk_rint(min*incr) - 9; 00116 } 00117 double bwidth = ww/double(num); 00118 00119 for (int i=1; i<num; i++) { 00120 int x0 = xx + (int)fltk_rint((i-.5)*bwidth); 00121 int x1 = xx + (int)fltk_rint((i+.5)*bwidth); 00122 int y0 = zeroh - (int)fltk_rint(values[i-1]*incr); 00123 int y1 = zeroh - (int)fltk_rint(values[i]*incr); 00124 int color = FL_GREEN; 00125 00126 if (i == imin) color = FL_RED; 00127 else if (i == imax) color = FL_BLUE; 00128 fl_color(color); 00129 if ((values[i-1]>0.0)!=(values[i]>0.0)) { 00130 double ttt = values[i-1]/(values[i-1]-values[i]); 00131 int xt = xx + (int)fltk_rint((i-.5+ttt)*bwidth); 00132 fl_polygon(x0,zeroh, x0,y0, xt,zeroh); 00133 fl_polygon(xt,zeroh, x1,y1, x1,zeroh); 00134 } else { 00135 //assert(x0 >= xx && x0 <= xx+ww); 00136 //assert(x1 >= xx && x1 <= xx+ww); 00137 //assert(y0 >= yy && y0 <= yy+hh); 00138 //assert(y1 >= yy && y1 <= yy+hh); 00139 //assert(zeroh >= yy && zeroh <= yy+hh); 00140 fl_polygon(x0, zeroh, x0, y0, x1, y1, x1, zeroh); 00141 } 00142 fl_color(FL_BLACK); 00143 fl_line(x0,y0,x1,y1); 00144 } 00145 fl_line(xx, zeroh, xx+ww, zeroh); 00146 char buf[30] = { 0 }; 00147 sprintf(buf, "%d: %3.2f", imin, min); 00148 fl_draw(buf, xx+(int)fltk_rint((imin+.5)*bwidth), zeroh-(int)fltk_rint(min*incr),0,0, 00149 min >= 0 ? FL_ALIGN_BOTTOM : FL_ALIGN_TOP); 00150 sprintf(buf, "%d: %3.2f", imax, max); 00151 fl_draw(buf, xx+(int)fltk_rint((imax+.5)*bwidth), zeroh-(int)fltk_rint(max*incr),0,0, 00152 max >= 0 ? FL_ALIGN_BOTTOM : FL_ALIGN_TOP); 00153 } 00154 00155 #endif // VMD_FLCHART_WORKAROUND 00156 00157 00158 void GeometryFltkMenu::handle_pick(Molecule *m, int atomid, float value) { 00159 char buf[64] = { 0 }; 00160 00161 if (!m || !m->current()) return; 00162 MolAtom *atm = m->atom(atomid); 00163 float *framepos = m->current()->pos; 00164 00165 char *molnamebuf = new char[20+strlen(m->molname())]; 00166 sprintf(molnamebuf, "%d: %s", m->id(), m->molname()); 00167 pickedmolecule->value(molnamebuf); 00168 delete [] molnamebuf; 00169 pickedresname->value(m->resNames.name(atm->resnameindex)); 00170 sprintf(buf, "%d", atm->resid); 00171 pickedresid->value(buf); 00172 pickedname->value(m->atomNames.name(atm->nameindex)); 00173 pickedtype->value(m->atomTypes.name(atm->typeindex)); 00174 sprintf(buf, "%d", atomid); 00175 pickedindex->value(buf); 00176 pickedchain->value(m->chainNames.name(atm->chainindex)); 00177 pickedsegname->value(m->segNames.name(atm->segnameindex)); 00178 sprintf(buf, "%8.3f %8.3f %8.3f", framepos[3*atomid+0], 00179 framepos[3*atomid+1], framepos[3*atomid+2]); 00180 pickedpos->value(buf); 00181 sprintf(buf, "%8.3f", value); 00182 pickedvalue->value(buf); 00183 } 00184 00185 void GeometryFltkMenu::fill_label_browser() { 00186 int cat = labeltypechooser->value(); 00187 GeomListPtr geomlist = glist->geom_list(cat); 00188 int gnum = geomlist->num(); 00189 00190 int curnum = labelbrowser->size(); 00191 // Only clear if the number has changed so that when we show or hide 00192 // it doesn't reset the items we've selected. 00193 if (curnum != gnum) { 00194 labelbrowser->clear(); 00195 } 00196 // for each label, break up the name by '/'. Each element goes in its 00197 // own column in the browser, with a format string preceding to specify 00198 // the color of the item. 00199 for (int j=0; j<gnum; j++) { 00200 char geomname[128] = { 0 }; 00201 char geomstr[128] = { 0 }; 00202 char buf[20] = { 0 }; 00203 GeometryMol *g = (*geomlist)[j]; 00204 strcpy(geomname, g->name()); 00205 geomstr[0] = '0円'; 00206 char *start = geomname; 00207 char *s = start; 00208 int done = 0; 00209 while (!done) { 00210 if (*s == '/' || *s == '0円') { 00211 if (!*s) 00212 done = 1; 00213 *s = '0円'; 00214 // color 203 is "Orchid". 00215 sprintf(buf, "%s%s\t", g->displayed() ? VMDMENU_GEOM_ACTIVE : VMDMENU_GEOM_INACTIVE, start); 00216 strcat(geomstr, buf); 00217 start = s+1; 00218 s = start; 00219 } else { 00220 s++; 00221 } 00222 } 00223 if (curnum != gnum) 00224 labelbrowser->add(geomstr); 00225 else 00226 labelbrowser->text(j+1, geomstr); 00227 } 00228 } 00229 00230 void GeometryFltkMenu::update_labelprops() { 00231 char tmpbuf[100] = { 0 }; 00232 float textsize = app->label_get_text_size(); 00233 sprintf(tmpbuf, "%5.2f", textsize); 00234 textsizeinput->value(tmpbuf); 00235 textsizeslider->value(textsize); 00236 00237 float textthickness = app->label_get_text_thickness(); 00238 sprintf(tmpbuf, "%5.2f", textthickness); 00239 textthicknessinput->value(tmpbuf); 00240 textthicknessslider->value(textthickness); 00241 00242 // get the offset of the selected label, if any 00243 int ind = labelbrowser->value(); 00244 if (ind > 0) { 00245 textoffsetpositioner->activate(); 00246 offsetresetbutton->activate(); 00247 const float *offset = app->geometryList->getTextOffset( 00248 labeltypechooser->text(), ind-1); 00249 if (offset) { 00250 textoffsetpositioner->xvalue(offset[0]); 00251 textoffsetpositioner->yvalue(-offset[1]); 00252 } else { 00253 msgWarn << "No label found to update text offset!" << sendmsg; 00254 } 00255 if (labeltypechooser->value() == 0) { // only for atom labels 00256 textformatinput->activate(); 00257 if (!user_is_typing_in_format_input) { 00258 const char *format = app->geometryList->getTextFormat( 00259 labeltypechooser->text(), ind-1); 00260 if (format) { 00261 textformatinput->value(format); 00262 } else { 00263 msgWarn << "No label found to update text format!" << sendmsg; 00264 } 00265 } 00266 } 00267 } else { 00268 textoffsetpositioner->deactivate(); 00269 offsetresetbutton->deactivate(); 00270 } 00271 if (ind < 1 || labeltypechooser->value() != 0) { 00272 textformatinput->deactivate(); 00273 } 00274 } 00275 00276 // populate the geometry type chooser. 00277 void GeometryFltkMenu::update_geometry_types() { 00278 labeltypechooser->clear(); 00279 for (int j=0; j<glist->num_lists(); j++) 00280 labeltypechooser->add(glist->geom_list_name(j)); 00281 labeltypechooser->value(0); 00282 } 00283 00284 void GeometryFltkMenu::typechooser_cb(Fl_Widget *, void *v) { 00285 ((GeometryFltkMenu *)v)->fill_label_browser(); 00286 ((GeometryFltkMenu *)v)->update_labelprops(); 00287 } 00288 00289 void GeometryFltkMenu::graphinwindow_cb(Fl_Widget *, void *v) { 00290 GeometryFltkMenu *self = (GeometryFltkMenu *)v; 00291 int last_clicked = self->labelbrowser->value(); 00292 if (!self->labelbrowser->selected(last_clicked)) { 00293 return; 00294 } 00295 00296 int item = last_clicked-1; 00297 GeomListPtr geomlist = self->glist->geom_list(self->labeltypechooser->value()); 00298 // make sure the label hasn't been deleted out from under us 00299 if (item >= geomlist->num()) { 00300 return; 00301 } 00302 GeometryMol *geom = (*geomlist)[item]; 00303 ResizeArray<float> values; 00304 if (!geom->calculate_all(values)) { 00305 return; 00306 } 00307 if (values.num() < 1) { 00308 return; 00309 } 00310 #if defined(VMD_FLCHART_WORKAROUND) 00311 // XXX workaround Fl_Chart bug that could cause out-of-bounds drawing 00312 self->chart->set_data(&(values[0]), values.num()); 00313 #else 00314 int i; 00315 self->chart->clear(); 00316 if (values.num() > 0) { 00317 self->chart->maxsize(values.num()); 00318 for (i=0; i<values.num(); i++) { 00319 self->chart->insert(i, values[i], NULL, 0); 00320 } 00321 } 00322 #endif 00323 } 00324 00325 void GeometryFltkMenu::show_cb(Fl_Widget *, void *v) { 00326 GeometryFltkMenu *self = (GeometryFltkMenu *)v; 00327 for (int i=self->labelbrowser->size(); i>0; i--) { 00328 if (self->labelbrowser->selected(i)) { 00329 self->app->label_show(self->labeltypechooser->text(), i-1, 1); 00330 } 00331 } 00332 } 00333 00334 void GeometryFltkMenu::hide_cb(Fl_Widget *, void *v) { 00335 GeometryFltkMenu *self = (GeometryFltkMenu *)v; 00336 for (int i=self->labelbrowser->size(); i>0; i--) { 00337 if (self->labelbrowser->selected(i)) { 00338 self->app->label_show(self->labeltypechooser->text(), i-1, 0); 00339 } 00340 } 00341 } 00342 00343 void GeometryFltkMenu::delete_cb(Fl_Widget *, void *v) { 00344 GeometryFltkMenu *self = (GeometryFltkMenu *)v; 00345 ResizeArray<int> tmp; 00346 int i; 00347 for (i=self->labelbrowser->size(); i>0; i--) { 00348 if (self->labelbrowser->selected(i)) tmp.append(i-1); 00349 } 00350 for (i=0; i<tmp.num(); i++) 00351 self->app->label_delete(self->labeltypechooser->text(), tmp[i]); 00352 } 00353 00354 void GeometryFltkMenu::labelbrowser_cb(Fl_Widget *, void *v) { 00355 GeometryFltkMenu *self = (GeometryFltkMenu *)v; 00356 int ind = self->labelbrowser->value(); 00357 if (ind < 1) return; 00358 int labeltype = self->labeltypechooser->value(); 00359 //GeomListPtr geomlist = self->glist->geom_list(labeltype); 00360 GeometryMol *geom = (*(self->glist->geom_list(labeltype)))[ind-1]; 00361 int atomid = geom->com_index(0); 00362 int molid = geom->obj_index(0); 00363 Molecule *m = self->app->moleculeList->mol_from_id(molid); 00364 // make sure we have the up-to-date value. 00365 geom->calculate(); 00366 self->handle_pick(m, atomid, geom->value()); 00367 if (self->previewcheckbutton->value()) { 00368 self->graphinwindow_cb(self->chart, self); 00369 } 00370 // show the correct label offset 00371 self->update_labelprops(); 00372 } 00373 00374 void GeometryFltkMenu::exportgraph_cb(Fl_Widget *, void *v) { 00375 GeometryFltkMenu *self = (GeometryFltkMenu *)v; 00376 if (self->labelbrowser->size() < 1) { 00377 msgInfo << "No labels selected" << sendmsg; 00378 return; 00379 } 00380 GeomListPtr geomlist = self->glist->geom_list(self->labeltypechooser->value()); 00381 if (geomlist->num() < 1) { 00382 msgErr << "GeometryFltkMenu::exportgraph_cb: No labels in list! That's weird." << sendmsg; 00383 return; 00384 } 00385 ResizeArray<int> items; 00386 for (int item=0; item <self->labelbrowser->size(); item++) { 00387 if (!self->labelbrowser->selected(1+item)) continue; 00388 items.append(item); 00389 GeometryMol *geom = (*geomlist)[item]; 00390 ResizeArray<float> values; 00391 if (!geom->calculate_all(values)) { 00392 msgErr << "GeometryFltkMenu::exportgraph_cb: Couldn't calculate values" << sendmsg; 00393 return; 00394 } 00395 if (values.num() < 1) { 00396 msgErr << "Nothing to plot!" << sendmsg; 00397 return; 00398 } 00399 } 00400 self->runcommand(new GraphLabelEvent(self->labeltypechooser->text(), 00401 &items[0], items.num())); 00402 } 00403 00404 // XXX Massive replication of code in exportgraph_cb, savetofile_cb, and 00405 // graphinwindow_cb. 00406 void GeometryFltkMenu::savetofile_cb(Fl_Widget *, void *v) { 00407 GeometryFltkMenu *self = (GeometryFltkMenu *)v; 00408 if (self->labelbrowser->size() < 1) { 00409 msgInfo << "No labels selected" << sendmsg; 00410 return; 00411 } 00412 GeomListPtr geomlist = self->glist->geom_list(self->labeltypechooser->value()); 00413 if (geomlist->num() < 1) { 00414 msgErr << "GeometryFltkMenu::savetofile_cb: No labels in list! That's weird." << sendmsg; 00415 return; 00416 } 00417 for (int item=0; item <self->labelbrowser->size(); item++) { 00418 if (!self->labelbrowser->selected(1+item)) continue; 00419 GeometryMol *geom = (*geomlist)[item]; 00420 ResizeArray<float> values; 00421 if (!geom->calculate_all(values)) { 00422 msgErr << "GeometryFltkMenu::savetofile_cb: Couldn't calculate values" << sendmsg; 00423 return; 00424 } 00425 if (values.num() < 1) { 00426 msgErr << "Nothing to plot!" << sendmsg; 00427 return; 00428 } 00429 char *file = self->app->vmd_choose_file(geom->unique_name(), 00430 "*.dat", 00431 "data file", 00432 1); 00433 if (!file) continue; 00434 FILE *fd = fopen(file, "w"); 00435 for (int i=0; i<values.num(); i++) { 00436 fprintf(fd, "%d\t%f\n", i, values[i]); 00437 } 00438 fclose(fd); 00439 } 00440 } 00441 00442 // handlers for adjusting label offset 00443 static void textoffset_cb(Fl_Widget *w, void *v) { 00444 Fl_Positioner *p = (Fl_Positioner *)w; 00445 00446 float x = (float) p->xvalue(); 00447 float y = (float) -p->yvalue(); 00448 ((GeometryFltkMenu *)v)->apply_offset_to_selected_labels(x, y); 00449 } 00450 00451 static void offsetreset_cb(Fl_Widget *, void *v) { 00452 ((GeometryFltkMenu *)v)->apply_offset_to_selected_labels(0, 0); 00453 } 00454 00455 void GeometryFltkMenu::apply_offset_to_selected_labels(float x, float y) { 00456 // get the selected geometry category 00457 const char *geomtype = labeltypechooser->text(); 00458 00459 // get all the currently selected labels 00460 for (int l=labelbrowser->size(); l>0; l--) { 00461 if (labelbrowser->selected(l)) { 00462 app->label_set_textoffset(geomtype, l-1, x, y); 00463 } 00464 } 00465 } 00466 00467 // handlers for setting label format 00468 static void textformat_cb(Fl_Widget *w, void *v) { 00469 Fl_Input *input = (Fl_Input *)w; 00470 ((GeometryFltkMenu *)v)->apply_format_to_selected_labels(input->value()); 00471 } 00472 void GeometryFltkMenu::apply_format_to_selected_labels(const char *format) { 00473 // get the selected geometry category 00474 const char *geomtype = labeltypechooser->text(); 00475 00476 // prevent the format entry from getting updated as we type, because 00477 // it selects all text, which makes it impossible to type more the one 00478 // character at a time. 00479 user_is_typing_in_format_input = TRUE; 00480 00481 00482 // get all the currently selected labels 00483 for (int l=labelbrowser->size(); l>0; l--) { 00484 if (labelbrowser->selected(l)) { 00485 app->label_set_textformat(geomtype, l-1, format); 00486 } 00487 } 00488 user_is_typing_in_format_input = FALSE; 00489 } 00490 00491 static void textsizeslidercb(Fl_Widget *w, void *v) { 00492 Fl_Slider *slider = (Fl_Slider *)w; 00493 VMDApp *app = (VMDApp *)v; 00494 app->label_set_text_size((float) slider->value()); 00495 } 00496 00497 static void textsizeinputcb(Fl_Widget *w, void *v) { 00498 Fl_Float_Input *input = (Fl_Float_Input *)w; 00499 VMDApp *app = (VMDApp *)v; 00500 char *endptr = NULL; 00501 const char *strval = input->value(); 00502 double val = strtod(strval, &endptr); 00503 if (endptr != strval) { 00504 // valid conversion performed 00505 app->label_set_text_size((float)val); 00506 } 00507 } 00508 00509 static void textthicknessslidercb(Fl_Widget *w, void *v) { 00510 Fl_Slider *slider = (Fl_Slider *)w; 00511 VMDApp *app = (VMDApp *)v; 00512 app->label_set_text_thickness((float) slider->value()); 00513 } 00514 00515 static void textthicknessinputcb(Fl_Widget *w, void *v) { 00516 Fl_Float_Input *input = (Fl_Float_Input *)w; 00517 VMDApp *app = (VMDApp *)v; 00518 char *endptr = NULL; 00519 const char *strval = input->value(); 00520 double val = strtod(strval, &endptr); 00521 if (endptr != strval) { 00522 // valid conversion performed 00523 app->label_set_text_thickness((float)val); 00524 } 00525 } 00526 00527 class My_Fl_Positioner : public Fl_Positioner { 00528 public: 00529 My_Fl_Positioner(int x, int y, int w, int h, const char *t=NULL) 00530 : Fl_Positioner(x, y, w, h, t) {} 00531 virtual void draw() { 00532 Fl_Positioner::draw(); 00533 fl_circle(90+50, 190+50, 5); 00534 } 00535 }; 00536 00537 static const int columns[] = {85, 85, 85, 85, 0}; 00538 void GeometryFltkMenu::make_window() { 00539 size(380,335); 00540 00541 { 00542 labelbrowser = new Fl_Multi_Browser(10, 45, 360, 70); 00543 VMDFLTKTOOLTIP(labelbrowser, "Select label to modify") 00544 labelbrowser->color(VMDMENU_BROWSER_BG); 00545 labelbrowser->selection_color(VMDMENU_BROWSER_SEL); 00546 labelbrowser->callback(labelbrowser_cb, this); 00547 labelbrowser->column_widths(columns); 00548 00549 { Fl_Choice* o = labeltypechooser = new Fl_Choice(10, 15, 95, 25); 00550 VMDFLTKTOOLTIP(labeltypechooser, "Select label type to show in browser") 00551 o->color(VMDMENU_CHOOSER_BG); 00552 o->selection_color(VMDMENU_CHOOSER_SEL); 00553 o->box(FL_THIN_UP_BOX); 00554 o->labeltype(FL_NO_LABEL); 00555 o->callback(typechooser_cb, this); 00556 } 00557 showbutton = new Fl_Button(125, 15, 75, 25, "Show"); 00558 #if defined(VMDMENU_WINDOW) 00559 showbutton->color(VMDMENU_WINDOW, FL_GRAY); 00560 #endif 00561 VMDFLTKTOOLTIP(showbutton, "Show (unhide) selected label") 00562 showbutton->callback(show_cb, this); 00563 00564 hidebutton = new Fl_Button(200, 15, 75, 25, "Hide"); 00565 #if defined(VMDMENU_WINDOW) 00566 hidebutton->color(VMDMENU_WINDOW, FL_GRAY); 00567 #endif 00568 VMDFLTKTOOLTIP(hidebutton, "Hide (do not display) selected label") 00569 hidebutton->callback(hide_cb, this); 00570 00571 deletebutton = new Fl_Button(275, 15, 75, 25, "Delete"); 00572 #if defined(VMDMENU_WINDOW) 00573 deletebutton->color(VMDMENU_WINDOW, FL_GRAY); 00574 #endif 00575 VMDFLTKTOOLTIP(deletebutton, "Delete selected label") 00576 deletebutton->callback(delete_cb, this); 00577 00578 { Fl_Tabs* o = new Fl_Tabs(10, 120, 360, 215); 00579 #if defined(VMDMENU_WINDOW) 00580 o->color(VMDMENU_WINDOW, FL_GRAY); 00581 o->selection_color(VMDMENU_WINDOW); 00582 #endif 00583 00584 { Fl_Group* o = pickinggroup = new Fl_Group(35, 145, 315, 180, "Picked Atom"); 00585 #if defined(VMDMENU_WINDOW) 00586 o->color(VMDMENU_WINDOW, FL_GRAY); 00587 o->selection_color(VMDMENU_WINDOW); 00588 #endif 00589 00590 Fl_Widget *w; 00591 w = pickedmolecule = new Fl_Output(110, 155, 230, 25, "Molecule:"); 00592 VMDFLTKTOOLTIP(pickedmolecule, "Parent molecule of picked atom") 00593 w->selection_color(VMDMENU_VALUE_SEL); 00594 00595 w = pickedresname = new Fl_Output(110, 205, 70, 25, "ResName:"); 00596 VMDFLTKTOOLTIP(pickedresname, "Parent residue name of picked atom") 00597 w->selection_color(VMDMENU_VALUE_SEL); 00598 00599 w = pickedresid = new Fl_Output(110, 230, 70, 25, "ResID:"); 00600 VMDFLTKTOOLTIP(pickedresid, "Parent residue ID of picked atom") 00601 w->selection_color(VMDMENU_VALUE_SEL); 00602 00603 w = pickedname = new Fl_Output(110, 255, 70, 25, "Name:"); 00604 VMDFLTKTOOLTIP(pickedname, "Name of picked atom") 00605 w->selection_color(VMDMENU_VALUE_SEL); 00606 00607 w = pickedtype = new Fl_Output(110, 280, 70, 25, "Type:"); 00608 VMDFLTKTOOLTIP(pickedtype, "Type of picked atom") 00609 w->selection_color(VMDMENU_VALUE_SEL); 00610 00611 w = pickedpos = new Fl_Output(110, 180, 230, 25, "XYZ:"); 00612 VMDFLTKTOOLTIP(pickedpos, "Coordinates of picked atom") 00613 w->selection_color(VMDMENU_VALUE_SEL); 00614 00615 w = pickedchain = new Fl_Output(270, 205, 70, 25, "Chain:"); 00616 VMDFLTKTOOLTIP(pickedchain, "Parent chain of picked atom") 00617 w->selection_color(VMDMENU_VALUE_SEL); 00618 00619 w = pickedsegname = new Fl_Output(270, 230, 70, 25, "SegName:"); 00620 VMDFLTKTOOLTIP(pickedsegname, "Parent segment name of picked atom") 00621 w->selection_color(VMDMENU_VALUE_SEL); 00622 00623 w = pickedindex = new Fl_Output(270, 255, 70, 25, "Index:"); 00624 VMDFLTKTOOLTIP(pickedindex, "Index of picked atom") 00625 w->selection_color(VMDMENU_VALUE_SEL); 00626 00627 w = pickedvalue = new Fl_Output(270, 280, 70, 25, "Value:"); 00628 VMDFLTKTOOLTIP(pickedvalue, "Value of label (bond length, angle, dihedral, etc)") 00629 w->selection_color(VMDMENU_VALUE_SEL); 00630 00631 o->end(); 00632 } 00633 { Fl_Group* o = geometrygroup = new Fl_Group(35, 145, 315, 180, "Graph"); 00634 #if defined(VMDMENU_WINDOW) 00635 o->color(VMDMENU_WINDOW, FL_GRAY); 00636 o->selection_color(VMDMENU_WINDOW); 00637 #endif 00638 o->hide(); 00639 savetofilebutton = new Fl_Button(285, 155, 55, 25, "Save..."); 00640 #if defined(VMDMENU_WINDOW) 00641 savetofilebutton->color(VMDMENU_WINDOW, FL_GRAY); 00642 #endif 00643 VMDFLTKTOOLTIP(savetofilebutton, "Save label values to a file") 00644 savetofilebutton->callback(savetofile_cb, this); 00645 00646 exportgraphbutton = new Fl_Button(200, 155, 65, 25, "Graph..."); 00647 #if defined(VMDMENU_WINDOW) 00648 exportgraphbutton->color(VMDMENU_WINDOW, FL_GRAY); 00649 #endif 00650 VMDFLTKTOOLTIP(exportgraphbutton, "Export label values to other graphing tools") 00651 exportgraphbutton->callback(exportgraph_cb, this); 00652 00653 previewcheckbutton = new Fl_Check_Button(40, 155, 100, 25, "Show preview"); 00654 VMDFLTKTOOLTIP(previewcheckbutton, "Show quick preview graph of label value") 00655 #if defined(VMD_FLCHART_WORKAROUND) 00656 // XXX workaround Fl_Chart bug that could cause out-of-bounds drawing 00657 chart = new myFl_Chart(45, 190, 295, 125); 00658 #else 00659 //chart = new Fl_Chart(20, 210, 330, 90); 00660 chart = new Fl_Chart(45, 190, 295, 125); 00661 chart->type(FL_FILLED_CHART); 00662 #endif 00663 o->end(); 00664 } 00665 { Fl_Group *o = propertiesgroup = new Fl_Group(35, 145, 315, 180, "Properties"); 00666 #if defined(VMDMENU_WINDOW) 00667 o->color(VMDMENU_WINDOW, FL_GRAY); 00668 o->selection_color(VMDMENU_WINDOW); 00669 #endif 00670 o->hide(); 00671 textoffsetpositioner = new My_Fl_Positioner(90, 155, 100, 100, "Offset:"); 00672 textoffsetpositioner->align(FL_ALIGN_LEFT); 00673 textoffsetpositioner->color(VMDMENU_POSITIONER_BG); 00674 textoffsetpositioner->selection_color(VMDMENU_POSITIONER_SEL); 00675 textoffsetpositioner->when(FL_WHEN_CHANGED); 00676 textoffsetpositioner->callback(textoffset_cb, this); 00677 // make more room on the left side and below so it's possible to get atom labels 00678 // all the way to the left of their atom 00679 textoffsetpositioner->xbounds(-.7, .7); 00680 textoffsetpositioner->ybounds(-.5, .5); 00681 textoffsetpositioner->value(0,0); 00682 VMDFLTKTOOLTIP(textoffsetpositioner, "Set the label offset relative to its default position"); 00683 00684 offsetresetbutton = new Fl_Button(200, 193, 55, 25, "Reset"); 00685 #if defined(VMDMENU_WINDOW) 00686 offsetresetbutton->color(VMDMENU_WINDOW, FL_GRAY); 00687 #endif 00688 VMDFLTKTOOLTIP(offsetresetbutton, "Reset the label offset to (0,0)"); 00689 offsetresetbutton->callback(offsetreset_cb, this); 00690 00691 textformatinput = new Fl_Input(90, 260, 245, 25, "Format:"); 00692 textformatinput->selection_color(VMDMENU_VALUE_SEL); 00693 textformatinput->when(FL_WHEN_CHANGED); 00694 textformatinput->callback(textformat_cb, this); 00695 VMDFLTKTOOLTIP(textformatinput, "Set selected atom labels with substitutions: %R->resname, %1R->1-char resname, %r->camelcase resname, %d->resid, %a->name, %q->charge, %i->0-index, %1i->1-index, %p->atomic number, %e->element, %s->segname, %o->occupancy, %b->beta, %c->chain"); 00696 00697 o->end(); 00698 } 00699 { Fl_Group *o = globalpropsgroup = new Fl_Group(35, 145, 315, 180, "Global Properties"); 00700 #if defined(VMDMENU_WINDOW) 00701 o->color(VMDMENU_WINDOW, FL_GRAY); 00702 o->selection_color(VMDMENU_WINDOW); 00703 #endif 00704 o->hide(); 00705 textsizeinput = new Fl_Float_Input(130, 155, 50, 25, "Text Size:"); 00706 VMDFLTKTOOLTIP(textsizeinput, "Set label text size") 00707 textsizeinput->when(FL_WHEN_ENTER_KEY); 00708 textsizeinput->selection_color(VMDMENU_VALUE_SEL); 00709 textsizeinput->callback(textsizeinputcb, app); 00710 00711 textsizeslider = new Fl_Slider(180, 155, 180, 25); 00712 VMDFLTKTOOLTIP(textsizeslider, "Set label text size") 00713 textsizeslider->type(FL_HOR_SLIDER); 00714 textsizeslider->color(VMDMENU_SLIDER_BG); 00715 textsizeslider->when(FL_WHEN_CHANGED); 00716 textsizeslider->callback(textsizeslidercb, app); 00717 textsizeslider->range(0, 5); 00718 00719 textthicknessinput = new Fl_Float_Input(130, 190, 50, 25, "Text Thickness:"); 00720 VMDFLTKTOOLTIP(textsizeinput, "Set label text line thickness") 00721 textthicknessinput->when(FL_WHEN_ENTER_KEY); 00722 textthicknessinput->selection_color(VMDMENU_VALUE_SEL); 00723 textthicknessinput->callback(textthicknessinputcb, app); 00724 00725 textthicknessslider = new Fl_Slider(180, 190, 180, 25); 00726 VMDFLTKTOOLTIP(textsizeslider, "Set label text line thickness") 00727 textthicknessslider->type(FL_HOR_SLIDER); 00728 textthicknessslider->color(VMDMENU_SLIDER_BG); 00729 textthicknessslider->when(FL_WHEN_CHANGED); 00730 textthicknessslider->callback(textthicknessslidercb, app); 00731 textthicknessslider->range(0, 5); 00732 00733 o->end(); 00734 } 00735 o->end(); 00736 } 00737 Fl_Window::end(); 00738 00739 update_labelprops(); 00740 } 00741 } 00742 00743 GeometryFltkMenu::GeometryFltkMenu(VMDApp *vmdapp) 00744 : VMDFltkMenu("labels", "Labels", vmdapp), glist(vmdapp->geometryList) { 00745 00746 command_wanted(Command::LABEL_ADD); 00747 command_wanted(Command::LABEL_DELETE); 00748 command_wanted(Command::LABEL_SHOW); 00749 command_wanted(Command::LABEL_ADDSPRING); 00750 command_wanted(Command::LABEL_TEXTSIZE); 00751 command_wanted(Command::LABEL_TEXTTHICKNESS); 00752 command_wanted(Command::LABEL_TEXTOFFSET); 00753 command_wanted(Command::LABEL_TEXTFORMAT); 00754 command_wanted(Command::ANIM_NEW_FRAME); 00755 command_wanted(Command::PICK_EVENT); 00756 command_wanted(Command::MOL_DEL); 00757 00758 user_is_typing_in_format_input = FALSE; 00759 00760 make_window(); 00761 update_geometry_types(); 00762 } 00763 00764 int GeometryFltkMenu::act_on_command(int type, Command *cmd) { 00765 switch (type) { 00766 case Command::PICK_EVENT: 00767 { 00768 PickEvent *event = (PickEvent *)cmd; 00769 Molecule *m = app->moleculeList->check_pickable(event->pickable); 00770 if (m) 00771 handle_pick(m, event->tag, 0); 00772 } 00773 break; 00774 00775 case Command::LABEL_ADD: 00776 case Command::LABEL_ADDSPRING: 00777 case Command::LABEL_DELETE: 00778 case Command::LABEL_SHOW: 00779 fill_label_browser(); 00780 update_labelprops(); 00781 break; 00782 00783 case Command::ANIM_NEW_FRAME: 00784 labelbrowser->do_callback(); 00785 break; 00786 00787 case Command::LABEL_TEXTSIZE: 00788 case Command::LABEL_TEXTTHICKNESS: 00789 case Command::LABEL_TEXTOFFSET: 00790 case Command::LABEL_TEXTFORMAT: 00791 update_labelprops(); 00792 break; 00793 00794 case Command::MOL_DEL: 00795 glist->prepare(); // mark all non-ok geoms and delete them before 00796 fill_label_browser(); // refilling the label browser with the current list 00797 update_labelprops(); 00798 break; 00799 } 00800 return 1; 00801 } 00802