ScaledUserView
part of wslib
a SCUserView adaptation which supports scaling and translation of it's drawFunc
also see: ScaledUserViewWindow
Creation
ScaledUserView ( window, bounds, fromBounds )
the window and bounds work the same way as in every SCView.
fromBounds : (also an instance variable) the drawFunc of this userView is scaled and translated
internally in such a way that the fromBounds rect fills the bounds. If no fromBounds are specified
ScaledUserView used the bounds for this instead, and thus doesn't scale anything.
(
// resize the window and see what happens
w = Window( "ScaledUserView" ).front;
b = ScaledUserView( w, w.view.bounds.insetBy( 10, 10 ), Rect(0,0,1,1) );
b.drawFunc = { Pen.line( 0.1@0.1, 0.9@0.9 ).stroke; };
b.view.resize = 5;
)
The Pen:width is set by ScaledUserView internally to correspond with 1 px in the view. To change this you can specify your own width:
b.drawFunc = { Pen.width = 0.05; Pen.line( 0.1@0.1, 0.9@0.9 ).stroke; };
Methods and variables
scaleH, scaleV
sets and gets the relative scaling of the drawFunc (default 1)
b.scaleH;
b.scaleH = 2;
b.scaleV = 0.5;
moveH, moveV
sets and gets the relative moving of the drawFunc (default 0.5).
This depends on the scaling. If the scaling is 1, moveH and moveV are not visible.
A moveH value of 0.5 means that the scaled func is centered in the view.
A moveH value of 1 means that the right side of the fromBounds is the same as the right side of the view
A moveH value of 0 means that the left side of the fromBounds is the same as that of the view
same goes for moveV
b.moveH;
b.scaleH = 2; b.moveH = 1; // zoomed H x 2 and scrolled to the outer right side
b.moveH = 0; // scrolled to the outer left side
b.moveH = 0.5; // scrolled to the center
scale, scale_ ( newScaleArray )
move, move_ ( newMoveArray )
the newScaleArray can be an Array, but also a number (for both H and V) or a Point
b.scale = [0.75, 0.5 ];
b.scale = 1.5@1;
b.scale = 1; b.move = 0.5; // back to normal
reset
resets scale and move to defaults.
clip
sets and gets clipping boolean for he drawFunc (default true).
If clip is true the path will be clipped to inside the view.
Depricated (all functions are clipped inside the view now)
b.scale = 2; b.clip = false;
b.clip = true;
b.reset;
autoRefresh
sets and gets the autoRefresh boolean (default true).
Auto refresh works for all the above methods and setters.
b.autoRefresh = false;
b.scale = 0.5;
b.refresh;
b.autoRefresh = true;
b.scale = [-0.5, 0.5]; // yes, you can also use negative values for scale
You can bypass it for each setter individually with it's refreshFlag argument (always the last argument)
b.scale_( 1.1, refreshFlag: false );
b.refresh;
view
holds the SCUserView on which this class is based
background
gets and sets the background color
*window
Creates an ScaledUserViewWindow instead
ScaledUserView.window;
drawFuncs
Next to the drawFunc, as used in the above examples, there are several other drawing functions. They can be used simultaniously.
unscaledDrawFunc
this drawFunc is not scaled or moved, except from that it is translated in such a way that Point(0,0) inside this func resembles the topLeft corner of the view. The func is drawn on top of the scaled drawFunc.
b.unscaledDrawFunc = { Pen.width = 2; Color.blue(0.5).set; Pen.line( 300@10, 10@300 ).stroke; };
// resize the window to see the difference
unclippedUnscaledDrawFunc
Same as above, but also not clipped. This draws yet on top of the other two
b.unclippedUnscaledDrawFunc = { Color.red(0.5).set; Pen.line( 200@(-10), 200@500 ).stroke; };
all drawFuncs receive the ScaledUserView itself as firsst argument. From there you can also request the current move and scale settings. But there is a more convenient way of using scaled data inside the unscaled functions:
translateScale ( item )
returns a scaled and translated version of the item. The item can be a Point, a Rect, an array containing Points and Rects, or Pen.
Points and Rects will be scaled and translated according to the settings of the ScaledUserView.
Pen will perform the correct Pen.scale and Pen.translate methods.
(
b.unscaledDrawFunc = { |view|
var points, scaledPoints;
points = [ 0.1@0.1, 0.9@0.1, 0.2@0.5 ];
scaledPoints = view.translateScale( points );
Pen.width = 5;
Color.blue.set;
Pen.moveTo( scaledPoints[0] );
scaledPoints[1..].do({ |point| Pen.lineTo( point ) });
Pen.stroke;
};
)
convertFwd ( x, y ), convertBwd ( x, y )
this converts unscaled x,y values to and back from scaled values
beforeDrawFunc
the beforeDrawFunc is called before any other of the drawFuncs are called at refresh. Use this if you need to calculate values before the other drawFuncs are called.
clearDrawFuncs
removes all drawFuncs
mouseActions
the ScaledUserView uses the same mouseAction types as regular SCViews:
mouseDownAction, mouseMoveAction and mouseUpAction
The arguments they get are different though:
arg view, scaledX, scaledY, modifier, x, y, isInside
view : the ScaledUserView ( as in the drawFuncs )
scaledX, scaledY : the x/y coordinates, scaled according to the view's settings
modifier : binary code of the current modifier key
x, y : the unscaled x/y coordinates, relative to the view's leftTop corner
isInside : a boolean stating wether the mouse is still inside the bounds of the view
the view is automatically refreshed, unless autoRefreshMouseActions is set to false.
(
b.mouseMoveAction = { |v, sx, sy, m, x, y, inside|
[ sx@sy, x@y, inside ].postln;
};
)
/// move a point around
(
b.clearDrawFuncs;
p = 0.5@0.5;
b.drawFunc = { Color.green(0.5).alpha_(0.75).set; Pen.addArc( p, 0.05, 0, 2pi ).fill };
b.mouseMoveAction = { |v, sx, sy, m, x, y, inside| if( inside ) { p = sx@sy; }; };
b.mouseDownAction = b.mouseMoveAction;
)
b.scale = [2, 0.5]; b.move = [ 0.75, 0.25 ]; // still works
b.reset;
gridLines
ScaledUserView has built-in grid drawing. The code below explain how it works:
b.gridLines = 10;
b.gridLines = [ 10, 4 ]; // number of lines for H and V
b.gridMode = \lines; b.refresh; // doesn't refresh!!
b.gridMode = [\blocks, \lines]; b.refresh;
b.scaleH = 1.5; b.moveH = 0.25;
b.reset;
ScaledUserView.gridColor = Color.red.alpha_(0.25); b.refresh; // gridColor is a global variable
b.gridMode = \blocks; b.refresh; // default
ScaledUserView.gridColor = Color.gray.alpha_(0.25); b.refresh; // default
b.gridLines = 0; // no grid (default) - inf does the same
b.gridSpacingH; // the actual variables are gridSpacingH and gridSpacingV