FXGradientBar

The new FXGradientBar widget is used to build color gradient ramps (e.g. for OpenGL textures). It allows for drag and drop of colors, various color blending features ranging from linear to quadratic, and furthermore horizonal or vertical orientation. An example of this, from the image.cpp test program, is shown below.

The FXGradientBar is based on the GIMP's gradient editor, and so that's probably your best source for getting a feel for how they work. A gradient consists of a number of segments, and each segment is described by an FXGradient struct:

struct FXGradient {
  FXdouble lower;                     /// Lower value
  FXdouble middle;                    /// Middle value
  FXdouble upper;                     /// Upper value
  FXColor  lowerColor;                /// Lower color
  FXColor  upperColor;                /// Upper color
  FXuchar  blend;                     /// Blend method
  };

If you look at the snapshot of an FXGradientBar (shown above), the lower and upper values of each segment are marked by the black triangles while the middle value is marked by a white triangle. You also need to specify the colors at the lower and upper bounds of each segment. Finally, each segment has an associated blend mode, one of GRADIENT_BLEND_LINEAR, GRADIENT_BLEND_POWER, GRADIENT_BLEND_SINE, GRADIENT_BLEND_INCREASING or GRADIENT_BLEND_DECREASING. According to the GIMP manual, these blending modes are:

To actually get a gradient of FXColor values based on an FXGradientBar, you need to call the gradient bar's gradient member function. The arguments to this function are an array of FXColor values and the size of the array. On return from the gradient() function, your color array will have been filled with FXColor values based on the gradient settings.

When a new segment (or range of segments) in the gradient bar is selected, the gradient bar will send a SEL_SELECTED message to its message target. Similarly, when a segment (or range of segments) is deselected, FXGradientBar sends SEL_DESELECTED to its message target. To determine which segment(s) of the gradient bar are currently selected, you can loop over the segments using the getNumSegments() and isSegmentSelected() member functions, e.g.

for (FXint seg=0; seg < gradientBar->getNumSegments(); seg++) {
  if (gradientBar->isSegmentSelected(seg)) {
    // do something
  }
}

When the current segment changes (e.g. because the user clicks on a new segment), FXGradientBar sends a SEL_CHANGED message to its message target. For this case, the message data sent with the message will be non-NULL, and can be cast to an integer that indicates the new current item, e.g.

long TargetObject::onGradientBarChanged(FXObject* sender, FXSelector sel, void* ptr) {
  FXint current;
  if (ptr != 0) {
    current = static_cast<FXint>(reinterpret_cast<FXival>(ptr)); 
  }
  return 1;
}

However, the FXGradientBar also sends SEL_CHANGED to its message target in a number of other circumstances, e.g. when the lower, middle or upper value of a gradient segment changes. For all of these additional cases, the message data sent with the SEL_CHANGED message is NULL.