SCUserView user-definable view
superclass: SCView
SCUserView is a user-definable View intended mainly for use with Pen and drawHooks.
See also: SCWindow, Pen, Color, and String
keyDownAction_
Set the function which should be evaluated if the view is in focus and a key is pressed. This function will be passed four arguments: the View, the key pressed as a Char, modifier keys (shift, alt, etc.), and the unicode value. See SCView for more details.
(
// select the window, type something and watch the post window
w = SCWindow.new("select this window and type something");
c = SCUserView(w,w.view.bounds);
c.keyDownAction = { arg view,char,modifiers,unicode;
[char, modifiers, unicode].postln;
c.drawFunc = {|me|
char.asString.drawAtPoint(180@150, Font("Helvetica", 70), Color.blue(0.3, 0.5))
};
c.refresh;
};
w.front; c.focus;
)
drawFunc_
Set the function which should be evaluated if the view is refreshed. This happens every time the view or the whole window is refreshed (manually by calling SCView:refresh, SCWindow:refresh or e.g. by selecting the view or resizing the window).
(
var func;
func = {|me|
Pen.use{
// clipping into the boundingbox
Pen.moveTo((me.bounds.left)@(me.bounds.top));
Pen.lineTo(((me.bounds.left)@(me.bounds.top))
+ (me.bounds.width@0));
Pen.lineTo(((me.bounds.left)@(me.bounds.top))
+ (me.bounds.width@me.bounds.height));
Pen.lineTo(((me.bounds.left)@(me.bounds.top))
+ (0@me.bounds.height));
Pen.lineTo((me.bounds.left)@(me.bounds.top));
Pen.clip;
// draw background
Color.gray(0.5).set;
Pen.moveTo((me.bounds.left)@(me.bounds.top));
Pen.lineTo(((me.bounds.left)@(me.bounds.top))
+ (me.bounds.width@0));
Pen.lineTo(((me.bounds.left)@(me.bounds.top))
+ (me.bounds.width@me.bounds.height));
Pen.lineTo(((me.bounds.left)@(me.bounds.top))
+ (0@me.bounds.height));
Pen.lineTo((me.bounds.left)@(me.bounds.top));
Pen.fill;
Pen.translate(100, 100);
10.do{
Color.red(rrand(0.0, 1), rrand(0.0, 0.5)).set;
Pen.addArc((400.exprand(2))@(100.rand), rrand(10, 100), 2pi.rand, pi);
Pen.perform([\stroke, \fill].choose);
}
}
};
w = SCWindow.new("DrawFunc Examples").front;
w.view.background_(Color.white);
3.do{|i|
v = SCUserView(w, Rect(20+(i*120), 100, 100, 100));
v.drawFunc = func;
};
w.refresh;
)
relativeOrigin_
Set the Origin of Pen in the view's drawFunc relative to the SCUserView.
(
var func;
func = {|me|
Pen.use{
10.do{
Color.red(rrand(0.0, 1), rrand(0.0, 0.5)).set;
Pen.addArc((400.exprand(2))@(100.rand), rrand(10, 100), 2pi.rand, pi);
Pen.perform([\stroke, \fill].choose);
}
}
};
w = SCWindow.new("DrawFunc Examples").front;
w.view.background_(Color.white);
3.do{|i|
v = SCUserView(w, Rect(20+(i*120), 100, 100, 100))
.drawFunc_(func).relativeOrigin_(true);
};
w.refresh;
)
mousePosition
Get the relative position of the mouse cursor.
mouseDownAction_
Set the function which should be evaluated if the mouse is at the beginning of tracking (mouse-down). This function will be passed four arguments: theView, x coordinate, y coordinate, and keyboard modifiers.
mouseMoveAction_
Set the function which should be evaluated if the mouse is tracked. This function will be passed four arguments: theView, x coordinate, y coordinate, and keyboard modifiers.
mouseUpAction_
Set the function which should be evaluated if the mouse is at the end of tracking (mouse-up). This function will be passed four arguments: theView, x coordinate, y coordinate, and keyboard modifiers.
(
var drawFunc, beginTrackFunc, endTrackFunc, trackFunc, sat = 0, absX;
drawFunc = {|me|
Pen.use{
10.do{
Color.red(rrand(0.0, 1), rrand(0.0, 0.5)).set;
Pen.addArc((400.exprand(2))@(100.rand), rrand(10, 100), 2pi.rand, pi);
Pen.perform([\stroke, \fill].choose);
}
}
};
beginTrackFunc = {|me, x, y, mod|
absX = x;
postf("begin path: x=% realtive mousePosition:%\n",absX, me.mousePosition);
};
endTrackFunc = {|me, x, y, mod|
postf("end path: (absX-x)==% realtive mousePosition:%\n",(absX-x), me.mousePosition);
};
trackFunc = {|me, x, y, mod|
sat = ((absX-x)/100);
((me.mousePosition)/(me.bounds.width@me.bounds.height)).postln;
me.refresh;
};
w = SCWindow.new.front;
w.view.background_(Color.white);
3.do{|i|
v = SCUserView(w, Rect(20+(i*120), 100, 100, 100));
//v.background_(Color.white); // not affecting anything...
v.drawFunc = drawFunc;
v.mouseDownAction = beginTrackFunc;
v.mouseUpAction = endTrackFunc;
v.mouseMoveAction = trackFunc;
v.relativeOrigin = true;
};
w.refresh;
)
// draw on the view
(
var w, txt, tmppoints, all;
tmppoints = [];
w = SCWindow("draw on me", Rect(128, 64, 340, 360));
v = SCUserView(w,w.view.bounds)
.mouseMoveAction_({|v,x,y|
[x,y].postln;
tmppoints = tmppoints.add(v.mousePosition);
v.refresh;
})
.mouseUpAction_({|v,x,y|
all = all.add(tmppoints.copy);
tmppoints = [];
v.refresh;
})
.drawFunc_{|me|
Pen.use {
Color.white.set;
Pen.fillRect(me.bounds.moveTo(0,0));
Pen.width = 1;
Color.black.set;
Pen.beginPath;
tmppoints.do{ |p, i|
if(i == 0){
Pen.moveTo(p);
}{
Pen.lineTo(p);
}
};
all.do{|points|
points.do{|p, i|
if(i == 0){
Pen.moveTo(p);
}{
Pen.lineTo(p);
}
};
};
Pen.stroke;
};
};
v.relativeOrigin = true;
w.front;
)
clearOnRefresh_
Set the behaviour for refreshing the view. If this flag is true (the default) the view will be cleared before each refresh call, otherwise It will draw in top of it. On OSX this functionality is only available for the version >= 10.4 and with the flag relativeOrigin set to true.
(
var width = 640, height = 480, w, theta = 0, drawFunc, gui;
gui = GUI.get( \cocoa );
w = gui.window.new( "clearOnRefresh = true", Rect( 128, 64, width, height ), false );
drawFunc = { arg view;
var x = 20 * sin( theta ), y = 42 * cos( theta );
gui.pen.addRect( view.bounds.moveTo( 0, 0 ));
gui.pen.clip;
theta = theta + 0.01;
gui.pen.fillColor_( Color.red( 0.2, 0.1 ));
gui.pen.fillRect( Rect( 0, 0, width, height ));
gui.pen.strokeColor_( Color.white );
gui.pen.translate( width * 0.5, height * 0.5 );
6.do { arg i;
gui.pen.rotate( theta * (1 - (i / 6)) );
gui.pen.scale( 0.7 + (i * 0.4), 0.4 + (i * 0.5) );
gui.pen.strokeOval( Rect.aboutPoint( Point( x, y ), 60, 40 ));
};
};
x = gui.userView.new( w, Rect( 10, 10, width - 20, height - 20 ))
.canFocus_( false )
.drawFunc_( drawFunc )
.clearOnRefresh_( false )
.relativeOrigin_( true );
w.front;
Routine({ while({ x.isClosed.not }, { x.refresh; (1/25).wait })}).play( AppClock );
)
(
var width= 640, height= 480, w, theta= 0, drawFunc;
w= GUI.window.new("trail test3", Rect(128, 64, width, height), false);
drawFunc= {|v|
var x= 20*sin(theta), y= 42*cos(theta);
theta= theta+0.01;
GUI.pen.fillColor_(Color.red(0.2, 0.1));
GUI.pen.fillRect(Rect(0, 0, width, height));
GUI.pen.strokeColor_(Color.white);
GUI.pen.push;
GUI.pen.translate(width*0.5, height*0.5);
6.do{|i|
GUI.pen.rotate(theta*(1-(i/6)));
GUI.pen.scale(0.7+(i*0.4), 0.4+(i*0.5));
GUI.pen.strokeOval(Rect.aboutPoint(Point(x, y), 60, 40))
};
GUI.pen.pop;
};
GUI.userView.new(w, Rect(10, 10, width-20, height-20)).drawFunc_(drawFunc).relativeOrigin_(true);
w.front;
Routine({inf.do{|i| w.refresh; (1/25).wait}}).play(AppClock);
)
prevent redrawing:
(
var func, views;
func = {|me|
Pen.use{
10.do{
Color.red(rrand(0.0, 1), rrand(0.0, 0.5)).set;
Pen.addArc((400.exprand(2))@(100.rand), rrand(10, 100), 2pi.rand, pi);
Pen.perform([\stroke, \fill].choose);
}
}
};
w = SCWindow.new("DrawFunc Examples").front;
w.view.background_(Color.white);
views = {|i|
v = SCUserView(w, Rect(20+(i*120), 100, 100, 100)).relativeOrigin_(true);
v.drawFunc = func;
} ! 3;
w.refresh;
{views.do{|v| v.clearOnRefresh_(false);v.drawFunc = nil}}.defer(0.4);
)
refreshInRect(aRect)
OS X only for the moment.
Constrains the receiver's refresh area to the rectangle passed in aRect.
// example
// you may use Quartz Debug's flash screen updates to see the refresh area of the view
(
var userView, win, blob = Rect(0, 0, 50, 50), trackblob=false, pmouse;
a = SCImage.new("/Library/Desktop Pictures/Ripples Blue.jpg");
win = SCWindow.new("refreshInRect Test", Rect(400, 400, 600, 200), scroll:true).front;
win.onClose_({ a.free; });
userView = SCUserView(win, Rect(10,10,2000,800))
.backgroundImage_(a, 5)
.relativeOrigin_(false)
.drawFunc_({|me|
Color.blue.setFill;
Pen.fillRect(blob);
})
.mouseDownAction_({|v, x, y, mod|
pmouse = x@y;
trackblob = blob.containsPoint(pmouse);
})
.mouseUpAction_({|v, x, y, mod|
trackblob = false;
})
.mouseMoveAction_({|v, x, y, mod|
var refresh, mouse, delta;
mouse = x@y;
if(trackblob, {
refresh = blob.copy;
delta = mouse-pmouse;
blob = blob.moveBy(delta.x, delta.y);
refresh = refresh.union(blob);
v.refreshInRect(refresh);
});
pmouse = mouse;
});
blob = blob.moveBy(userView.bounds.left, userView.bounds.top);
userView.bounds.postln;
)