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;

)