Mixer: Enable keyboard value input and mouse value dragging on slider controls.

This commit is contained in:
Jonathan Moore Liles 2013-09-18 23:28:58 -07:00
parent 47f15d9937
commit b7b3d499e5
4 changed files with 285 additions and 64 deletions

View File

@ -24,24 +24,76 @@
#include <FL/fl_draw.H> #include <FL/fl_draw.H>
#include <math.h> #include <math.h>
void Fl_Value_SliderX::input_cb(Fl_Widget*, void* v) {
Fl_Value_SliderX& t = *(Fl_Value_SliderX*)v;
double nv;
if ((t.step() - floor(t.step()))>0.0 || t.step() == 0.0)
nv = strtod(t.input.value(), 0);
else
nv = strtol(t.input.value(), 0, 0);
if (nv != t.value() || t.when() & FL_WHEN_NOT_CHANGED) {
if ( ! t.soft())
nv = t.clamp(nv);
t.set_value(nv);
t.set_changed();
if (t.when())
{
t.value_damage();
t.do_callback();
}
}
}
void Fl_Value_SliderX::value_damage() {
char buf[128];
format(buf);
input.value(buf);
input.mark(input.position()); // turn off selection highlight
redraw();
}
Fl_Value_SliderX::~Fl_Value_SliderX ( void )
{
if (input.parent() == (Fl_Group *)this)
input.parent(0); // *revert* ctor kludge!
}
/** /**
Creates a new Fl_Value_SliderX widget using the given Creates a new Fl_Value_SliderX widget using the given
position, size, and label string. The default boxtype is FL_DOWN_BOX. position, size, and label string. The default boxtype is FL_DOWN_BOX.
*/ */
Fl_Value_SliderX::Fl_Value_SliderX(int X, int Y, int W, int H, const char*l) Fl_Value_SliderX::Fl_Value_SliderX(int X, int Y, int W, int H, const char*l)
: Fl_SliderX(X,Y,W,H,l) { : Fl_SliderX(X,Y,W,H,l),input(X, Y, W, H, 0) {
step(1,100); step(1,100);
textfont_ = FL_HELVETICA;
textsize_ = 10; soft_ = 0;
textcolor_ = FL_FOREGROUND_COLOR; if (input.parent()) // defeat automatic-add
input.parent()->remove(input);
input.parent((Fl_Group *)this); // kludge!
input.callback(input_cb, this);
input.when(FL_WHEN_ENTER_KEY);
box(input.box());
color(input.color());
selection_color(input.selection_color());
align(FL_ALIGN_LEFT);
value_damage();
textsize(9);
set_flag(SHORTCUT_LABEL);
} }
void Fl_Value_SliderX::draw() { void Fl_Value_SliderX::draw() {
int sxx = x(), syy = y(), sww = w(), shh = h(); int sxx = x(), syy = y(), sww = w(), shh = h();
int bxx = x(), byy = y(), bww = w(), bhh = h(); int bxx = x(), byy = y(), bww = w(), bhh = h();
if (horizontal()) { if (horizontal()) {
input.resize(x(), y(), 35, h());
bww = 35; sxx += 35; sww -= 35; bww = 35; sxx += 35; sww -= 35;
} else { } else {
input.resize(x(), y(), w(), 25 );
syy += 25; bhh = 25; shh -= 25; syy += 25; bhh = 25; shh -= 25;
} }
if (damage()&FL_DAMAGE_ALL) draw_box(box(),sxx,syy,sww,shh,color()); if (damage()&FL_DAMAGE_ALL) draw_box(box(),sxx,syy,sww,shh,color());
@ -50,11 +102,12 @@ void Fl_Value_SliderX::draw() {
sww-Fl::box_dw(box()), sww-Fl::box_dw(box()),
shh-Fl::box_dh(box())); shh-Fl::box_dh(box()));
draw_box(box(),bxx,byy,bww,bhh,color()); draw_box(box(),bxx,byy,bww,bhh,color());
char buf[128];
format(buf); if (damage()&~FL_DAMAGE_CHILD) input.clear_damage(FL_DAMAGE_ALL);
fl_font(textfont(), textsize()); input.box(box());
fl_color(active_r() ? textcolor() : fl_inactive(textcolor())); input.color(color(), selection_color());
fl_draw(buf, bxx, byy, bww, bhh, FL_ALIGN_CLIP); Fl_Widget *i = &input; i->draw(); // calls protected input.draw()
input.clear_damage();
} }
int Fl_Value_SliderX::handle(int event) { int Fl_Value_SliderX::handle(int event) {
@ -62,16 +115,117 @@ int Fl_Value_SliderX::handle(int event) {
Fl::focus(this); Fl::focus(this);
redraw(); redraw();
} }
int sxx = x(), syy = y(), sww = w(), shh = h(); int sxx = x(), syy = y(), sww = w(), shh = h();
if (horizontal()) { if (horizontal()) {
sxx += 35; sww -= 35; sxx += 35; sww -= 35;
} else { } else {
syy += 25; shh -= 25; syy += 25; shh -= 25;
} }
return Fl_SliderX::handle(event,
double v;
int delta;
int mx = Fl::event_x_root();
static int ix, drag;
// input.when(when());
switch (event) {
case FL_ENTER:
return 1;
case FL_LEAVE:
if ( ! drag )
fl_cursor( FL_CURSOR_DEFAULT );
return 1;
case FL_MOVE:
if ( drag || Fl::event_inside( &input ) )
fl_cursor( FL_CURSOR_WE );
else
fl_cursor( FL_CURSOR_DEFAULT );
return 1;
case FL_PUSH:
// if (!step()) goto DEFAULT;
if ( Fl::event_inside(&input) )
{
input.handle(event);
ix = mx;
drag = Fl::event_button();
handle_push();
return 1;
}
goto DEFAULT;
break;
case FL_DRAG:
if ( ! drag )
goto DEFAULT;
fl_cursor( FL_CURSOR_WE );
// if (!step()) goto DEFAULT;
delta = mx-ix;
if (delta > 5) delta -= 5;
else if (delta < -5) delta += 5;
else delta = 0;
switch (drag) {
case 3: v = increment(previous_value(), delta*100); break;
case 2: v = increment(previous_value(), delta*10); break;
default:v = increment(previous_value(), delta); break;
}
// v = previous_value() + delta * ( fabs( maximum() - minimum() ) * 0.001 );
v = round(v);
v = soft()?softclamp(v):clamp(v);
handle_drag(v);
value_damage();
return 1;
case FL_RELEASE:
if ( ! drag )
goto DEFAULT;
// if (!step()) goto DEFAULT;
if (value() != previous_value() || !Fl::event_is_click())
handle_release();
drag = 0;
fl_cursor( FL_CURSOR_DEFAULT );
/* else { */
/* Fl_Widget_Tracker wp(&input); */
/* input.handle(FL_PUSH); */
/* if (wp.exists()) */
/* input.handle(FL_RELEASE); */
/* } */
return 1;
case FL_FOCUS:
return input.take_focus();
case FL_UNFOCUS:
{
input_cb(&input,this);
return 1;
}
case FL_SHORTCUT:
return input.handle(event);
}
DEFAULT:
int r = Fl_SliderX::handle(event,
sxx+Fl::box_dx(box()), sxx+Fl::box_dx(box()),
syy+Fl::box_dy(box()), syy+Fl::box_dy(box()),
sww-Fl::box_dw(box()), sww-Fl::box_dw(box()),
shh-Fl::box_dh(box())); shh-Fl::box_dh(box()));
if ( r )
{
return r;
}
else
{
input.type(((step() - floor(step()))>0.0 || step() == 0.0) ? FL_FLOAT_INPUT : FL_INT_INPUT);
return input.handle(event);
}
} }

View File

@ -21,6 +21,7 @@
#define Fl_Value_SliderX_H #define Fl_Value_SliderX_H
#include "Fl_SliderX.H" #include "Fl_SliderX.H"
#include <FL/Fl_Input.H>
/** /**
The Fl_Value_SliderX widget is a Fl_SliderX widget The Fl_Value_SliderX widget is a Fl_SliderX widget
@ -29,26 +30,70 @@
\image latex value_slider.png "Fl_Value_SliderX" width=4cm \image latex value_slider.png "Fl_Value_SliderX" width=4cm
*/ */
class FL_EXPORT Fl_Value_SliderX : public Fl_SliderX { class FL_EXPORT Fl_Value_SliderX : public Fl_SliderX {
Fl_Font textfont_; /* This is the encapsulated Fl_input attribute to which
Fl_Fontsize textsize_; this class delegates the value font, color and shortcut */
Fl_Color textcolor_; Fl_Input input;
private:
char soft_;
static void input_cb(Fl_Widget*,void*);
virtual void value_damage(); // cause damage() due to value() changing
protected: protected:
void draw(); void draw();
public: public:
int handle(int); int handle(int);
Fl_Value_SliderX(int x,int y,int w,int h, const char *l = 0); Fl_Value_SliderX(int x,int y,int w,int h, const char *l = 0);
virtual ~Fl_Value_SliderX ( );
/** See void Fl_Value_Input::soft(char s) */
void soft(char s) {soft_ = s;}
/**
If "soft" is turned on, the user is allowed to drag
the value outside the range. If they drag the value to one of
the ends, let go, then grab again and continue to drag, they can
get to any value. The default is true.
*/
char soft() const {return soft_;}
/**
Returns the current shortcut key for the Input.
\see Fl_Value_Input::shortcut(int)
*/
int shortcut() const {return input.shortcut();}
/**
Sets the shortcut key to \p s. Setting this
overrides the use of '&' in the label(). The value is a bitwise
OR of a key and a set of shift flags, for example FL_ALT | 'a'
, FL_ALT | (FL_F + 10), or just 'a'. A value
of 0 disables the shortcut.
The key can be any value returned by
Fl::event_key(), but will usually be an ASCII letter. Use
a lower-case letter unless you require the shift key to be held down.
The shift flags can be any set of values accepted by
Fl::event_state(). If the bit is on that shift key must
be pushed. Meta, Alt, Ctrl, and Shift must be off if they are not in
the shift flags (zero for the other bits indicates a "don't care"
setting).
*/
void shortcut(int s) {input.shortcut(s);}
/** Gets the typeface of the text in the value box. */ /** Gets the typeface of the text in the value box. */
Fl_Font textfont() const {return textfont_;} Fl_Font textfont() const {return input.textfont();}
/** Sets the typeface of the text in the value box. */ /** Sets the typeface of the text in the value box. */
void textfont(Fl_Font s) {textfont_ = s;} void textfont(Fl_Font s) {input.textfont(s);}
/** Gets the size of the text in the value box. */ /** Gets the size of the text in the value box. */
Fl_Fontsize textsize() const {return textsize_;} Fl_Fontsize textsize() const {return input.textsize();}
/** Sets the size of the text in the value box. */ /** Sets the size of the text in the value box. */
void textsize(Fl_Fontsize s) {textsize_ = s;} void textsize(Fl_Fontsize s) {input.textsize(s);}
/** Gets the color of the text in the value box. */ /** Gets the color of the text in the value box. */
Fl_Color textcolor() const {return textcolor_;} Fl_Color textcolor() const {return input.textcolor();}
/** Sets the color of the text in the value box.*/ /** Sets the color of the text in the value box.*/
void textcolor(Fl_Color s) {textcolor_ = s;} void textcolor(Fl_Color n) {input.textcolor(n);}
/** Gets the color of the text cursor. The text cursor is black by default. */
Fl_Color cursor_color() const {return input.cursor_color();}
/** Sets the color of the text cursor. The text cursor is black by default. */
void cursor_color(Fl_Color n) {input.cursor_color(n);}
}; };
#endif #endif

View File

@ -467,6 +467,8 @@ Controller_Module::connect_to ( Port *p )
} }
} }
o->precision(2);
o->value( p->control_value() ); o->value( p->control_value() );
_type = SLIDER; _type = SLIDER;
@ -813,9 +815,8 @@ Controller_Module::menu ( void )
void void
Controller_Module::draw ( void ) Controller_Module::draw ( void )
{ {
draw_box(x(),y(),w(),h());
Fl_Group::draw(); Fl_Group::draw();
draw_box(x(),y(),w(),h());
if ( learn_mode() ) if ( learn_mode() )
{ {

View File

@ -249,12 +249,22 @@ Module_Parameter_Editor::make_controls ( void )
o->align(FL_ALIGN_TOP); o->align(FL_ALIGN_TOP);
o->box( FL_DOWN_BOX ); o->box( FL_DOWN_BOX );
o->precision( 2 );
/* a couple of plugins have ridiculously small units */ /* a couple of plugins have ridiculously small units */
if ( p->hints.maximum < 0.5f ) float r = fabs( p->hints.maximum - p->hints.minimum );
o->precision( 5 );
if ( r <= 0.01f )
o->precision( 4 );
else if ( r <= 0.1f )
o->precision( 3 );
else if ( r <= 100.0f )
o->precision( 2 );
else if ( r <= 5000.0f )
o->precision( 1 );
/* else if ( r <= 10000.0f ) */
/* o->precision( 1 ); */
else
o->precision( 0 );
// o->step( fabs( ( o->maximum() - o->minimum() ) ) / 32.0f );
} }
else else
{ {
@ -285,10 +295,21 @@ Module_Parameter_Editor::make_controls ( void )
o->minimum( p->hints.maximum ); o->minimum( p->hints.maximum );
} }
o->precision( 2 );
/* a couple of plugins have ridiculously small units */ /* a couple of plugins have ridiculously small units */
if ( p->hints.maximum < 0.5f ) float r = fabs( p->hints.maximum - p->hints.minimum );
o->precision( 5 );
if ( r <= 0.01f )
o->precision( 4 );
else if ( r <= 0.1f )
o->precision( 3 );
else if ( r <= 100.0f )
o->precision( 2 );
else if ( r <= 5000.0f )
o->precision( 1 );
/* else if ( r <= 10000.0f ) */
/* o->precision( 1 ); */
else
o->precision( 0 );
o->textsize( 8 ); o->textsize( 8 );
// o->box( FL_NO_BOX ); // o->box( FL_NO_BOX );