This is just one of several computer projects that I occasionally work on. The state of this project is work in progress.

STIPPLE Window Interface Toolkit

Introduction

I have my own programming language called STIPPLE. This project is a library of code written in STIPPLE that allows me to easily write applications that have a graphical user interface (GUI). Currently, this library directly interfaces to the Tcl/Tk graphical toolkit. A good place to find out more about Tcl/Tk is to go visit the Scriptics web site.

Rationale

Why use Tcl/Tk? Well, it seems to be the easiest to use window toolkit that I have been able to find. There might be others, but I haven't stumbled across them yet. Another advantage of Tcl/Tk is that it runs on the three platforms I most care about -- Unix (Linux in particular), Windows, and MacIntosh. Also, this toolkit should be fairly easy to bang together since the Tcl/Tk team has undertaken all of the hard work of figuring our all of the arcane issues associated with these various platforms.

To Do List

This is not most logical place to put a "to-do" list, but I find it convienient here.

Design

The basic idea behnd the SWIT library is to treat Tcl/Tk as a black box. There are two basic pieces to SWIT -- an application library written in STIPPLE and Tcl/Tk window shell that is running some Tcl code that makes it behave like a server for SWIT library requests; the application library is call the SWIT application client or SWIT client for short and the Tcl/Tk window shell is called the SWIT server.

The application is linked together with the SWIT client library. The SWIT client starts up the SWIT server and opens a TCP/IP connection to it. The SWIT client library sends commands and procedures to the SWIT server and the the SWIT server sends back results, error codes, and events.

There is one connection object for each active connection to a SWIT server. Thus, SWIT directly supports the ability to do GUI applications that display on multiple displays (e.g. a shared white board). Furthermore, a SWIT server can support multiple connections from different window SWIT clients. As long as the SWIT line protocol is obeyed, someone else could write a client library that is equivalent to SWIT in another language (e.g. Java, C, Perl, etc.). A picture of several applications sharing a single SWIT server is shown below:

Overall SWIT Architecture

The SWIT line protocol is very basic. It basically consists of lines of text sent back and forth between the SWIT client library and the SWIT server. The lines are summarized below:

H SWIT_Server major minor socket_name
The header line is sent by the SWIT server to the SWIT client library immediately upon connection establishment.
magor
The major version number for the SWIT line protocol. For now this is `1'.
minor
The minor version number for the SWIT line protocol. For now this is `0'.
socket_name
This is the socket name that the SWIT server is talking back to the client on. This is usually sockN, Where N is a a number. For example, `sock5'.
This command is sent back to the SWIT client library exactly once. After connection establishment, the SWIT server is sitting in an event loop waiting for command lines. (See the C line immediately below.)
C command
The command line is sent by the SWIT client library to the SWIT server where
command
This is the command that needs to be executed.
Each command causes a corresponding result line to be returned. (See the R line immediately below.)
R catch_code result_string
The result line reports the result of executing a command line. The Tcl command line is executed in an enclosing catch statement.
catch_code
This is the result of the catch statement. A catch result of `0' means that no error occured and a non-zero value means that an error occurred.
result_string
The result of the command is returned. If the catch_code is non-zero, the catch error message is returned instead.
E event_number event_data
An event line is sent each time an event occurs in the SWIT server that needs to be reported back to the SWIT client library.
event_number
This is a unique event identification number that was assigned by the SWIT client library.
event_data
This is event data. The data is returned as a sequence of space separated values (usually numbers.)
On all of these commands, an new-line character is encoded as `\n' and a backslash character is encoded as `\\'. There is no specific line for dealing with closing down a TCP/IP connection. That is all there is to the protocol.

If you were to use the telnet program to connect to the SWIT server, you could use the following to put up a button:

    % swit_server	# Start SWIT server.
    % telnet your_machine_name 4231
    => H SWIT_Server 1 0 sock5
    C button .hi -text Hi
    => R 0 0 .hi
    C proc hi {} {puts sock5 "E 0 hi_pushed"}
    => R 1 0
    C bind .hi <Button1> hi
    => R 2 0
    C grid .hi
    => R 3 0
	# Click on the button:
    => E 0 hi_pushed
	# Click on the button:
    => E 0 hi_pushed
								

Within the SWIT client library, everything is driven off of an event loop.

One important feature of the SWIT client library is the ablity to easily replicate an application window on more than one display. The primary reason for supporting multi-display applications is to simplify support. A user can call up their local support phone number and easily display exactly what they are seeing on the display of the person dealing with the help desk issue. The task of displaying the same window on mulitple displays is called cloning.

When an application window is cloned, it is possible to pass application control from user to user. For example, an application user calls up their support desk, clones the application, and the help desk person temporarily takes control, fixes the problem, and passes control back to the original user.

So how does all this cloning stuff work? Well, basically an application is represented as nested data structure -- application, top-level frames, frames, widgets, canvas objects, etc. Whenever a clone is made, the data structure is cloned. As changes are made to the master data structure, these changes are mirrored in the cloned version. The change mirroring is performed asynchronously so that slow data connections to the clone display do not slow down changes to the master data strucure. Furthermore, multiple clones are permitted, so each clone can be updated at a different rate.

So how does clone updating work? Well basically, each node in the master data structure contains a modification counter. Each time the master data structure is changed, the modification counter is incremented. A change lower in the master data structure also causes the each modification counter in the parent nodes to be incremented as well. When it time to update a cloned data structure, it is a simple matter of to verify corresponding nodes in the between the master and clone data structures to see what changed. Each node in the clone data strucutre that has an modification count that does not match corresponding node in the master data structure is updated and the count is made equal again. In fact, when a clone is made, it performs a lazy copy of the various nodes in the master tree.

Summary

The derived interfaces and source code are available.


Copyright (c) 1998 by amWayne C. Gramlich All rights reserved.