last mod: 01-Aug-08 sciss
known issues / todo | |
File->Close | Doesn't work for some reason with internal frames |
OS X Screen Menu | Modifications to the menu root are not reflected in the menu "prototype" visible when no window is open |
Menu bar management. The root handle of a menu bar is represented by JSCMenuRoot
. Currently, only one global, application wide menu root is supported, but future versions might provide a menu root per window.
To create a menu, an instance of JSCMenuGroup
is created with the menu root as its parent argument. The group is then populated with items by instantiating the JSCMenuItem
class with the group as the parent argument. To create submenus, groups can be nested. To enhance visual clarity, separators can be inserted through the JSCMenuSeparator
class.
Note that on Mac OS X the menu bar appears as the screen title bar. However it is only visible if at least one SwingOSC window is opened.
JSCMenuRoot.new( <server> )
server
– the SwingOSC server to use. If omitted or nil
, the SwingOSC.default
server is used.Note that only one instance per server can be created, if you try to instantiate the root again, the same object will be returned.
r = JSCMenuRoot.new;
JSCMenuGroup.new( <parent>, <name>, <index> )
parent
– an instance of JSCMenuRoot
to attach the group to the top level, or another JSCMenuGroup
to create a submenu.name
– a String that is used to label the menu node.index
– an Integer that specifies the position of the node in the parent group. A value of 0
will place the node at the very left or top of the parent group. A value of 1
will place it after the first node in the parent group. A value of nil
will place the node at the end of the parent group, so usually you will just omit this argument.
Example:
( r = JSCMenuRoot.new; a = JSCMenuGroup( r, "Utilities" ); // add to the end of the root b = JSCMenuGroup( r, "Demos" ); // add to the end of the root c = JSCMenuGroup( a, "Server" ); // a submenu of "Utilities" // depending on the OS, the window bar not visible // unless there is at least one window if( JSCWindow.allWindows.size == 0, { JSCWindow( "Test" ).front }); )
JSCMenuGroup.new( <parent>, <name>, <index> )
The arguments have the same meaning as with JSCMenuGroup
. An item cannot have submenus. Instead is represents an action to be performed upon selection. Similar to a JSCView, you can register a Function to be invoked when the item is selected, using the setter method action_( <func> )
.
Example:
( // we want this item to appear before the "Server" // submenu, hence we use an index of 0 d = JSCMenuItem( a, "Browse UGens", 0 ); d.action = { arg item; UGen.browse }; e = JSCMenuItem( a, "Inspect Server", 1 ); e.action = { arg item; Server.default.inspect }; // now inside the "Server" submenu f = JSCMenuItem( c, "Query All Nodes" ).action_({ Server.default.queryAllNodes }); // and one for the "Demo" menu h = JSCMenuItem( b, "Analog Bubbles" ).action_({ { CombN.ar( SinOsc.ar( LFSaw.kr( 0.4, 0, 24, LFSaw.kr([ 8, 7.23 ], 0, 3, 80 )).midicps, 0, 0.04 ), 0.2, 0.2, 4 ); }.play; }); )
Some of the properties of the nodes can be modified. For example, a groups or item's name, using the name_( <newName> )
setter method:
a.name = "Tools";
Also groups and items can be disabled so they appear greyed out and cannot be selected. The corresponding setter method is enabled_( <bool> )
. In the following example, an observer is set up that enables and disables the scsynth based menu nodes depending on whether scsynth is running or not:
( UpdateListener.newFor( Server.default, { arg upd, s; c.enabled = s.serverRunning; h.enabled = s.serverRunning; }, \serverRunning ).update( Server.default, \serverRunning ); )
For quicker access, keyboard shortcuts can be assigned, using the shortcut_( <description> )
setter method. The argument is a human readable string following the format <modifiers>* <key>
, where:
modifiers := shift | meta | meta2 | control | ctrl | alt | altGraph
key :=
key code nameThe key code name consists either of a normal signal alphanumerical character, e.g. "Q"
, "W"
, "E"
, "R"
, "T"
, etc., or a any of the VK_...
as defined in java.awt.KeyEvent, e.g. "BACK_SLASH"
, "DOWN"
, "ESCAPE"
, etc.
Important: To facilitate cross-platform operation, the meaning of "meta"
and "meta2"
depends on the platform: On OS X, "meta"
corresponds to the Command-Key, on Windows and Linux this maps to the Control-Key, so it always corresponds to the commonly used menu shortcut modifier. On the other hand, "meta2"
maps to the Control-Key on OS X, and on Windows and Linux is realized as a combination of Control and Alt. Hence you can use "meta2"
as a secondary menu modifier that will not conflict with the primary modifier. If possible, avoid the use of "control"
and "alt"
, since they may interfere with the other modifiers.
Example:
d.shortcut = "meta U"; e.shortcut = "alt shift I"; h.shortcut = "meta2 B";
Nodes can be removed from the menu bar by calling the remove
method:
h.remove;
The JSCMenuCheckItem
extends the functionality of JSCMenuItem
by having a checkmark icon that gets toggled on and off. The state of the checkmark can be queried using the selected
method, or programmatically set using selected_( <bool> )
.
In the following example, the checkmark reflects whether the Moto-Rev synth is actually playing:
( var synth; h = JSCMenuCheckItem( b, "Moto Rev" ) .shortcut_( "meta2 M" ) .enabled_( Server.default.serverRunning ) .action_({ arg item; synth.release; synth = nil; if( item.selected, { synth = { RLPF.ar( LFPulse.ar( SinOsc.kr( 0.2, 0, 10, 21 ), 0.1 ), 100, 0.1 ).clip2( 0.4 ); }.play.register; UpdateListener.newFor( synth, { arg upd, n; if( synth == n, { synth = nil; item.selected = false }); }, \n_end ); }); }); )
Finally, separator lines can be inserted for increased visual clarity. The constructor is JSCMenuSeparator( <parent>, <index> )
. Here we insert a separator before the "Server" submenu:
JSCMenuSeparator( a, 2 );