DO NOT REPLY TO THIS MESSAGE.  INSTEAD, POST ANY RESPONSES TO THE LINK BELOW.

[STR New]

Link: http://www.fltk.org/str.php?L2951
Version: 1.4-feature


I have an application with a colour bar type legend which does not give
the required resolution, so I needed to be able to adjust the low and
high values in an intuitive but minimally invasive way on screen.

I hacked together the following demonstrator, drawing some inspiration
from Fl_Slider. The features I required were:
- a vertical slider
- possibility of setting min and max values of continuous range (no step)
- possibility to move low and high sliders (min <= low < high <= max)

I then hacked it further to fit directly with the rest of my application.

Questions:
1. Does anybody know of a similar widget out there?
2. Is it worth factoring out a separate DoubleValuator base class?
3. Apart from vertical/horizontal what other features are needed?
4. Does it require min/low/high/max fields?
5. Would a floating tooltip with feedback be enough? (eg Greg's TipWin)

I'd be willing to have a go a this, but can't provide any timeframes.


Link: http://www.fltk.org/str.php?L2951
Version: 1.4-feature
// test program to demonstrate DoubleSlider concept
//
// compile using 'fltk-config --compile filename.cxx'

#include <FL/Fl.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Window.H>
#include <FL/fl_draw.H>

// Double slider widget:
// program sets min and max values, and then user can move sliders
// to reduce the high and low values within this range.
//
class DoubleSlider : public Fl_Box
{
    // everything is public as this is just a proof-of-concept
public:
    int loPos, hiPos;   // pixel position of top of low and high sliders
    int top, bottom;    // pixel position of top and bottom of range
    int clickOffset;    // difference between top of slider and mouse
    bool loClicked, hiClicked;  // which slider has been selected
    double lolo, lo, hi, hihi;  // min, low, high and max values

    DoubleSlider(int X, int Y, int W, int H, char* T=0)
    : Fl_Box(X, Y, W, H, T)
    {
        box(FL_DOWN_BOX);
        lolo = lo = 0.0;
        hihi = hi = 1.0;
        loClicked = false;
        hiClicked = false;
        clickOffset = 0;
        top = Y;
        bottom = Y + H;
        hiPos = Y;
        loPos = Y + H - W;
    }
    
    ~DoubleSlider()
    {
    }
          
    // draw within the interior of the box
    //
    void draw(int X, int Y, int W, int H)
    {
        int upper = top + Fl::box_dy(box());
        int lower = bottom - Fl::box_dy(box());
        
        // calculate widget positions of sliders
        hiPos = upper + ((lower-upper - W) * (hihi - hi) / (hihi - lolo));
        loPos = upper + ((lower-upper - W) * (hihi - lo) / (hihi - lolo));
        
        // draw background line linking sliders
        Fl_Color black = active_r() ? FL_FOREGROUND_COLOR : FL_INACTIVE_COLOR;
        draw_box(FL_THIN_DOWN_BOX, X+W/2-2, hiPos+W/2, 4, loPos-hiPos, black);

        // draw sliders
        fl_draw_box(FL_UP_BOX, X, hiPos, W, W, selection_color());
        fl_draw_box(FL_UP_BOX, X, loPos, W, W, selection_color());
        
        // add the lines across the middle of the sliders
        int xi = X + Fl::box_dx(FL_UP_BOX);
        int wi = W - Fl::box_dw(FL_UP_BOX);
        fl_color(fl_darker(selection_color()));
        fl_rectf(xi, hiPos+W/2-1, wi, 3);
        fl_rectf(xi, loPos+W/2-1, wi, 3);
    }
    
    void draw()
    {
        if (damage() & FL_DAMAGE_ALL)
        {
            draw_box(FL_FLAT_BOX, selection_color());
            draw_box(box(), x(), top, w(), bottom-top, selection_color());
        }
        
        draw(   x() + Fl::box_dx(box()),
                top + Fl::box_dy(box()),
                w() - Fl::box_dw(box()),
                bottom- top - Fl::box_dh(box()));
    }

    int onPush(int X, int Y, int W, int H, int mX, int mY)
    {
        if (X < mX && mX < X+W && hiPos < mY && mY < hiPos+W)
        {
            loClicked = false;
            hiClicked = true;
            clickOffset = mY - hiPos;
            return 1;
        }
        if (X < mX && mX < X+W && loPos < mY && mY < loPos+W)
        {
            loClicked = true;
            hiClicked = false;
            clickOffset = mY - loPos;
            return 1;
        }
        loClicked = false;
        hiClicked = false;
        clickOffset = 0; 
        return 0;
    }
    
    int onDrag(int X, int Y, int W, int H, int mX, int mY)
    {
        int upper = top + Fl::box_dy(box());
        int lower = bottom - Fl::box_dy(box());
        double value;
        
        mY = mY - clickOffset;
        if (hiClicked == true)
        {
            mY = (mY > upper) ? mY : upper;
            mY = (mY < loPos-W) ? mY : loPos-W;
            value = lolo + (lower-W - mY) * (hihi - lolo) / (lower-W - upper);
            if (value != hi)
            {
                hi = value;
                redraw();
            }
            return 1;
        }
        if (loClicked == true)
        {
            mY = (mY > hiPos+W) ? mY : hiPos+W;
            mY = (mY < lower-W) ? mY : lower-W;
            value = lolo + (lower-W - mY) * (hihi - lolo) / (lower-W - upper);
            if (value != lo)
            {
                lo = value;
                redraw();
            }
            return 1;
        }     
        return 0;
    }
    
    int onRelease(int X, int Y, int W, int H, int mX, int mY)
    {
        return 1;
    }
    
    int handle(int event, int X, int Y, int W, int H)
    {
        switch(event)
        {
            case FL_PUSH:
                return onPush(X, Y, W, H, Fl::event_x(), Fl::event_y());
                break;
            case FL_DRAG:
                return onDrag(X, Y, W, H, Fl::event_x(), Fl::event_y());
                break;
            case FL_RELEASE:
                return onRelease(X, Y, W, H, Fl::event_x(), Fl::event_y());
                break;                
        }
        return Fl_Box::handle(event);
    }
    
    int handle(int event)
    {
        return handle( event,
                x() + Fl::box_dx(box()),
                y() + Fl::box_dy(box()),
                w() - Fl::box_dw(box()),
                h() - Fl::box_dh(box()));
    }
};

int main(int argc, char* argv[])
{
    Fl_Window* w = new Fl_Window(200, 200);

    DoubleSlider* ds = new DoubleSlider(10, 10, 20, 180);
    ds->lo = 0.25;
    ds->hi = 0.75;
    ds->top += 50;
    
    w->end();
    
    w->show(argc, argv);
    return Fl::run();
}
_______________________________________________
fltk-dev mailing list
fltk-dev@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk-dev

Reply via email to