SwingOSC – Java-based GUI classes

This class is meant as an emulation of SCTextView. last mod: 31-dec-09 sciss
Also refer to JSCView for different behaviour affecting all widgets

different behaviour
string_effective even when the view is made non-editable (in CocoaGUI, string_ doesn't work in this case)
enterInterpretsSelectionuses Ctrl+Return instead
extended functionality
caret_sets the cursor position
selectchanges the selection range
selectAllselect whole document
caretColor_colour of the cursor (useful for dark backgrounds)
openURLallows loading of remote files via HTTP
action_action function is called whenever text is entered, removed or caret moved
known issues / todo
textBounds_not available
usesTabToFocusNextView_not yet available
mouseDownActionnot called with extra "pos" argument
string_doesn't clear previously used style, there should be a way to clear it
text transmissiondue to the trickery of the SuperCollider unicode support (a unicode character can be reflected by more than one Char in a SuperCollider String), there occurs a discrepency between the character count (and hence cursor position) of the server (Swing) and the client (SuperCollider). You'll get "discrepancy" warning messages, indicating that the text representation on the client (SuperCollider) might be wrong

 

JSCTextView

Note: please use the abstraction layer TextView if possible!

A text view can display a large body of text, either plain or with attributes (such as in HTML). It can also be used to edit multiline text.

(
var win;

win = JSCWindow.new;
t = JSCTextView( win, win.view.bounds.insetBy( 4, 4 ))
    .resize_( 5 )
    .hasVerticalScroller_( true )
    .autohidesScrollers_( true )
    .focus( true );
win.front;
)

 

The content can be programmatically set from a plain string, using the string_ method:

t.string = "Schoko";

 

There is a general approach to changing and styling the text: Global methods such as string_ and font_ apply to the whole text, and they are accompanied by methods of the type set<PropertyName> which along with the new property value take two additional parameters, the cursor start position and the amount of characters to change. For setString it means that text is inserted when the amount of characters is zero, or replaced if it is greater than zero. Examples:

t.setString( "lade", 7, 0 );  // insert given string at position 7
t.setString( "Klang", 0, 6 ); // at position 0 replace 6 characters with the given string

 

The other properties are font, stringColor, leftIndent, rightIndent, spaceAbove, spaceBelow, lineSpacing, and align. Here are font and stringColor:

Character attributes


t.font = JFont( "Times", 14 );
t.setFont( JFont( "Times-Bold", 20 ), 0, 5 );
t.stringColor = Color.blue;
t.setStringColor( Color.red, 5, 4 );
t.background = Color.yellow;  // the global background colour
t.background = Color.white;
t.caretColor = Color.green;   // cursor colour (SwingOSC only)
t.caretColor = Color.black;

 

Paragraph attributes

The indentation of paragraphs is controlled through the properties leftIndent, rightIndent, spaceAbove, and spaceBelow, where each value is specified in pixels:

t.string      = "".catList(({{ "riverrun, past Eve and Adams".scramble } ! 8 ++ "\n" } ! 3).flatten );
t.leftIndent  = 30;             // all paragraphs
t.rightIndent = 30;
t.setLeftIndent( 60, 550, 1 );  // just the last paragraph
t.setRightIndent( 0, 550, 1 );  // just the last paragraph
t.spaceAbove  = 15;
t.spaceBelow  = 15;

 

Paragraph line spacing and alignment:

t.setLineSpacing( 1.0, 0, 1 );    // first paragraph: +100% (double-spacing)
t.setLineSpacing( -0.5, 225, 1 ); // second paragraph: -50% (half-spacing)
t.lineSpacing = 0.0;              // all normal (+- 0 %)
t.align = \right;
t.setAlign( \center, 0, 1 );      // just the first paragraph
t.setAlign( \justified, 225, 1 ); // just the second paragraph
t.setAlign( \left, 550, 1 );      // just the third paragraph

 

Custom tabulator settings

First, let's start with a basic text:

t.string = "\talpha\n\t\tbeta\n\t\t\tgamma\n\t\t\t\tdelta";
t.leftIndent = 0; t.align = \left;  // (reset previously made indentation)

 

Now let's customize the tabs:

// either just positions in pixels
t.tabs   = [ 30, 60, 90, 120 ];
t.tabs   = Array.geom( 5, 20, 1.5 ).integrate;
// ...or combos of positions with alignment
t.tabs   = [[ 30, \center ], [ 60, \center ], [ 90, \center ], [ 120, \center ]];
t.tabs   = [[ 30, \right ], [ 60, \right ], [ 90, \right ], [ 120, \right ]];

t.string = "\t1.0\n\t2.3456\n\t-133.3"
t.tabs   = [[ 40, \decimal ]];

 

Disabling the editor

When the text view is a display-only element and you don't want the content to be editable, you can call

t.editable = false;  // disable editing
t.editable = true;   // enable editing

 

Text editing notifications

When using the view as an editor, you may want to be notified about the editing process. To do so, register an action function:

t.action = { arg view, state ... params; ([ state ] ++ params).postcs };

 

The following states and state-parameters are defined:

\caret means the cursor was moved or the selection changed. with no text selected (cursor displayed) pos1 equals pos2, otherwise pos1 and pos2 correspond to the selected range (pos1 may be both greater or less than pos2).

Selections

While the whole text (without styling) can be queried with the string method, selectedString returns the currently selected text (possibly empty). The cursor position where the selections begins is returned by selectionStart and the number of characters in the selection by selectionSize. The following example uses these methods to provide a styling button:

(
    t.bounds = t.bounds.insetAll( 0, 30, 0, 0 );
    x = JSCButton( t.parent, Rect( 4, 4, 60, 22 ))
        .enabled_( false )
        .canFocus_( false )
        .states_([[ "Style" ]])
        .action_({ t.setStringColor( Color.rand, t.selectionStart, t.selectionSize )});
    t.action = { arg view, what, pos1, pos2; if( what == \caret, { x.enabled = pos1 != pos2 })};
)

 

Code execution

JSCTextView by default allows you to execute the selected text (or the current line if no selection has been made) in the SuperCollider interpreter, by pressing Ctrl+Return. For example, try to focus the view and press Ctrl+Return here:

t.string = "JSCTextView.superclasses"; t.selectAll;

 

To disable this keystroke feature:

t.enterInterpretsSelection_( false );

 

Loading files

There are two methods, open and openURL to open local and remote text files. These can be plain text or HTML formatted files.


t.open( Document.current.path ); // load this help document
t.openURL( "http://en.wikipedia.org/wiki/SuperCollider" );  // a web document

 

As you can see with the Wikipedia page, the support for modern HTML is limited. E.g. see this bug report: bugs.sun.com/bugdatabase/view_bug.do?bug_id=4296022. Also note that the display becomes better when the view is made non-editable (see next section).

Hyperlink notifications

When viewing HTML documents, you may wish to be notified about hyperlink mouse-overs and activations. A precondition is that the view is read-only, that is non-editable:

t.editable = false;

 

Three action fields are provided, linkAction (executed when the user clicks on a link), linkEnteredAction (executed when the user moves the mouse over a link), and linkExitedAction (executed when the user move the mouse away from a link). The arguments passed into the functions registered here are view (the instance of the JSCTextView), the url and the description. For special links like "javascript:..." the url is empty. Examples:

t.linkAction        = { arg view, url, description; [ "activated", url, description ].postln };
t.linkEnteredAction = { arg view, url, description; [ "entered", url, description ].postln };
t.linkExitedAction  = { arg view, url, description; [ "exited", url, description ].postln };

// a simple link-action to follow links
t.linkAction = { arg view, url; view.openURL( url )};

 

Scrollbars

By default, the view does not have scrollbars. These can be enabled using the hasHorizontalScroller_ and hasVerticalScroller_ methods:

(
var win;

win = JSCWindow.new;
t = JSCTextView( win, win.view.bounds.insetBy( 4, 4 ))
    .resize_( 5 )
	.string_( UGen.allSubclasses.collect( _.name ).asCompileString );
win.front;
)

// now display the vertical scrollbars
t.hasVerticalScroller   = true;
// now display the horizontal scrollbars
// ...note that since lineWrap is on, there is
// ...nothing to scroll here...
t.hasHorizontalScroller = true;

// therefore, when we enable automatic hiding
// ...of unused scrollbars, the horizontal bar
// ...will disappear again
t.autohidesScrollers   = true;