JTcl and Swank: Whatʼs new with and on the JVM

1Bruce A. Johnson, 2Tom Poindexter, & 3Dan Bodoh

1 bruce@onemoonscientific.com, One Moon Scientific, Inc, Westfield, NJ and University of Maryland, Baltimore County 2 [email protected] 3 [email protected]

Abstract JTcl is an implementation of the Tool Command Language (Tcl) written in Java and is derived from the Jacl project. The current release (2.0) of JTcl implements a large ex- tent of Tcl 8.4 syntax and commands, limited only by the API restrictions of the Java Vir- tual Machine. Swank is an implementation of the TK GUI toolkit implemented using the Java GUI API. Most Tk 8.4 widgets and commands have been implemented as well as additional ones based on Swing widgets. This paper describes the current state of these projects and gives examples of their use.

Introduction While there is an abundance of alternative The Java Virtual Machine [Lind99] has programming languages on the JVM, become a platform on which a variety of there are relatively few implementations of computer programming languages can be toolkits besides executed. While originally written to exe- the AWT and Swing toolkits that come cute Java programs that had been com- standard with most Java distributions. piled into Java byte codes, it is now used The primary alternatives have been to run languages such as Clojure, Groovy, Swank, SWT (the Standard Widget Jacl, JRuby, Jython, Rhino and Scala Toolkit), and quite recently JavaFX. While [WikiJVM]. Some of these, like Scala, SWT is largely implemented on top of na- appeared originally as a language on the tive platform widgets and JavaFX is im- JVM, and others, like Jacl, are JVM im- plemented with its own windowing toolkit, plementations of existing languages. Swank is a layer on top of the Swing wid- Jacl, which is an implementation of Tcl gets that provides an interface to the pro- [Ost10], was one of the first non-Java lan- grammer that is analogous to that of the guages on the JVM and appeared shortly Tk toolkit [Ost10]. after the initial development of Java [Lam97]. In this paper we’ll discuss recent devel- Jacl Modernization opments in the Tcl and Tk on the JVM, fo- Jacl modernization was selected as one cussing on the language implementation of the Tcl Core Team projects during the JTcl, and the Tk-style graphical user in- Google Summer of Code 2009 [Szul09]. terface toolkit Swank. The goal of the project was to bring Jacl's language features to the level of Tcl/ 8.4. Tcl 8.4 was chosen as a target level for JTcl several reasons. First, it represented a JTcl is a fork of Jacl, an implementation of stable base of Tcl compliance that could Tcl written in Java [Lam97]. Jacl was writ- be achieved by implementing new com- ten during the period of Tcl/C 8.0 devel- mands or augmenting existing ones. opment and contains Java equivalents of Second, the project was limited to one many internal data structures, most impor- student for one summer, so the work tantly the notion of Tcl objects to hold bi- product of the GSOC project was limited. nary representation of numeric data types, Third, current Tcl/C version 8.5 contained efficient list and array structures, and im- many structural changes, such as the ex- plementation of most of Tcl 8.0's com- pand syntax which would require a con- mands. Jacl does not implement the Tcl siderable amount of interpreter changes. byte code compiler and runtime [Lew96], The target of the GSOC project was de- nor the Tcl fileevent command and sup- rived by comparing the current set of Jacl porting event system that allows for event command definitions with the Tcl/C 8.4 driven I/O. After initial development by definitions. Many of the command imple- the original authors, Jacl development mentations required relatively little addi- was performed by individuals rather than tional code to support a particular com- as an official port of the Tcl Core Team. mand option, larger code rework was re- During this time Jacl development slowed quired to implement commands such as to mostly bug fixes but did result in a few [regex] and [regsub]. These commands major improvements, a port of the relied on moving from a custom underly- object system [DeJ05] and the Tcl-to-Java ing regular expression library to use the compiler (TJC) [DeJ06]. Development of Java java.util.regexp package. core Tcl commands and features did not keep synchronized with mainline Tcl de- While the GSOC 2009 Jacl Modernization velopment. Despite Jacl's slow progress, project yielded many improvements, it did it had proved useful in a number of com- not reach full Tcl 8.4 compliance. The mercial products, open source projects GSOC project relied on command de- and proprietary internal projects. Jacl was scriptions based on the Tcl 8.4 manual used by IBM in its WebSphere Application pages, so while many command options Server and One Moon Scientific's were added or improved, strict compli- NMRView products [John04], as well as ance to Tcl/C test cases was not tested. the open source Swank and Æjaks pro- The Jacl implementation of [regex] and jects [Poin07]. [regsub] improved significantly to match Tcl 8.4, but many edge cases were not addressed. Addition of a event system and [fileevent] also proved to be too ambi- tious, requiring more time that was avail- able. Tcl Compliance and Test Suite The Tcl language for any particular ver- The JTcl project was formed to continue sion is described in man pages and other development of Jacl and complete the documentation, but the definitive source work of the GSOC Jacl Modernization of Tcl compliance is represented by the project. The project founders decided that Tcl test suite. The test suite is usually de- a fork was the best way to achieve its veloped in conjunction with a particular goals. Jacl was a part of the TclJava pro- version of Tcl to ensure that the inter- ject, which produced the the Jacl inter- preter's result for any give operation preter as well as TclBlend, a Tcl extension matches expected results. that enables use of Java classes and ob- jects from the the Tcl/C runtime. Much of The Jacl project contained a test suite that the TclJava packaging and build system matched Tcl 8.0 compliance and was en- was designed to support the use of the hanced as changes were made to the java package in both Jacl and TclBlend source code. For JTcl, the Tcl 8.4 test environments. JTcl project members had suite was imported and used to measure no interest in the TclBlend extension and Tcl compliance. JTcl integrates the Tcl instead would focus entirely on the Java test suite through the JUnit test facility. implementation of Tcl. JUnit is a Java oriented test environment, roughly equivalent to the tcltest Tcl pack- In addition to furthering Tcl 8.4 compli- age. When running JUnit in a Java envi- ance, a number of other improvements ronment, the normal usage is to run a test were desired. First, Java code develop- method that invokes methods on an ob- ment is greatly enhanced by the use of ject under test, and asserts that actual re- Java-centric Integrated Development En- sults are equal to expected results. vironments (IDEs) such as Eclipse, Net- Since JUnit is widely supported by Java beans and IntelliJ, so the structure of the IDEs, the Tcl test suite in JTcl is invoked JTcl source code should be arranged to through JUnit classes. This allows testing support easy use by Java IDEs.. Second, of JTcl source code directly from the IDE, the build system in Jacl using make would without requiring a compile/test cycle. be replaced with a Java-centric build sys- tem. While make could be used to com- The Tcl test suite contains generic tests pile and package JTcl, Java oriented build that should run the same on any execu- systems ant and maven are better sup- tion platform as well as many tests that ported by Java IDEs. Third, packaging are specific to the platform. For example, the JTcl system would be in a single jar a particular test may only run on a Win- file for simple installation, as opposed to dows platform, while an equivalent test the Jacl system packaging in five sepa- may only run on a environment. A rate jar files. Lastly, extraneous source Java JVM presents a single virtual ma- code such as the TclBlend extension chine that (mostly) eliminates machine would be removed entirely. and platform differences. As a result, only the tests that are labeled as generic are Basic-RE meta-character ('b') are not tested in JTcl. supported. To work around these differences, the JTcl Even with running only the generic Tcl JUnit base class is designed to run a Tcl tests in JTcl, many differences in test re- test suite test file with a list of expected sults were observed and many of which failure cases. Each failure case returned were false negative results. Erroneous by the test suite is examined to note the test results generally fell into the following type of the failure, and when the differ- categories: ence could be categorized as one of the above cases, that case was added to the 1. Differences in error messages – expected failure list. The result of the ex- when a test would check for specific pected failure lists allow the entire test error messages, differences between suite to be run, with a better indication of JTcl and Tcl/C would often arise as er- positive or negative results. Numerous ror callback messages may contain Tcl command implementation classes slightly different text. Most of these were modified to pass the Tcl test suite. differences are a result of Tcl/C's byte code compiler, which returns errors Code Modernization / IDE support stating “...while compiling...” vs. the pure interpreter's error messages While the main focus of the JTcl project is “...invoked from within....”. to continue the effort of making JTcl con- 2. Ordering of results - many Tcl com- form to the Tcl language 8.4 test suite, mands return unordered results, e.g. and number of other efforts were done to [info commands]. Due to JTcl's use of modernize the code. “Modernize” is native Java libraries for hash maps in- somewhat a subjective term. The JTcl stead of Tcl's C coded ones, key lists project's definition of modernization in- were returned with different orderings. cludes reforming the code as if the JTcl 3. Unsupported functions of the JVM – code was being developed new by skilled the Java JVM does not support many Java using accepted Java low level system functions, so Tcl development best practices and tools. commands such as [file stat] are lim- ited to the operations that can be per- The existing Jacl Java code was origi- formed. nally developed to closely mimic the Tcl/C 4. Regexp differences – JTcl makes use version. This was likely done for ease of of the Java library java.util.regexp the initial port to Java. JTcl has the follow- package for regular expression han- ing changes to the source code, besides dling, whereas Tcl uses the Spencer those made for test suite compliance: ARE library coded in C. While most common Tcl ARE regular expressions 1. Source packages – Java code can be are accepted in JTcl via direct use of organized into distinct packages (i.e., java.util.regexp or through emulation, namespaces). This promotes grouping some Tcl ARE expressions such as the similar source code classes by func- tion. In JTcl, the package tcl.lang.* is used for core interpreter classes, Packaging / Tcllib tcl.lang.cmd.* for commands, Recent Jacl distributions have included tcl.lang.channel.* for I/O classes, etc. the Incr Tcl and Tcl-to-Java compiler Standard JTcl packages java, itcl, and packages. Jacl's packaging favored tjc were moved to tcl.pkg.* packages. separate jar files for the Jacl core inter- Included Tcl library code (e.g., *.tcl preter and each extension. JTcl instead files) was moved from Java source packages all core and extension compo- code directories to resource directo- nents into a single jar file. Jacl also in- ries. cludes Tcllib as part of its packaging. 2. Code formatting – much Jacl's Tcllib is a large collection of Tcl coded li- source code had specific hand- braries.. Some modules of Tcllib that formatted conventions, such as ASCII only support Tcl versions 8.5 and 8.6 are form-feed characters (^L) to separate excluded in the JTcl distribution. methods, comments within method ar- guments, debug-only code fragments. Packaging all core and library compo- JTcl code is reformatted using auto- nents of JTcl into a single jar file allow the mated tools for consistency, and de- interpreter to be started as simply as java bug specific code is removed in favor -jar jtcl.jar, though a more common usage of using the IDE's debug and break- still utilizes helper scripts. The JTcl point facilities. startup scripts jtcl (for /Unix/ 3. Block comments converted to MacOSX/Cygwin/Msys environments) and Javadoc comments – Jacl code con- jtcl.bat (Windows) allow for additional jar tains many block comments that pre- files to be included via the normal cede methods, but these were not in CLASSPATH environment variable, as the format to support the Javadoc well as runtime Java JVM parameters to tools for creating automated source be easily modified. code documentation. Where practical, source code block comments in JTcl The JTcl website is included in the project are Javadoc formatted. and is built using the maven build system. 4. IDE/build tool friendly directory lay- The JTcl source Javadoc files are also out – the project directory layout was built during website generation. changed to easily support Java IDEs and build tools. src/main/java contains RegExp Improvements the Java source code, src/main/ The regular expression engine class, resources contain Tcl library code, src/ tcl.lang.Regex, is new in JTcl and used by test/java contains Java JUnit code, [regsub], [regexp] and [lsearch -regexp]. src/test/resources contain test Tcl code This class brings the full power of TCL 8.4 (i.e., the Tcl test suite.) Additional di- Advanced Regular Expressions (ARE) to rectories contain the project website JTcl, with a few caveats. The older Basic source code, maven assembly de- Regular Expressions (BREs) and Ex- scriptors, runtime startup scripts, etc. tended Regular Expressions (EREs) are not supported, although EREs that are identical to AREs and not explicitly re- quested with the 'e' embedded option are needed for the embedded options, which supported. are similar to but not exactly like the java.util.regex.Pattern match flags. A primary implementation goal was to make use of java.util.regex.Pattern and Tcl does contain some regex features that java.util.regex.Matcher [Oracle2004], are not available in Java. These are emu- rather than writing a custom engine based lated with more complex Java expres- on the C library used in Tcl 8.4. A sions. For example, the Tcl \M (match at tcl.lang.Regex instance combines the the end of a word) has no direct Java steps of compiling a regular expression equivalent, so it is translated to and matching it on an input string, and (?=\W|$)(?<=\w) (look ahead for a word contains all the functionality required to character and behind for non-word char- implement [regsub] and [regexp]. acter).

The tcl.lang.Regex.compile() method is The decision to use responsible for converting a Tcl regular java.util.regex.Pattern led to one incom- expression to a Java Pattern instance. patibility in JTcl regular expressions. Tcl This method parses the Tcl regular ex- always attempts to match the longest pression, building a Java regular expres- string starting from the outermost levels to sion in a Stringbuffer, and compiles the the inner levels of parentheses. With al- Java regular expression into a Pattern ternation (A|B) Tcl chooses the longest instance. match of all the branches. Java evaluates the regular expression from left to right, Many aspects of the conversion of Tcl and returns the first successful match, regular expression syntax to Java syntax even if it's not the longest. This incom- are merely direct translations. For exam- patibility will not affect most common uses ple, a static Hashmap is used to translate of [regexp] and [regsub]. Tcl's character classes and escape se- quences to Java's equivalent, such as Pattern syntax error information returned [:alnum:], to \pAlnum and [:ESC:] to by Tcl is replicated by translating the mes- \\033. sage from the java.util.regex. Pattern- SyntaxException thrown by the Java More complex translations are required Pattern.compile(). However, Java is for those elements that are similar in the more forgiving about poor regular expres- two regular expression languages, but dif- sion syntax, and therefore some expres- fer in minor details or at boundary condi- sions that would generate an error in Tcl tions. For example, an empty Tcl regex may be interpreted as literal characters in matches before every character in the JTcl. string, and after the last character. Java's empty regex is similar, but does not match Code refactoring was done to collapse the after the last character. So a Tcl empty [regexp] and [regsub] common code into regex is translated to ^|(?!$) for Java. tcl.lang.Regex. The matched input sub- Many similar complex translations are string state information used by [regexp -all] and [regsub -all] was delegated to organization allows for future develop- java.util.regex.Matcher, simplifying the ment of platform-specific TclProcess code. subclasses that use native code, or a Java 7 subclass that makes use of the An apparent Tcl 8.4 bug was replicated in new redirection capabilities of Process- the JTcl code: a difference between re- Builder. gexp and regsub. The command [regexp -all -inline {a*} {a}] returns one match, {a}. The tcl.lang.process.TclProcess sub- The similar command [regsub -all {a*} {a} class is responsible for handling its own {Z}] returns {ZZ}, one Z for the match of input and output redirection. {a} with {a}, and a second Z for a zero- JavaProcess is limited by the capabilities length match after the 'a'. The of the Java 1.5 and 1.6 API, which does java.util.regex.Matcher match groups not expose the 's pipe are used for code simplicity, with a special and file descriptor inheritance mecha- case in the [regexp] implementation for nisms. All pipelines and redirection must this inconsistency. use Process.getInputStream(), Process.getOutputStream(), a n Process Pipelines for [exec] and Process.getErrorStream(). To create a [open] pipe, a new thread is created with an in- Process pipelines for [exec] and [open “| stance of tcl.lang.process. command”] and the Tcl 8.4 [exec] input TclProcess.Coupler which reads the up- and output redirection were added to JTcl, stream JavaProcess's output stream and using pure Java. The tcl.lang.Pipeline writes to the downstream JavaProcess's class parses an [exec]- or [open]-style input stream. pipeline string and builds a chain of tcl.lang.process.TclProcess instances These limitations in the Java API create for the chain of operating system com- some incompatibilities between a Tcl pipe- mands in the pipeline. Each TclProcess line and a JTcl pipeline. A pipeline instance is made aware of its neighbor launched in the background by JTcl can- TclProcess (or its redirected input and not outlive the JTcl process itself because output) with a tcl.lang.process.Redirect JTcl, rather than the operating system, is instance. The Pipeline instance can managing the pipe. manage any of the [exec] redirectors The [open “| command”] command uses a The Java Process API use of the Input- channel view of Pipeline, Stream class for standard input and the tcl.lang.channel.PipelineChannel. lack of file descriptor inheritance in the API creates problems for JTcl's tclsh emu- The tcl.lang.process.TclProcess class is lation, tcl.lang.Shell, when using [exec]. abstract with currently one concrete sub- With Java's InputStream, the only way to class: tcl.lang.process.JavaProcess. detect an end-of-file condition is to do an JavaProcess is a pure Java implementa- InputStream.read(). But doing the read tion using java.lang.Process and will take at least one byte from the stan- java.lang.ProcessBuilder. This code dard input. So the JavaProcess instance for an exec'd process can take an extra (“pid”). If this fails, -1 is returned as the byte from standard input that it may not process id. need, stealing that byte from the JTcl shell itself. A simple example is shown File Events and the New Channel Sub- below. system Significant improvements were made to Contents of the file testStdin.txt: the channel subsystem for JTcl to support exec head -1 non-blocking I/O, , and to fix fail- this line should go to head and to ing tests in the Tcl 8.4 test suite. Both stdout [fcopy] and [fileevent] are supported, puts {this line should be inter- preted by the JTcl shell} exit The [fcopy] command simply copies from one channel to another within a separate This file is sent to the JTcl shell via stan- Java thread, and uses the existing JTcl dard input: event queue to execute the callback script when [fcopy] completes. If possible, a $java tcl.lang.Shell < byte copy is made to avoid the Unicode testStdin.txt encoding and decoding step, and an effi- Two possible cases occur – the first is the cient buffering is enabled. expected output: this line should go to head and to stdout The [fileevent] command depends on the this line should be interpreted by the JTcl new non-blocking I/O implemented in the shell channel subsystem. The fileevent itself is described with two objects, The second case is when the tcl.lang.channel.FileEventScript and JavaProcess instance for 'head' steals an tcl.lang.channel.FileEvent. The in- extra byte stance of FileEventScript exists for the this line should go to head and to stdout lifetime of a fileevent, and schedules new couldn't execute “uts”: no such file or di- instances of FileEvent on the JTcl event rectory queue. Each FileEvent instance, when it comes off the queue, tests for readability These incompatibilities are relatively mi- or writability of the channel and executes nor, and could be fixed with the Java 7 the fileevent script as necessary. capabilities of ProcessBuilder which support true file descriptor inheritance at As originally coded in Jacl, the the operating system level. tcl.lang.channel.Channel abstract class is the root object for all types of channels. The [pid fileid] command is supported on Much of the channel code was re-written Posix systems on at least some JVMs by in a more Java-like fashion, replacing the looking for a field named “pid” in the literal C-to-Java translation. Subclasses of java.lang.Process instance with a value Channel are shown in Table 1. the same as that returned by Process.getClass().getDeclaredField Table 1

Java Class Description

SeekableChannel Abstract class that adds seek() and tell()

FileChannel Extends SeekableChannel to implement file I/O

ResourceChannel Implements reading of a Java resource using a “resource:” prefix on the file name

ReadInputStreamChannel Bridges a Tcl channel to a Java InputStream

AbstractSocketChannel Abstract class that has common code for socket channels

ServerSocketChannel Implements Tcl server sockets

SocketChannel Implements Tcl sockets

TclByteArrayChannel Used internally to bridge Tcl channels to Tcl byte arrays

In order to support the JTcl enhancements and fixes, Jacl's TclInputStream and InputBuffer reads bytes from the EofIn- TclOutputStream classes were replaced putFilter, provides a resizable read buffer with a chain of subclasses of and implements non-blocking reads. It java.io.InputStream, java.io.Reader, performs non-blocking reads by perform- java.io.OutputStream, a n d ing EofInputFilter.read() in a separate java.io.Writer. thread. All byte read operations on the channel are taken from this InputStream. The input side of a Channel uses the fol- lowing chain of InputStreams and Read- MarkableInputStream reads bytes from ers: the InputBuffer and allows for look-ahead in the stream. Channel.getInputStream() presents an InputStream view of the data on the UnicodeDecoder reads bytes from the channel. For example, a FileChannel MarkableInputStream and converts to uses java.io.FileInputStream. Unicode using the encoding configured by the channel. EofInputFilter reads bytes from EolInputFilter reads characters from Channel.getInputStream() and adds the UnicodeDecoder and performs the con- end-of-file byte configured by the channel. figured end-of-line translation on the channel. All character read operations on a web server in merely 41 lines of code. the channel are taken from this Reader. We found that DustMote running under JTcl could readily serve a web site (the The output side of a Channel uses the document root was set to the content of following chain of OutputStreams and the www.onemoonscientific.com site) indi- Writers: cating that the fileevent and server socket code functions as expected. EolOutputFilter is written to by the chan- nel when it performs character writes. It As a further test, multiple simultaneous performs the configured end-of-line trans- instances of JTcl were set up calling a lation on the channel. script using the [http::geturl] command to pull a file from the DustMote server. As UnicodeEncoder is written to by Eol- described above the fcopy command initi- OutputFilter, and translates Unicode ates a separate Java thread to do the file characters to bytes according to the en- copy to the clients socket and we indeed coding configured on the channel. observed that the Thread usage by Dust- Mote increased proportionally to the num- OutputBuffer is written to by Unico- ber of clients accessing it. deEncoder as well as by the channel when it performs byte writes. It provides a resizable buffer, but unlike InputBuffer, Swank does not handle non-blocking writes. The success of Tcl as a programming lan- guage comes not only from the intrinsic EofOutputFilter is written to by Output- value of Tcl, but its companion Graphical Buffer and adds the end-of-file character User Interface Toolkit, Tk. Tk has become that the channel is configured to use. so successful that it is used not only as the GUI toolkit for Tcl, but also with other NonBlockingOutputStream is written to languages such as Python. Without a by EofOutputFilter, and performs its Java implementation of Tk, JTcl would not OutputStream.write() and be able to fill many of the programming OutputStream.flush() in a separate niches accessible to Tcl. Tk widgets are, thread for non-blocking writes. however, programmed with low level calls to each platforms native graphics system Channel.getOutputStream() is written to and replicating this in Java would be a by NonBlockingOutputStream, and pro- large task. vides an OutputStream view of the chan- nel data. Developing Swank Two key factors allowed for the feasibility Testing Sockets and File Events of developing Swank (“Tk in Java”) in a reasonable period of time. Swing, the pri- A hallmark of Tcl is its event system that mary Java user interface toolkit, provides allows writing of servers with a minimal a rich variety of widgets with similar func- amount of code. An example of this is the tionality to Tk widgets. For example, the DustMote script [Kapl02] that implements Tk toplevel widget is similar to the Swing Table 2 Swing Tk Swing Tk JButton button JRadioButtonMenuItem radiobutton (on menus) JCheckBox checkbutton JScrollBar scrollbar JFrame toplevel JSlider scale JLabel label JSpinner spinbox JList listbox JTextArea message JMenu menu JTextField entry JMenuBar menubar JTextPane text JPanel frame JFrame (composite) labelframe JRadioButton radiobutton JPanel (customized)

JFrame widget, the button to JButton, the menu to JMenu, etc. Using the Swing The second key factor was the introspec- widgets meant that the behavior of Swank tion capabilities of the JTcl language. would not be as similar to Tk as it would if Much of the code that forms the basis of the Swank widgets were developed with Swank is generated by JTcl scripts that lower level Java graphic operations. On determine the fields and methods of each the other hand, adopting Swing meant Swing component and then automatically that a great deal of coding work could be produce Java code that provides a Tk-like skipped. Furthermore,using the Swing interface to the components. This gener- widgets provides a richer set of behaviors ates a large number of configuration op- than the original Tk widgets. tions for each widget. Some of these map

Table 3 Swing Tk Swing Tk JDesktopPane jdesktoppane JProgressBar jprogressbar JComboBox jcombobox JScrollPane jscrollpane JDialog jdialog JSplitPane panedwindow JEditorPane html JTabbedPane jtabbedpane JInternalFrame JInternalframe JTable jtable JOptionPane joptionpane JToolBar jtoolbar JPasswordField jpasswordfield JTree jtree JPopupMenu jpopupmenu JWindow jwindow coincidentally to the names and functions in Tk, but the Swank implementation has of Tk configuration options. In other significant differences. cases, JTcl code is used to specifically generate Java code for Tk options. In The behavior of most of the widgets in some of these cases it is only necessary these tables is largely a product of that of to generate code that parses the appro- the underlying Swing widget. The two priate Tk option and maps it to an existing most complex Tk widgets, text and can- Java Swing method. In other cases spe- vas, required substantial Java code to re- cific Java code is written to enable the produce the behavior of the Tk widgets. correct action in response to the specified The canvas widget, in particular, is almost option. This Java code is inserted in the entirely implemented by Swank specific generated Java file. Java code. This widget is based on the Swing JPanel, which essentially provides In earlier versions of Swank we made an empty screen area on which to draw available nearly all configuration options by overriding its paintComponent of the Swing widgets as Tk-style configu- method. ration options. Starting with version 3.0 the code generator has been changed to Swank Canvas Widget limit the options to a predefined list that The Swank canvas widget provides most leaves out many of the more obscure all of the features of the Tk canvas, plus Swing configuration options. This leads to some additional capabilities. Colors are a simpler toolkit that presents options one area where the Swank canvas is dis- more consistent with that of the Tk toolkit. tinguished from that of Tk. In Swank, ob- jects like rectangles and ovals can have Swank Widgets gradient or texture fills, and the colors for Swing widgets and the Tk style com- all Swank canvas items can be transpar- mands used with Swank to create them ent. are listed in Table 2. These are the wid- gets that have a particularly close corre- Configuration Options spondence between the Tk widget and Additional configuration options are avail- the Tk-style widget as implemented in able for Swank canvas items. For exam- Swank. ple, while Tk lines can have arrows at one or both ends of the line, lines on the Swank canvas allow for different styles Some Swing widgets don’t have a direct (arrow, square, circle, diamond or nothing) correspondence to existing Tk widgets, at each end. All Swank canvas items also but were deemed useful enough that they support a -rotate configuration item. A should have a Tk style command in common style when generating diagrams Swank. These are listed in Table 3. is the placing of a text label on a shape. Some of them do have analogous Tk To facilitate this, rectangles and ovals on commands that are available in exten- the Swank canvas can be configured with sions like the table and combobox wid- a text option (and corresponding font and gets. Others, like the panedwindow, exist text color options). Additional Canvas Items an Affine Transform associated with it, the Several additional canvas item types are scale of which is changed with the canvas present in Swank. In addition to normal "zoom" subcommand. This allows one to text items, the Swank canvas adds htext zoom the view of the entire canvas in or items. These support many HTML tags out. and some CSS styles (as implemented by Java Swing HTML endowed text widgets). For example, an htext item could have an H2 header, superscripts, bold and italic text or be laid out as a table using HTML table tags. Handle Selection A standard feature of many programs for Connection items are unique in that their creating diagrams or illustrations is the coordinates are specified in terms of a ability to select, move and resize items on fraction of the bounds of two other items the drawing canvas using various mouse on the canvas. In this way it is easy to actions. This can be implemented in a Tk produce diagrams where dragging one program by drawing selection indicators item around maintains a displayed con- and handles with explicit canvas items, nector to a second item without needing but it seemed such a common paradigm to write Tcl level code to reposition the that we added low level support to the connector. Annotation items combine a Swank canvas for these actions. line with an arrow at one end and a text All items can be selected using an "hse- string at the other. lect" subcommand. Any items that are se- lected are displayed with selection han- Affine Transforms dles. When the mouse enters a handle All Swank canvas items can have an Af- the cursor is changed to an "appropriate" fine transform associated with them. The resize cursor. The handles are not im- standard Swank canvas includes frac- plemented as separate canvas items, but tional transforms that allow canvas draw- are fundamentally displayed by the under- ing in fractional positions of the canvas, lying Java code at appropriate positions allowing, for example, a rectangle to fill on the bounds of the item. Moving and the top half of a canvas, no matter how resizing selected items is the responsibil- the canvas is resized. This capability is ity of "user code" and is not part of extensively used in the NMR analysis Swank, but is easily implemented. program dataChord where custom canvas items add transforms to the canvas that Scene Graph allow items to be drawn relative to the first Advanced graphics applications often ar- items position. In this way labels and an- range the display items as a collection of notations positioned near features of the nodes in a graph structure known as a NMR spectrum remain positioned relative Scene Graph. Rendering of the items is to the NMR feature, no matter how the then done by traversing the scene graph whole spectrum is zoomed or panned. and rendering each viewable item. Additionally, the whole Swank canvas has Whether or not items are rendered in front of or behind other items depends on their the node to which they are attached. If an relative position in the scene graph. A "aboveThis" argument is specified, the scene graph is being developed for the aboveThis item must be attached to the Swank canvas. As currently implemented same node as any items to be moved. the Swank canvas scene graph is imple- Thus raise (and the comparable holds for mented by adding a new "-node" configu- lower) will only change the display order ration option for each item on the canvas of items relative to other items attached to and adding a new node item type. Each the same node (but, note that node items traditional item on a canvas (arc, rectan- themselves can be raised or lowered). gle, line etc.) exists as leaf node on the graph and can not have other items at- Charts tached. Only the new node item can have Charts are implemented using JFreeChart descendants, which may be traditional [Gilb11]. In the Swank implementation display items, or additional nodes. they are essentially just another item that can be placed on the canvas. The chart If nodes are not specified the canvas acts shown in Figure 1, for example, is not im- as the traditional Tk canvas, effectively plemented by using a multiple individual being a scene graph with one root node canvas items, as would be done in Tk, but and zero or more visual items that are is instead a single chart item that can rendered in order of their attachment to readily be resized and repositioned on the the root node. The scene graph is ren- canvas. dered in a depth-first (post-ordered) fash- ion with children at each node rendered The canvas charts, illustrate a significant from left to right (first to last added). The advantage of working in the JVM envi- bounding box (returned with the "canvas ronment. Working with the C implementa- bbox" command) is the union of the tion of Tcl/Tk one would need to find a bounds of all the items below that node. charting library that works on all the major Node items are also rendered if they have environments (Mac, Windows, Linux, etc.) a non empty fill or outline parameter. They and then ensure that it compiles, links and are rendered as rectangles whose size is runs on these. Integrating such a library the same as the bounding box described might require significant knowledge of the above. Note that if the fill parameter is set, build environment of each operating sys- and is not transparent, all items below that tem. Using such a library also requires an node will be obscured as the node is ongoing commitment to update the library drawn after the items below it on the and build environment for new operating graph. system releases. With the JVM ap- proach,however, one needs only ensure The raise and lower canvas subcom- that the libraries jar files are available on mands have a modified behavior with re- the build and run classpaths and one has spect to scene graphs that have more a high level of confidence that the applica- than one node. A raise command issued tion will run on any platform implementing without a "aboveThis" argument will move a compatible version of the JVM. the specified items to be the last items of Figure 1. This figure is a screenshot of the program dataChord Spectrum Analyst which is a Java program that integrates JTcl and Swank. The primary window is used for displaying Nuclear Magnetic Resonance (NMR) spectra, but also provides for rich annotation features by the user. The NMR spectra are analyzed, in part, using tools available from the Apache Commons Math libary [ACM11]. The spectra are rendered as custom items on the Swank canvas, so multiple spectra can be rendered in various positions and orientations on the canvas. The screenshot is somewhat contrived to show various Swank canvas items: a rectangle with a transparent, gradient color, two ovals joined by a connector item, an htext item showing the user of superscript and bold text, and a chart item, implemnted using the JFreeChart library.

Much of the data analysis of dataChord Spectrum Analyst is implemented as JTcl scripts, and as a client-server program it relies heavily on the file, channel and socket capababilites of JTcl. Canvas3D Besides the standard Tk-like canvas, A large advantage of developing in the Swank includes a canvas suitable for dis- JTcl/Swank environment is the ability to playing 3D objects. The implementation take advantage of other libraries imple- is at present fairly limited, but does pro- mented in Java. The developer can have vide the ability to draw spheres, cylinders, a high level of confidence that the combi- cones, and text. The actual 3D graphics nation of JTcl and Swank with other Java are implemented using Java3D. libraries will run unchanged on any plat- Building and Packaging form with the JVM. An example of this is Swank is built and packaged using the the program, dataChord Spectrum Analyst same maven-based infrastructure as used (Figure 1), which is written to use JTcl and by JTcl. The primary build result is a zip Swank, and integrates in a cross-platform file that forms a “batteries included” distri- way libraries for math, statistics and chart- bution, that includes JTcl (which as dis- ing. cussed above includes incr Tcl, the TJC Tcl to Java Compiler, and much of Tcllib), JTcl is hosted at http://jtcl.kenai.com/ and the chart canvas item code (including Swank at http://swank.kenai.com/. In- JFreeChart jar files), and the canvas3d stallers, source code, documentation, package. mailing lists and bug trackers are avail- able for both projects at these sites. Helper scripts for starting a Swank envi- ronment are included and are analogous to those described above for JTcl. Tk dis- References tributions include a program called “”. [ACM11] Swank provides helper scripts called Commons Math: The Apache Commons “wisk” (and wisk.bat on Windows) that Mathematics Library start up the same type of environment that http://commons.apache.org/math/ “wish” does. Also included are helper scripts, swkcon (and swkcon.bat on Win- [DeJ05] dows). These start up Swank with a Incr Tcl extension for Jacl Swank implementation of the TkCon con- TclJava project sole [Hobbs09]. http://sf.net/projects/tcljava http://sourceforge.net/mailarchive/messag e.php?msg_id=1134245 Conclusions Together, JTcl and Swank, provide an en- [DeJ06] vironment for developing applications that TJC : A Tcl to Java Compiler is very similar to that of Tcl and Tk. Most Mo DeJong programs that will run with Tcl 8.4 will run Thirteenth Annual Tcl/Tk Workshop, 2006 unchanged on JTcl. Swank has a greater http://modejong.com/publications.html level of differences to Tk, but provides a high level of compatibility along with addi- [Gilb11] tional widgets and capabilities, especially JFreeChart with regards to the canvas widget. David Gilbert http://www.jfree.org/jfreechart [Ost10] “Tcl and the Tk Toolkit, 2nd Ed.”, John. K. [Hobbs09] Ousterhout and Ken Jones, 2010, TkCon Project Addison-Wesley. Jeffrey Hobbs http://tkcon.sourceforge.net/ [Poin07] Aejaks Project [John04] Tom Poindexter "From C to Java, Scientific Data Analysis http://sf.net/projects/aejaks with Java, Jacl and Swank" Bruce A. Johnson [Szul09] 11'th Annual Tcl/Tk Conference Tcl/Tk Community Google Summer of http://www.tcl.tk/community/tcl2004/Paper Code 2009 s/ Jacl Modernization Project http://wiki.tcl.tk/23812 [Kapl02] DustMote [WikiJVM] http://wiki.tcl.tk/4333 JVM Languages http://en.wikipedia.org/wiki/JVM_language [Lam97] s "Jacl: A Tcl Implementation in Java" Ioi K. Lam, Brian Smith Fifth Annual Tcl/Tk Workshop, 1997 http://www.usenix.org/publications/library/ proceedings/tcl97/lam.html

[Lew96] "An On-the-fly Bytecode Compiler for Tcl" Brian T. Lewis Fourth Annual USENIX Tcl/Tk Workshop, 1996 http://www.usenix.org/publications/library/ proceedings/tcl96/lewis.html

[Lind99] “The Java™ Virtual Machine Specifica- tion, 2nd Ed.”, T. Lindholm and F. Yellin, 1999, Prentice Hall.

[Oracle2004] http://download.oracle.com/javase/1,5.0/d ocs/api/overview-summary.html