RoundNumberBox

part of wslib



a Pen-based replacement for SCNumberBox, with extra styling options. 



RoundNumberBox works the same way as a NumberBox. But, as the name states, it has rounded edges. It also features a lot of extra functionality and styling options.


One of the extra features is the possibility to enter expressions into the box. These are automatically interpreted after hitting the enter key.


(

w = Window("RoundNumberBox Example", Rect(100, 500, 400, 120)).front;

b = RoundNumberBox(w, Rect(150, 10, 100, 20));

b.value = rrand(1,15);

b.action = {arg numb; numb.value.postln; };

)


(

f = { |keyStroke| // this function acts as if typing a string

w.front; b.focus;

{

keyStroke.do({ |char|

b.keyDown( char, 0 );

0.25.wait;

});

0.5.wait;

b.keyDown($\n, 0 );

}.fork;

};

)


f.( "1+1" );

f.( "100*2" );

f.( "(5+1)**2" );


The behaviour can be customized using the interpretFunc and allowedChars variables. 

The default interpretFunc is:    { |string| string.interpret } 

The default allowedChars are:    "+-.eE*/()%"

Any typed char that is not in the allowedChars string will not show up in the box. The interpretFunc should usually return a Number, which is to be displayed in the numberbox. If the function returns nil the old value is kept. The interpretFunc allows for alternate interpretations of the entered data. For example it could detect unit types:


( // first run the example above

b.interpretFunc = { |string|

var ext;

ext = string.find( "dB" );

if( ext.notNil )

{ string[..ext-1].interpret  }

{ string.interpret.ampdb };

};

b.allowedChars = "+-.eE*/()% dB";

)


f.( "0.1" ); // regular values are now converted to dB's

f.( "0 dB" ); // trailing "dB" signs will be interpreted as straight dB's

f.( "-6 dB" );

f.( "0" );

f.( "1" );



The counterpart of this is the formatFunc. This is the function used to show the value in the numberbox. An example to add to the above would be the following:


// first run the examples above

b.formatFunc = { |value| value.round(0.001).asString + "dB"; };


Another feature of RoundNumberBox is the charSelectIndex. This gives the ability to show a selection rectangle behind one of the characters displayed in the box. The example shows how this feature can be used:


(

w = Window("click a number and start dragging", Rect(100, 500, 400, 120)).front;

b = RoundNumberBox(w, Rect(150, 10, 70, 20));

b.clipLo_(-999).clipHi_(1000).align_( \right );

b.formatFunc_({ |value|value.asStringWithFrac(4).preExtend(9, $  ); }); // fixed width string

c = [ 1000, 100, 10, 1, 0, 0.1, 0.01, 0.001, 0.0001 ]; // stepsizes


// mouse support

b.mouseDownAction = { |vw, x, y|

vw.charSelectIndex = vw.charIndexFromPoint( x@y, [4] );

vw.scroll_step = c[vw.charSelectIndex] ? 1;

vw.step = vw.scroll_step;

};


// arrow keys left/right to select char, up/down to change value

b.keyDownAction = { |vw, char, mod, unicode|

var res;

res = case { unicode == 16rF703 }

{ vw.charSelectIndex = (vw.charSelectIndex + 1).min(8); nil }

{ unicode == 16rF702 }

{ vw.charSelectIndex = (vw.charSelectIndex - 1).max(-1); nil }

{ true }

{ vw.keyDown( char, mod, unicode ); };

vw.step = c[vw.charSelectIndex] ? 1;

res;

};

)


Creation / Class Methods


*new (parent, bounds)

parent - The parent view.

bounds - An instance of Rect, or a Point indicating width@height.

(

w = Window("RoundNumberBox Example", Rect(100, 500, 400, 120));

b = RoundNumberBox(w, Rect(150, 10, 100, 20));

b.value = rrand(1,15);

b.action = {arg numb; numb.value.postln; };

w.front

)

Check the SCNumberBox helpfile for more examples and variable descriptions