Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

ColorFltkMenu.C

Go to the documentation of this file.
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 #include "ColorFltkMenu.h"
00010 
00011 #include <stdio.h>
00012 #include <math.h>
00013 
00014 #include <FL/fl_draw.H>
00015 #include <FL/forms.H>
00016 #include <FL/Fl.H>
00017 #include <FL/Fl_Window.H>
00018 #include <FL/Fl_Hold_Browser.H>
00019 #include <FL/Fl_Box.H>
00020 #include <FL/Fl_Tabs.H>
00021 #include <FL/Fl_Group.H>
00022 #include <FL/Fl_Value_Slider.H>
00023 #include <FL/Fl_Button.H>
00024 #include <FL/Fl_Toggle_Button.H>
00025 #include <FL/Fl_Choice.H>
00026 #include <FL/Fl_Value_Slider.H>
00027 #include <FL/Fl_Input_Choice.H>
00028 #if defined(VMD_USE_FLTK_COLORCHOOSER)
00029 #include <FL/Fl_Color_Chooser.H>
00030 #endif
00031 
00032 #include "Command.h"
00033 #include "Scene.h"
00034 #include "VMDApp.h"
00035 #include "Inform.h"
00036 #include "utilities.h"
00037 
00039 class ColorscaleImage : public Fl_Box {
00040   VMDApp *app;
00041   int grating;
00042   unsigned char *data;
00043 
00044 public:
00045   ColorscaleImage(int myx, int myy, int myw, int myh, 
00046                   int grateon, VMDApp *vmdapp) : Fl_Box(myx, myy, myw, myh), app(vmdapp), grating(grateon) {
00047     data = new unsigned char[3*w()*h()];
00048   }
00049   ~ColorscaleImage() { delete [] data; }
00050 
00051 protected:
00052   virtual void draw() {
00053     if (grating) {
00054       // To validate color map usability we draw draw a 
00055       // Kovesi style 2-D color scale test w/ sinusoidal "grating" effect, 
00056       // by adding high-frequency 10% sinusoid to the value
00057       // See:  https://arxiv.org/abs/1509.03700
00058       const float *rgb = app->scene->color_value(REGCLRS);
00059       int xs = w(), ys = h();
00060       for (int ix=0; ix<xs; ix++) {
00061         for (int iy=0; iy<ys; iy++) {
00062           float vertscale = (0.05f * (ys-iy-1) / float(ys));
00063           float singrate =  sinf((xs / 5.0f) * VMD_TWOPIF * ix / float(xs));
00064           float csidx = (vertscale * singrate) + (ix/float(xs));
00065 
00066           // map to integer color scale index range   
00067           int idx = int(csidx * MAPCLRS);
00068           idx = (idx < 0)        ?           0 : idx;
00069           idx = (idx >= MAPCLRS) ? (MAPCLRS-1) : idx;
00070 
00071           int idx3 = idx*3;
00072           int img3 = (xs*iy + ix) * 3;
00073 
00074           unsigned char r = (unsigned char)(255*rgb[idx3 + 0]);
00075           unsigned char g = (unsigned char)(255*rgb[idx3 + 1]);
00076           unsigned char b = (unsigned char)(255*rgb[idx3 + 2]);
00077 
00078           data[img3    ] = r;
00079           data[img3 + 1] = g;
00080           data[img3 + 2] = b;
00081         }
00082       }
00083     } else {
00084       // just draw the plain colorscale data itself with no perturbation
00085       for (int i=0; i<w(); i++) {
00086         const float *rgb = app->scene->color_value(i*MAPCLRS/w()+REGCLRS);
00087         unsigned char r = (unsigned char)(255*rgb[0]);
00088         unsigned char g = (unsigned char)(255*rgb[1]);
00089         unsigned char b = (unsigned char)(255*rgb[2]);
00090         for (int j=0; j<h(); j++) {
00091           data[3*(w()*j + i)    ] = r;
00092           data[3*(w()*j + i) + 1] = g;
00093           data[3*(w()*j + i) + 2] = b;
00094         }
00095       }
00096 
00097     }
00098 
00099     fl_draw_image(data, x(), y(), w(), h());
00100   }
00101 
00102 };
00103 
00104 
00105 //#define VMD_FLCHART_WORKAROUND 1
00106 #if defined(VMD_FLCHART_WORKAROUND)
00107 
00108 // Use Fltk's definition of rint, since Windows sees fit to omit rint
00109 // from its math library.  This definition isn't correct for negative
00110 // arguments, but it's what's used in the original Fl_Chart class,
00111 // from which this code was derived, so I'll keep doing it there way.
00112 static double fltk_rint(double v) {return floor(v+.5);}
00113 
00118 class myFl_Chart : public Fl_Widget {
00119 private:
00120   int num;
00121   float *values;
00122   float min, max;
00123   int imin, imax;
00124 
00125 public:
00126   myFl_Chart(int x, int y, int w, int h, const char *l=0) : Fl_Widget(x,y,w,h,l) {
00127     box(FL_BORDER_BOX);
00128     align(FL_ALIGN_BOTTOM);
00129     num = 0;
00130     values = NULL;
00131     min = max = 0;
00132     imin = imax = 0;
00133   }
00134 
00135   ~myFl_Chart() {
00136     delete [] values;
00137   }
00138 
00139   void clear() {
00140     delete [] values;
00141     values = NULL;
00142     num = 0;
00143     redraw();
00144   }
00145 
00146   void set_data(const float *data, int n) {
00147     if (n < 1) {
00148       clear();
00149       return;
00150     }
00151     delete [] values;
00152     values = new float[n];
00153     memcpy(values, data, n*sizeof(float));
00154     num = n;
00155     min = max = data[0];
00156     imin = imax = 0;
00157     for (int i=1; i<n; i++) {
00158       if (min > data[i]) { min = data[i]; imin = i; }
00159       if (max < data[i]) { max = data[i]; imax = i; }
00160     }
00161     redraw();
00162   }
00163 
00164   void bounds(float newmin, float newmax) {
00165     min = newmin;
00166     max = newmax;
00167   }
00168 
00169 protected:
00170   void draw() {
00171     int xx, yy, ww, hh;
00172     if (!num) return;
00173     xx = x()+9;
00174     yy = y()+9;
00175     ww = w()-2*9;
00176     hh = h()-2*9;
00177 
00178     draw_box();
00179 
00180     double lh = fl_height(); // compensate for text height?
00181     double incr;
00182     int zeroh;
00183     if (min > 0) {
00184       incr = (hh-2*lh)/max;
00185       zeroh = yy+hh-9;
00186     } else if (max < 0) {
00187       incr = (hh-2*lh)/min;
00188       zeroh = yy-9;
00189     } else {
00190       incr = (hh-2*lh)/(max-min);
00191       zeroh = yy+hh+(int)fltk_rint(min*incr) - 9;
00192     }
00193     double bwidth = ww/double(num);
00194 
00195     for (int i=1; i<num; i++) {
00196       int x0 = xx    + (int)fltk_rint((i-.5)*bwidth);
00197       int x1 = xx    + (int)fltk_rint((i+.5)*bwidth);
00198       int y0 = zeroh - (int)fltk_rint(values[i-1]*incr);
00199       int y1 = zeroh - (int)fltk_rint(values[i]*incr);
00200       int color = FL_GREEN;
00201 
00202       if (i == imin) color = FL_RED;
00203       else if (i == imax) color = FL_BLUE;
00204       fl_color(color);
00205       if ((values[i-1]>0.0)!=(values[i]>0.0)) {
00206         double ttt = values[i-1]/(values[i-1]-values[i]);
00207         int xt = xx + (int)fltk_rint((i-.5+ttt)*bwidth);
00208         fl_polygon(x0,zeroh, x0,y0, xt,zeroh);
00209         fl_polygon(xt,zeroh, x1,y1, x1,zeroh);
00210       } else {
00211         fl_polygon(x0, zeroh, x0, y0, x1, y1, x1, zeroh);
00212       }
00213       fl_color(FL_BLACK);
00214       fl_line(x0,y0,x1,y1);
00215     }
00216     fl_line(xx, zeroh, xx+ww, zeroh);
00217 
00218 #if 0
00219     char buf[30] = { 0 };
00220     sprintf(buf, "%d: %3.2f", imin, min);
00221     fl_draw(buf, xx+(int)fltk_rint((imin+.5)*bwidth), zeroh-(int)fltk_rint(min*incr),0,0,
00222          min >= 0 ? FL_ALIGN_BOTTOM : FL_ALIGN_TOP);
00223     sprintf(buf, "%d: %3.2f", imax, max);
00224     fl_draw(buf, xx+(int)fltk_rint((imax+.5)*bwidth), zeroh-(int)fltk_rint(max*incr),0,0,
00225          max >= 0 ? FL_ALIGN_BOTTOM : FL_ALIGN_TOP);
00226 #endif
00227   }
00228 
00229 };
00230 
00231 #endif // VMD_FLCHART_WORKAROUND
00232 
00233 
00234 #if defined(VMD_FLCHART_WORKAROUND)
00235 #define CHARTCLASS myFl_Chart 
00236 #else
00237 #define CHARTCLASS Fl_Chart
00238 #endif
00239 
00241 class ColorscaleLumaChart : public CHARTCLASS {
00242   VMDApp *app;
00243   ResizeArray<float> values;
00244 
00245 public:
00246   ColorscaleLumaChart(int myx, int myy, int myw, int myh, VMDApp *vmdapp) : CHARTCLASS(myx, myy, myw, myh), app(vmdapp) {
00247   }
00248   ~ColorscaleLumaChart() { }
00249 
00250 protected:
00251   virtual void draw() {
00252     values.clear();
00253     // just draw the plain colorscale data itself with no perturbation
00254     int i;
00255     for (i=0; i<w(); i++) {
00256       const float *rgb = app->scene->color_value(i*MAPCLRS/w()+REGCLRS);
00257       float r = rgb[0];
00258       float g = rgb[1];
00259       float b = rgb[2];
00260 
00261       // convert linear gamma RGB to CIEXYZ
00262 //      float Xd65 = r*0.41239f + g*0.35758f + b*0.18048f;
00263       float Yd65 = r*0.21264f + g*0.71517f + b*0.07219f;
00264 //      float Zd65 = r*0.01933f + g*0.11919f + b*0.95053f;
00265 
00266       // convert CIEXYZ to CIELAB
00267 //      float fXd65 = (Xd65 > 0.008856) ? powf(Xd65, 1.0f/3.0f) : Xd65 * 7.787f + 16.0f/116.0f;
00268       float fYd65 = (Yd65 > 0.008856) ? powf(Yd65, 1.0f/3.0f) : Yd65 * 7.787f + 16.0f/116.0f;
00269 //      float fZd65 = (Zd65 > 0.008856) ? powf(Zd65, 1.0f/3.0f) : Zd65 * 7.787f + 16.0f/116.0f;
00270       float labL = (116.0f * fYd65) - 16.0f;
00271 //      float laba = 500.0f * (fXd65 - fYd65);
00272 //      float labb = 500.0f * (fYd65 - fZd65);
00273       values.append(labL);
00274     }
00275 
00276 #if defined(VMD_FLCHART_WORKAROUND)
00277     // XXX workaround Fl_Chart bug that could cause out-of-bounds drawing
00278     myFl_Chart::set_data(&(values[0]), values.num());
00279     myFl_Chart::draw();
00280 #else 
00281     clear();
00282     type(FL_LINE_CHART);
00283     bounds(0.0, 100.0);
00284     for (i=0; i<values.num(); i++) {
00285       add(values[i]);
00286     }
00287     Fl_Chart::draw();
00288 #endif // VMD_FLCHART_WORKAROUND
00289   }
00290 
00291 };
00292 
00293 
00294 
00295 void ColorFltkMenu::make_window() {
00296   size(475, 495);
00297   { 
00298     { Fl_Tabs* o = new Fl_Tabs(0, 0, 475, 495);
00299 #if defined(VMDMENU_WINDOW)
00300       o->color(VMDMENU_WINDOW, FL_GRAY);
00301       o->selection_color(VMDMENU_WINDOW);
00302 #endif
00303 
00304     //
00305     // Color editing tabs
00306     //
00307 
00308 #if defined(VMD_USE_FLTK_COLORCHOOSER)
00309       // use FLTK-provided color chooser
00310       { Fl_Group* o = new Fl_Group(0, 20, 475, 425, "Color Definitions");
00311 #if defined(VMDMENU_WINDOW)
00312         o->color(VMDMENU_WINDOW, FL_GRAY);
00313         o->selection_color(VMDMENU_WINDOW);
00314 #endif
00315         //o->hide();
00316         { Fl_Hold_Browser* o = colordefbrowser = new Fl_Hold_Browser(10, 195, 110, 205);
00317           o->labeltype(FL_NO_LABEL);
00318           o->color(VMDMENU_BROWSER_BG, VMDMENU_BROWSER_SEL);
00319           o->callback(colordef_cb, this);
00320           VMDFLTKTOOLTIP(o, "Select color name to adjust RGB color definition")
00321         }
00322         { Fl_Color_Chooser *o = colchooser = new Fl_Color_Chooser(125, 195, 280, 205);
00323           colchooser->rgb(1.0, 1.0, 1.0);
00324           o->callback(colchooser_cb, this);
00325         }
00326         { Fl_Box *o = colchooserbox = new Fl_Box(FL_DOWN_BOX, 410, 195, 55, 205, "");
00327           o->color(fl_rgb_color(255, 255, 255));
00328         }
00329         colchoosedefaultbutton = new Fl_Button(230, 405, 85, 25, "Default");
00330 #if defined(VMDMENU_WINDOW)
00331         colchoosedefaultbutton->color(VMDMENU_WINDOW, FL_GRAY);
00332 #endif
00333         colchoosedefaultbutton->callback(default_cb, this);
00334         VMDFLTKTOOLTIP(colchoosedefaultbutton, "Reset to original RGB color")
00335 #endif
00336 
00337 
00338 #if defined(VMD_USE_VMD_COLORCHOOSER)
00339       { Fl_Group* o = new Fl_Group(0, 20, 475, 425, "Color Definitions");
00340 #if defined(VMDMENU_WINDOW)
00341         o->color(VMDMENU_WINDOW, FL_GRAY);
00342         o->selection_color(VMDMENU_WINDOW);
00343 #endif
00344         { Fl_Hold_Browser* o = colordefbrowser = new Fl_Hold_Browser(15, 195, 135, 120);
00345           o->labeltype(FL_NO_LABEL);
00346           o->color(VMDMENU_BROWSER_BG, VMDMENU_BROWSER_SEL);
00347           o->callback(colordef_cb, this);
00348           VMDFLTKTOOLTIP(o, "Select color name to adjust RGB color definition")
00349         }
00350         { Fl_Value_Slider* o = redscale = new Fl_Value_Slider(160, 195, 300, 20);
00351           o->type(FL_HORIZONTAL);
00352           o->color(VMDMENU_COLOR_RSLIDER);
00353           o->callback(rgb_cb, this);
00354           VMDFLTKTOOLTIP(o, "Adjust slider to change RGB color definition")
00355         }
00356         { Fl_Value_Slider* o = greenscale = new Fl_Value_Slider(160, 215, 300, 20);
00357           o->type(FL_HORIZONTAL);
00358           o->color(VMDMENU_COLOR_GSLIDER);
00359           o->callback(rgb_cb, this);
00360           VMDFLTKTOOLTIP(o, "Adjust slider to change RGB color definition")
00361         }
00362         { Fl_Value_Slider* o = bluescale = new Fl_Value_Slider(160, 235, 300, 20);
00363           o->type(FL_HORIZONTAL);
00364           o->color(VMDMENU_COLOR_BSLIDER);
00365           o->callback(rgb_cb, this);
00366           VMDFLTKTOOLTIP(o, "Adjust slider to change RGB color definition")
00367         }
00368         { Fl_Button* o = grayscalebutton = new Fl_Button(165, 265, 85, 25, "Grayscale");
00369           o->type(FL_TOGGLE_BUTTON);
00370 #if defined(VMDMENU_WINDOW)
00371           o->color(VMDMENU_WINDOW, FL_GRAY);
00372 #endif
00373           VMDFLTKTOOLTIP(o, "Lock sliders for grayscale color")
00374         }
00375         defaultbutton = new Fl_Button(290, 265, 85, 25, "Default");
00376 #if defined(VMDMENU_WINDOW)
00377         defaultbutton->color(VMDMENU_WINDOW, FL_GRAY);
00378 #endif
00379         defaultbutton->callback(default_cb, this);
00380         VMDFLTKTOOLTIP(defaultbutton, "Reset to original RGB color")
00381 #endif
00382 
00383         // color category/name/color browsers common to both code versions
00384         { Fl_Hold_Browser* o = categorybrowser = new Fl_Hold_Browser(10, 75, 125, 100, "Categories");
00385           o->align(FL_ALIGN_TOP);
00386           o->color(VMDMENU_BROWSER_BG, VMDMENU_BROWSER_SEL);
00387           o->callback(category_cb, this);
00388           VMDFLTKTOOLTIP(o, "Select color category then name to set active color")
00389         }
00390         { Fl_Hold_Browser* o = itembrowser = new Fl_Hold_Browser(140, 75, 210, 100, "Names");
00391           o->align(FL_ALIGN_TOP);
00392           o->color(VMDMENU_BROWSER_BG, VMDMENU_BROWSER_SEL);
00393           o->callback(item_cb, this);
00394           VMDFLTKTOOLTIP(o, "Select color category then name to set active color")
00395         }
00396         { Fl_Hold_Browser* o = colorbrowser = new Fl_Hold_Browser(355, 75, 110, 100, "Colors");
00397           o->align(FL_ALIGN_TOP);
00398           o->color(VMDMENU_BROWSER_BG, VMDMENU_BROWSER_SEL);
00399           o->callback(color_cb, this);
00400           VMDFLTKTOOLTIP(o, "Select color category then name to set active color")
00401         }
00402         new Fl_Box(10, 30, 190, 25, "Assign colors to categories:");
00403 
00404         o->end();
00405       }
00406 
00407       { Fl_Group* o = new Fl_Group(0, 20, 475, 475, "Color Scale");
00408 #if defined(VMDMENU_WINDOW)
00409         o->color(VMDMENU_WINDOW, FL_GRAY);
00410         o->selection_color(VMDMENU_WINDOW);
00411 #endif
00412         o->hide();
00413         { Fl_Choice* o = scalemethod = new Fl_Choice(15, 40, 110, 25, "Method");
00414           o->color(VMDMENU_CHOOSER_BG, VMDMENU_CHOOSER_SEL);
00415           o->down_box(FL_BORDER_BOX);
00416           o->align(FL_ALIGN_TOP);
00417           o->callback(scalemethod_cb, this);
00418         }
00419         offsetvalue = new Fl_Value_Slider(200, 25, 265, 20, "Offset");
00420         offsetvalue->type(FL_HORIZONTAL);
00421         offsetvalue->color(VMDMENU_SLIDER_BG, VMDMENU_SLIDER_FG);
00422         offsetvalue->align(FL_ALIGN_LEFT);
00423         offsetvalue->range(-1.0, 1.0);
00424         offsetvalue->callback(scalesettings_cb, this);
00425         { Fl_Value_Slider* o = midpointvalue = new Fl_Value_Slider(200, 55, 265, 20, "Midpoint");
00426           o->type(FL_HORIZONTAL);
00427           midpointvalue->align(FL_ALIGN_LEFT);
00428           midpointvalue->color(VMDMENU_SLIDER_BG, VMDMENU_SLIDER_FG);
00429           o->range(0.0, 1.0);
00430           o->callback(scalesettings_cb, this);
00431         }
00432         { Fl_Toggle_Button *o = scalereversebutton = new Fl_Toggle_Button(15, 85, 110, 25, "Reverse");
00433           o->callback(scalesettings_cb, this);
00434         }
00435         { Fl_Input_Choice *o = scaleposterize = new Fl_Input_Choice(200, 85, 100, 25, "Posterize");
00436           o->add("Off");
00437           o->add("2");
00438           o->add("3");
00439           o->add("4");
00440           o->add("5");
00441           o->add("6");
00442           o->add("7");
00443           o->add("8");
00444           o->add("9");
00445           o->add("10");
00446           o->add("11");
00447           o->add("12");
00448           o->add("13");
00449           o->add("14");
00450           o->add("15");
00451           o->add("16");
00452           o->value("Off");
00453           o->callback(scalesettings_cb, this);
00454         }
00455 
00456 
00457         new Fl_Box(10, 135, 425, 20, "High spatial frequency color scale test grating");
00458         new Fl_Box(435, 155, 30, 20, "10%");
00459         new Fl_Box(435, 220, 30, 20, "5%");
00460         new Fl_Box(435, 285, 30, 20, "0%");
00461         image = new ColorscaleImage(10, 155, 425, 150, 1, app);
00462         new Fl_Box(10, 315, 425, 20, "CIELAB L* perceptual lightness");
00463         scalelumachart = new ColorscaleLumaChart(10, 335, 425, 150, app);
00464         new Fl_Box(435, 345, 30, 20, "100"); // down 10px to 100% line
00465         new Fl_Box(435, 455, 30, 20, "0"); // up 10px to Fl_Chart zero line
00466 
00467         o->end();
00468       }
00469       o->end();
00470     }
00471     end();
00472   }
00473 }
00474 
00475 
00476 ColorFltkMenu::ColorFltkMenu(VMDApp *vmdapp) 
00477 : VMDFltkMenu("color", "Color Controls", vmdapp) {
00478   make_window();
00479 
00480   command_wanted(Command::COLOR_SCALE_METHOD);
00481   command_wanted(Command::COLOR_SCALE_SETTINGS);
00482   command_wanted(Command::COLOR_SCALE_COLORS);
00483   command_wanted(Command::COLOR_CHANGE);
00484   command_wanted(Command::COLOR_NAME);
00485   command_wanted(Command::MOL_RENAME);
00486   command_wanted(Command::COLOR_ADD_ITEM);
00487 
00488   // set up color scale values
00489   for (int j=0; j<vmdapp->num_colorscale_methods(); j++)
00490     scalemethod->add(app->colorscale_method_menuname(j));
00491 
00492   reset_color_categories();
00493   reset_color_names();
00494   reset_color_scale();
00495 }
00496 
00497 void ColorFltkMenu::reset_color_categories() {
00498   categorybrowser->clear();
00499   int n = app->num_color_categories();
00500   for (int j=0; j<n; j++)
00501     categorybrowser->add(app->color_category(j));
00502   categorybrowser->value(0);  //nothing selected
00503 }
00504 
00505 void ColorFltkMenu::reset_color_names() {
00506   colorbrowser->clear();
00507   colordefbrowser->clear();
00508   int n = app->num_regular_colors();
00509   for (int j=0; j<n; j++) {
00510     char buf[128] = { 0 };
00511     sprintf(buf, "%d %s", j, app->color_name(j));
00512     colorbrowser->add(buf);
00513     colordefbrowser->add(buf);
00514   }
00515   colorbrowser->value(0);    // nothing selected
00516   colordefbrowser->value(0); // nothing selected
00517 }
00518 
00519 void ColorFltkMenu::reset_color_scale() {
00520   int idx = app->colorscale_method_current();
00521   const char *menuname = app->colorscale_method_menuname(idx);
00522   set_chooser_from_string(menuname, scalemethod);
00523 
00524   float mid, min, max;
00525   int rev, posterize;
00526   app->colorscale_params(&mid, &min, &max, &rev, &posterize);
00527   offsetvalue->value(min);
00528   midpointvalue->value(mid);
00529   scalereversebutton->value(rev);
00530 
00531   // make controls active/inactive according to
00532   // the type of colorscale that is active
00533   if (app->scene->colorscale_type(idx)) {
00534     offsetvalue->activate();
00535     midpointvalue->activate(); 
00536   } else {
00537     offsetvalue->deactivate();
00538     midpointvalue->deactivate(); 
00539   }
00540 
00541   image->redraw();
00542   scalelumachart->redraw();
00543 }
00544 
00545 void ColorFltkMenu::update_chosen_color() {
00546   int catval = categorybrowser->value();
00547   int itemval = itembrowser->value();
00548   if (!catval || !itemval) {
00549     colordefbrowser->value(0);
00550     return;
00551   }
00552   const char *category = categorybrowser->text(catval);
00553   const char *item = itembrowser->text(itemval);
00554   const char *color = app->color_mapping(category, item);
00555   int index = app->color_index(color);
00556   if (index < 0) {
00557     msgErr << "ColorFltkMenu::update_chosen_color: invalid color" << sendmsg;
00558     return;
00559   }
00560   colorbrowser->value(index+1);
00561   colorbrowser->visible(index+1);
00562   colordefbrowser->value(index+1);
00563   colordefbrowser->visible(index+1);
00564   update_color_definition();
00565 }
00566 
00567 void ColorFltkMenu::update_color_definition() {
00568   float r, g, b;
00569   const char *colorname = app->color_name(colordefbrowser->value()-1);
00570   if (!app->color_value(colorname, &r, &g, &b)) return;
00571 #if defined(VMD_USE_FLTK_COLORCHOOSER)
00572   colchooser->rgb(r, g, b);
00573 #endif
00574 #if defined(VMD_USE_VMD_COLORCHOOSER)
00575   redscale->value(r);
00576   greenscale->value(g);
00577   bluescale->value(b);
00578 #endif
00579 }
00580 
00581 int ColorFltkMenu::act_on_command(int type, Command *) {
00582   switch (type) {
00583     case Command::COLOR_SCALE_METHOD:
00584     case Command::COLOR_SCALE_SETTINGS:
00585     case Command::COLOR_SCALE_COLORS:
00586       reset_color_scale();
00587       break;
00588     case Command::COLOR_CHANGE:
00589       update_color_definition();
00590       break;
00591     case Command::COLOR_NAME:
00592     case Command::MOL_RENAME:
00593       update_chosen_color();
00594       break;
00595     case Command::COLOR_ADD_ITEM:
00596       category_cb(NULL, this);
00597       break;
00598     default:
00599       ;
00600   }
00601   return FALSE;
00602 }
00603 
00604 void ColorFltkMenu::category_cb(Fl_Widget *, void *v) {
00605   ColorFltkMenu *self = (ColorFltkMenu *)v;
00606   int val = self->categorybrowser->value();
00607   if (!val) return;
00608   const char *category = self->categorybrowser->text(val);
00609   int n = self->app->num_color_category_items(category);
00610   self->itembrowser->clear();
00611   for (int i=0; i<n; i++)
00612     self->itembrowser->add(self->app->color_category_item(category, i));
00613   self->itembrowser->value(0);
00614   self->colorbrowser->value(0);
00615 }
00616 
00617 void ColorFltkMenu::item_cb(Fl_Widget *, void *v) {
00618   ColorFltkMenu *self = (ColorFltkMenu *)v;
00619   self->update_chosen_color();
00620 }
00621 
00622 void ColorFltkMenu::color_cb(Fl_Widget *, void *v) {
00623   ColorFltkMenu *self = (ColorFltkMenu *)v;
00624   int catval = self->categorybrowser->value();
00625   int itemval = self->itembrowser->value();
00626   int colorval = self->colorbrowser->value();
00627   if (!catval || !itemval || !colorval) return;
00628   const char *category = self->categorybrowser->text(catval);
00629   const char *item = self->itembrowser->text(itemval);
00630   const char *color = self->app->color_name(colorval-1);
00631   self->app->color_change_name(category, item, color);
00632   self->update_chosen_color();
00633 }
00634 
00635 void ColorFltkMenu::colordef_cb(Fl_Widget *, void *v) {
00636   ColorFltkMenu *self = (ColorFltkMenu *)v;
00637   self->update_color_definition();
00638 }
00639 
00640 
00641 #if defined(VMD_USE_FLTK_COLORCHOOSER)
00642 // callback for FLTK-provided color chooser
00643 void ColorFltkMenu::colchooser_cb(Fl_Widget *w, void *v) {
00644   ColorFltkMenu *self = (ColorFltkMenu *)v;
00645 
00646   float r, g, b;
00647   r = (float)self->colchooser->r();
00648   g = (float)self->colchooser->g();
00649   b = (float)self->colchooser->b();
00650   self->colchooserbox->color(fl_rgb_color(uchar(255*r), 
00651                                           uchar(255*g), 
00652                                           uchar(255*b)));
00653   self->colchooserbox->redraw();
00654 
00655   int val = self->colordefbrowser->value();
00656   if (!val) return; // don't proceed further unless a color item is selected
00657 
00658   const char *color = self->colordefbrowser->text(val);
00659   self->app->color_change_rgb(color, r, g, b);
00660 }
00661 #endif
00662 
00663 
00664 #if defined(VMD_USE_VMD_COLORCHOOSER)
00665 // callback for classic VMD color sliders
00666 void ColorFltkMenu::rgb_cb(Fl_Widget *w, void *v) {
00667   ColorFltkMenu *self = (ColorFltkMenu *)v;
00668   int val = self->colordefbrowser->value();
00669   if (!val) return;
00670   const char *color = self->colordefbrowser->text(val);
00671   float r, g, b;
00672   if (self->grayscalebutton->value()) {
00673     r = g = b = (float)((Fl_Value_Slider *)w)->value();
00674   } else {
00675     r = (float)self->redscale->value();
00676     g = (float)self->greenscale->value();
00677     b = (float)self->bluescale->value();
00678   }
00679   self->app->color_change_rgb(color, r, g, b);
00680 }
00681 #endif
00682 
00683 
00684 void ColorFltkMenu::default_cb(Fl_Widget *, void *v) {
00685   ColorFltkMenu *self = (ColorFltkMenu *)v;
00686   int val = self->colordefbrowser->value();
00687   if (!val) return;
00688   const char *color = self->colordefbrowser->text(val);
00689   float r, g, b;
00690   if (!self->app->color_default_value(color, &r, &g, &b)) {
00691     msgErr << "ColorFltkMenu::default_cb(): invalid color" << sendmsg;
00692     return;
00693   }
00694   self->app->color_change_rgb(color, r, g, b);
00695 }
00696 
00697 void ColorFltkMenu::scalemethod_cb(Fl_Widget *w, void *v) {
00698   ColorFltkMenu *self = (ColorFltkMenu *)v;
00699   Fl_Choice *choice = (Fl_Choice *)w;
00700 
00701   int idx = choice->value();
00702   const char *mn = choice->text();
00703 
00704   //
00705   // Find the index of a string that matches the name of the given menu
00706   // item.  XXX Only checks leaf node menu names, not full pathnames currently
00707   //
00708   // FLTK 1.1.4
00709   int i, strindex;
00710   int num = self->app->num_colorscale_methods();
00711   for (strindex=-1, i=0; i < num; i++) {
00712     // find leaf menu name from full menu path
00713     const char *colstr;
00714     if ((colstr = strrchr(self->app->colorscale_method_menuname(i), '/')) == NULL)
00715       colstr = self->app->colorscale_method_menuname(i);
00716     else
00717       colstr++;
00718 
00719     // compare leaf submenu item name against left color mode name
00720     if (!strcmp(colstr, mn)) {
00721       strindex=i;
00722       break;
00723     }
00724   }
00725   idx = strindex;
00726 
00727   self->app->colorscale_setmethod(idx);
00728 }
00729 
00730 void ColorFltkMenu::scalesettings_cb(Fl_Widget *, void *v) {
00731   ColorFltkMenu *self = (ColorFltkMenu *)v;
00732   float mid, min, max;
00733   int rev, posterize;
00734   self->app->colorscale_params(&mid, &min, &max, &rev, &posterize);
00735   mid = (float)self->midpointvalue->value();
00736   min = (float)self->offsetvalue->value();
00737   rev = self->scalereversebutton->value();
00738   const char *posterizestr = self->scaleposterize->value();
00739   posterize = 0;
00740   if (!strupcmp(posterizestr, "off")) {
00741     posterize = 0;
00742   } else {
00743     if (sscanf(posterizestr, "%d", &posterize) != 1) {
00744       posterize = 0;
00745     }
00746   }
00747 
00748   self->app->colorscale_setparams(mid, min, max, rev, posterize);
00749 }
00750 
00751 
00752 

Generated on Wed Apr 17 02:45:06 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002