// this example shows the possibility

// of creating any kind of gui widgets

// in swingOSC. here we create an

// AWT frame, place an applet inside

// and run it.

n = NetAddr( "127.0.0.1", 57111 );

try { n.connect }; // if running on TCP!

// using multiple message sends

(

n.sendMsg( "/global", \myWindow, '[', "/new", "java.awt.Frame", "SwingOSC avec un applet", ']');

n.sendMsg( "/set", \myWindow, \bounds, '[', "/new", "java.awt.Rectangle", 80, 80, 500, 500, ']', \visible, true,

\layout, '[', "/new", "java.awt.BorderLayout", ']' );

n.sendMsg( "/global", \myBubbles, '[', "/new", "de.sciss.swingosc.test.Bubbles", ']' );

n.sendMsg( "/method", \myWindow, \add, '[', "/ref", \myBubbles, ']', "Center" );

n.sendMsg( "/set", \myBubbles, \size, '[', "/method", \myWindow, \getSize, ']');

n.sendMsg( "/method", \myBubbles, \start );

)

(

n.sendMsg( "/method", \myBubbles, \stop );

n.sendMsg( "/method", \myWindow, \dispose );

n.sendMsg( "/free", \myBubbles, \myWindow );

)

// using one bundle

(

n.sendBundle( nil,

[ "/global", \myWindow, '[', "/new", "java.awt.Frame", "SwingOSC avec un applet", ']' ],

[ "/set", \myWindow, \bounds, '[', "/new", "java.awt.Rectangle", 80, 80, 500, 500, ']', \visible, true,

\layout, '[', "/new", "java.awt.BorderLayout", ']' ],

[ "/global", \myBubbles, '[', "/new", "de.sciss.swingosc.test.Bubbles", ']' ],

[ "/method", \myWindow, \add, '[', "/ref", \myBubbles, ']', "Center" ],

[ "/set", \myBubbles, \size, '[', "/method", \myWindow, \getSize, ']' ],

[ "/method", \myBubbles, \start ]

);

)

(

n.sendBundle( nil,

[ "/method", \myBubbles, \stop ],

[ "/method", \myWindow, \dispose ],

[ "/free", \myBubbles, \myWindow ]

);

)

n.sendMsg( "/quit" );

Explanation

n.sendMsg( "/global", \myWindow, '[', "/new", "java.awt.Frame", "SwingOSC avec un applet", ']' );

- When creating object, we often need to refer to them later. To do this, we need to store their reference in some variable. "/global" puts the result of the second argument in a variable whose name is given in the first argument. Variables defined with "/global" are accessible by different client (clients are distinguished by their sender socket address).

- When an argument is not a literal, that is a number or a symbol, it needs to be encapsulated in two bracket string arguments '[', ']'. Therefore, the expressing '[', "/new" ..., ']' represents the second argument for the outer OSC command "/global".

- Note that SuperCollider only uses integer, float and string type tags in OSC commands. When we use symbols in the example above, we do this for better readibility and conceptual differentiation between language symbols and actual strings. You are free to use strings everywhere. Note however, that to use the actual strings "[" and "]", they need to be escaped as '[', "/ref", \brko, ']' and '[', "/ref", \brko, ']' respectively.

- To instantiate an object, use the "/new" command, whose first argument is the full qualified class name, the rest of the arguments being passed to the constructor. In the first line, SwingOSC will look up a constructor Frame::Frame( String ). In some cases, argument types will be automatically converted, for example a float might be converted to a double or even integer. SwingOSC has a simple scheme as to "measure" what's the best fitting constructor or method. For example consider the class java.awt.Color which has a constructor Color::Color( int, int, int ) and a constructor Color::Color( float, float, float ). Depending on the OSC arguments, when it finds ints or longs, it will use the first constructor, if it finds floats or doubles, it uses the second version.

n.sendMsg( "/set", \myWindow, \bounds, '[', "/new", "java.awt.Rectangle", 80, 80, 500, 500, ']', ... );

- The second line's command is "/set" which is an abbreviation for "/method" which can execute any number of methods at once, given that these methods' names start with "set" and that their signature requires exactly one argument. This is generally true for all kind of java "beans" methods. Since AWT and Swing components are very bean-like, this works very well in many cases. For example, java.awt.Frame has the methods setBounds( java.awt.Rectangle ), setVisible( boolean ), setLayout( java.awt.LayoutManager ). Using the "/set" command reduces the method calls to the property names with lower-case first letter (bounds, visible, layout), and property names and their values assembled as pairs.

n.sendMsg( "/method", \myWindow, \add, '[', "/ref", \myBubbles, ']', "Center" );

- When methods need to be called that do not begin with "set" or which have an argument count other than one, we need to use the "/method" command, whose first argument is the reference name of the object on which to operate, the second argument is the method name, the rest of the arguments are the arguments passed to the method. Note that in these method arguments, when you wish to use a previously created object, you cannot put its reference name directly as it will be interpreted as a string. Instead you dereference it using the '[', "/ref", <objectID>, ']' construction.

n.sendMsg( "/set", \myBubbles, \size, '[', "/method", \myWindow, \getSize, ']' );

- A side-effect of "/method" is that it returns the method's return value if used as a nested bracket argument. Therefore we can use it to generate arguments for the outer command directly, without having to store them in temporary variables. Please note that "/get" behaves different as it is meant to send back the values to the client. Therefore we cannot use '[', "/get", \myWindow, \getSiz e, ']' here!

n.sendMsg( "/method", \myWindow, \dispose );

n.sendMsg( "/free", \myBubbles, \myWindow );

- Other that in the previous version of SwingOSC, the application does not know anything about the mechanics of the created objects any more. In fact, you are not limited to creating instances of subclasses of java.awt.Component. Therefore, the "/free" method now simply removes the variable association. It will not do the cleanup of compents for you. This must be done explicitly as shown above using the window's dispose() method. Also, a drawback of the new concept is that there exists no node tree any more. Therefore, calling "/free" on a window does not affect any of the gadgets put inside the window. So cleaning up a populated window can be tedious. However, SwingOSC primarily aims at applications where separate client side classes deal with this cleanup automatically, as shown in the SuperCollider GUI classes for example.

// last mod: 30-jul-07 sciss