SuperCollider provides for using different gui kits, and also provides syntax for transparently writing kit and platform independent code. Two main classes control this mechnanism: the gui factory abstraction class, GUI, and the subclasses of ViewRedirect, which transparently uses the GUI class to redirect to the kit-specific gui class.

For a table of all gui classes and their equivalents, see GUI-Classes.

w=Window("Test Window").front; // Window is a subclass of ViewRedirect

w.postln // w now contains the class appropriate to the gui kit

Kit-dependant gui classes have a prefix. For example, to make a window, the CocoaGUI kit uses SCWindow, or the swing kit uses JSCWindow. It is generally discouraged to use the kit-dependant classes directly. Instead, you simply use the subclasses of ViewRedirect. In most cases this involves simply using the class base name without any prefix, like in the example above. Behind the scenes, the above technique actually automatically redirects to the appropriate GUI class method. For a table of all gui classes and their kit-dependent equivalents, see GUI-Classes.

Depending on the curent GUI.scheme the example above is equivalent to writing, for example:

SCWindow("Test Window").front; // cocoa version

or

JSCWindow("Test Window").front; // swing version

Basic Usage: Windows, Containers and Decorators

(

// Window returns the window class for the current kit

w = Window( "my name is...", Rect( 128, 64, 340, 360 ));

w.view.decorator = FlowLayout( w.view.bounds ); // comment this out for no decorator

// w.addFlowLayout // you can use this instead of the above line for brevity.

w.view.background = Color( 0.6, 0.8, 0.8 );

32.do({ arg i;

// Here Button returns the button class for the current kit

b = Button( w, Rect( rrand( 20, 300 ), rrand( 20, 300 ), 75, 24 ));

b.states = [[ "Start " ++ i, Color.black, Color.rand ],

[ "Stop " ++ i, Color.white, Color.red ]];

});

w.front;

)

w.postln //prints the window instance for the current gui kit

b.postln //prints the button instance for the current gui kit

In the above example, first a Window was created. A Window automatically has its own top level container, which is a subclass of CompositeView. A CompositeView can have a decorator, which automatically places the contents in a predetermined order. In this case it is a FlowLayout, which is the only one that currently exists. This is optional however. Try commenting out the decorator in the example above.

Window and CompositeView both have addFlowLayout utility methods which assign an instance of FlowLayout to their view decorators and return the decorator.

Most gui objects are subclasses of View. All subclasses of View are created with the same beginning arguments, parent and bounds, for example, Slider(parent, bounds).

The parent is a container view of some kind, and the bounds are an instance of Rect or a Point (for width and height only). Using a Point is convenient if you are using a decorator for the postioning.

(

w=Window.new.front;// Use Rect for precise placement in a CompositeView

Slider(w, Rect (50,50,250,20)); // Slider is actually placed in w.view, which is a top view.

Slider(w.view, Rect (50,100,250,20)) // So this is equivalent when Window is used as a parent

)

You can easily nest containers, decorators and views to make complex layouts, and you can use colors to visually separate them:

14.do{ Slider(v, 180@20).background_(v.background) };// Points used, since the layout is handled by a decorator.

18.do{ Slider2D(y,58@58).background_(Color.rand); };

)

Container Coordinates

Container and User views use relative bounds coordinates, which are measured from the parent view's top left corner.

(

w=Window.new.front;// Use Rect for precise placement in a CompositeView

v=CompositeView(w, Rect(50,50,300,300));

v.background_(Color.grey);// give the subview a visible color

Slider(v, Rect (50,50,220,20)) // so this is equivalent when Window is used as a parent

)

Window Coordinates

For a Window, the bounds coordinates are measured from the bottom left of the screen.

The bounds.rect differs from that of views, and is the following: Rect(left, bottom, width,height). Typically, you will call Window.screenBounds to place a window precisely independently of the screen size you are working on.

(

w=Window.new("A Precisely Placed Window",

Rect(100, Window.screenBounds.height-300, 300, 200 )

).front;

) //since the window is 200 high and the bottom is at screenBounds.height-300, the top is 100 from the screen top

Resizing

Views can resize or stretch according to nine differents states, according to the instance variable resize. For documentation and examples see resize.

Actions: Performing Things with a GUI Widget

Gui widgets typically have an action, which is a Function or FunctionList to be evaluated when the user interacts with the widget.

You can set the action, or use addAction, or removeAction to determine how a widget interacts with your code.

Calls to the gui system from from the lang must be made from the AppClock, since the SystemClock is reserved for high priority sound related tasks. If you want to control a gui with a Routine or Task, then you must either use the AppClock to play them, or use the defer mechanism, which schedules a Function in the AppClock:

Sending values from a gui object to the sound server is basically the same as sending from the lang. Gui widgets typically have an action, which is a Function or FunctionList to be evaluated when the user interacts with the widget.

// b.get sends query to the server, and waits for a response before it sets the StaticText.

0.01.wait;

}.loop

}.play

});

CmdPeriod.doOnce({w.close});

w.onClose={r.stop; q.free; b.free }; //clean up if the window closes

)

Here an OSCreponder changes a gui. See OSCresponderNode for more examples. It is important here that the action of the responder is defered.

(

s.waitForBoot({

w=Window.new.front;

w.view.background_(Color.blue(0.3));

x={var d,arr,out;

d = Dust.kr(2,0.2);// generate triggers for SendTrig and for DynKlank

SendTrig.kr(d, 0, 0.9); // send message to lang

arr=Array.fill(4, {TRand.kr(50+500.rand,1200+1200.rand,d)});

out=DynKlank.ar(`[arr, nil, [1, 1, 1, 1]], K2A.ar(d)*0.1);

Limiter.ar(out,0.5)

}.play;

// register to receive this message

a = OSCresponderNode(s.addr, '/tr',

{ {w.refresh}.defer }).add; // you must use defer here

w.drawHook = {|me|

Pen.use{

90.do{

Pen.strokeColor=Color.rand.alpha_(rrand(0.1,0.9));

Pen.addArc(400.rand@400.rand, rrand(10, 100), 2pi.rand, pi);

Pen.stroke;

};

}

};

CmdPeriod.doOnce({w.close}); //close window when sound is stopped

w.onClose=({a.remove; x.free;});// clean up

});

)

Custom GUI: designing your own widgets using UserView

UserView is generally speaking a view in which you can draw, and for which you can define mouse, key, and drag and drop actions. For documentation on all of these, see the UserView, View, and Pen help files. The example below, however, will demonstrate a basic example of these techniques for designing a widget. The steps you need to take are the following:

Caution, subclassing differs in many points from the example below. For a subclassing template and a quick tutorial on how to write a custom widget as a SCUserView subclass, see SCUserView-Subclassing.

You can get a quick simple automatic interface for a Synth with SynthDesc : makeWindow.

(

s.waitForBoot({

SynthDef("test", { arg out, freq=330, amp=0.6;

Out.ar(out, SinOsc.ar(freq,0,amp))

}).add;

SynthDescLib.global.at(\test).makeWindow;

});

)

Helper Methods in GUI

*stringBounds( string, font )

Returns a Rect object describing the bounds occupied by the given string if it was painted using the given font. Note that this method is asynchronous in SwingOSC, hence it is advised to use it inside a Routine.(not necessary on CocoaGUI). Example:

These classes use the current GUI kit implementation as returned by GUI.current . You usually do not instantiate them directly, but use one of the "Plus-GUI" methods described in the next paragraph.

ObjectInspector

StringInspector

ClassInspector

FunctionDefInspector

MethodInspector

SlotInspector

FrameInspector

ClassBrowser

"Plus-GUI" methods are methods added to other classes such as String or Server that provide GUI functionality for those classes. These methods use the current GUI kit implementation as returned by GUI.current .