A General Framework for Constructing Java-based

Educational

Environments

by

Donald A. Garrett, B.S.

 

 

 

 

A Thesis Presented in Partial Fulfillment

of the Requirements for the Degree

Master of Science

 

 

 

 

 

 

 

 

COLLEGE OF ENGINEERING AND SCIENCE

LOUISIANA TECH UNIVERSITY

 

November 1998

Signature page, pull and replace.

ABSTRACT

This thesis defines an extension to the Watson Project. This extension is a standardized framework for all labs. The framework standardizes much of the behavior of the labs and simplifies the process of creating new ones. This framework also simplifies the process of updating the standardized components of the lab, which is of considerable importance in working around the many problems that have arisen with the AWT libraries in JDK 1.0.2. To avoid these problems, the framework moves to JDK 1.1.6 with Swing 1.0.2 and is intended to move to JDK 1.2 when available.

The framework includes an abstract base class for any lab. This class contains an activity manager for saving, loading, and evaluating student work; a help manager for handling the help system; and a dialog manager to simplify standard dialog interaction. An optional component in the framework (called Sled) is a syntax-directed editor based on special tags embedded in programs. To demonstrate the effectiveness, two labs are implemented based on the framework. The Graphics lab was ported from existing code, and the Prolog lab was created from scratch using the Jinni library.

Approval for Scholarly Dissemination. Pull and replace.

Table Of Contents

ABSTRACT*

LIST OF TABLES*

LIST OF FIGURES*

Acknowlegments*

CHAPTER 1 INTRODUCTION*

CHAPTER 2 BACKGROUND*

CHAPTER 3 CONTRIBUTION*

CHAPTER 4 CONCLUSIONS*

LIST OF TABLES

LIST OF FIGURES

Acknowlegments

I begin by acknowledging a good friend, Dr. Micheal B. O’Neal. I would never have finished this work without him. He has helped to prompt me to return and finish the work, served as the head of my committee, and provided a rent-free place to live while I worked. Indirectly, he has even provided distraction when needed. I had only to sit back and consider the meaning of that mysterious initial ‘B’.

I would also like to thank Dr. Barry Kurtz who has made a considerable difference in my education. He is one of the primary reasons that I feel I have really studied Computer Science instead of just programming and other technical skills.

Dr. Paul Tarau has been very gracious in serving on the committee of a student he has met only briefly, and continuing to help even after moving back to Canada. He has also provided the Jinni library used in this project and put up with my persistent questions when I did not understand some aspect of its behavior.

I would also like to thank my friends who have been very helpful all the way through. In particular, I want to thank Kevin Brunner, who finished his thesis first (leaving me no choice but to finish), and Dion Brooks, who put up with losing his business partner for almost six months.

I would also like to thank my parents and family. Upon hearing that their son was making yet another major change, they asked only (as always), "How can we help?"

CHAPTER 1

Introduction

Introduction

This thesis is intended to extend the Watson Project and to support the process of moving it to newer Java technologies. In particular, this aim has been achieved by creating a standard framework for all Watson labs, moving the Graphics lab to this framework, and reimplementing the Syntax-aware Language Editor (Sled) editor in terms of this framework. A new lab covering the rudiments of the Prolog language has also been implemented to demonstrate the general nature of the framework.

Justification

Java Changes

The Java language is currently going through rapid development, and new versions are being continually released that introduce new technologies to supplement or replace previous systems. Some of these changes allow for substantial improvements to existing systems, or they provide corrections to problems with previous versions.

The largest problems with Java’s platform independence have not come from poor implementations of the Java Virtual Machine (JVM), as one would intuitively expect, but from native portions of the standard libraries. The worst package in the standard libraries is the Abstract Windowing Toolkit (AWT) which uses a native "peer" for each interface component.

Unfortunately, Sun is not removing the native peers from the AWT in newer versions of Java. Instead, it has introduced the ability to create new components that are pure Java, without changing the builtin components with native peers. Pure Java components are known as "lightweight" and the components with a native peer are known as "heavyweight." They have modified the old components to introduce a simpler and more efficient event model.

Sun has released a set of libraries known as the Java Foundation Classes (JFC) which include a large collection of lightweight components. These components, known collectively as "Swing," are similar to the original components from the AWT but have many more features and are much more complex. The swing libraries will be a standard part of the Java 1.2 release [Sun98].

VErsion

Attributes

JDK 1.0.2

AWT

Heavyweight

1.0 event model

JDK 1.1.5

AWT, Swing as external library

Heavyweight and Lightweight

1.1 event model

JDK 1.2 (still Beta)

Swing, AWT

Lightweight and Heavyweight

1.1 event model

Table 1:JDK Support by Version

Watson Labs

The current versions of the Watson labs are implemented in Java version 1.02. Since the platform independence of Java has not proved to be as reliable as hoped, it is important to make use of newer versions and features that correct the problems now discovered. This task is somewhat problematic since the newer versions of the JVM are not yet as widely used as the older versions.

The current labs are also implemented as fully independent code bases, meaning that changes or corrections to one lab do not automatically propagate to other labs. It also means that each lab must implement all of the standard features for a Watson lab. Differences in these standard behaviors will arise subtly.

By creating a standard framework, we directly encode our standard behaviors, we reduce the total size of our code base (there is much less duplication), and we give a single location to adjust for many changes to the Java libraries. Any mechanism that reduces complexity will improve the chances of success for any project [Bro95].

Approach

Framework

The approach taken with the new framework is to implement a few classes designed to be extended to create new labs. These classes will leave well-defined blanks that are to be filled in for particular labs. The framework will define the following subsystems:

Labs

In order to demonstrate the usefulness of this framework, two labs have been implemented using the framework. It shows that the framework is useable, and it demonstrates that the framework is general enough to work for multiple labs.

One lab planned is the Graphics lab. This lab already exists and is usually given as the ‘standard.’ This makes it a good choice to base the behavior of the framework on and gives a good feel for how much work will be needed to port other existing labs to this new system. Graphics currently uses the Sled editor to allow users to edit programs that draw images on its drawing canvas. It can also create programs from images drawn directly by users. The Graphics lab is also capable of drawing animation sequences created by running programs. There should be sufficient complexity to locate most of the paint and event-related problems that arise from using the new Swing library.

The second lab planned is a Prolog lab. It will contain a Sled editor specialized for Prolog, and an engine to execute these programs. Depending on time constraints, it may contain some form of direct prolog interaction, or animation of the program execution.

Implementation

Packages

This new framework will be implemented in the package edu.LaTech.Watson. The primary interfaces will be the classes WatsonLab and WatsonDialog. The former is to be extended to create new labs, and the latter is extended to create new dialogs. These classes and their subcomponents will implement the core of the Watson look and feel as well as behavior. This behavior includes the help system, the activities system, and standard dialogs. Hooks for the Assist system will be added, but this system is not currently functional and will not be further extended as part of this thesis project.

A second general package soon implemented called edu.LaTech.Watson.Sled will provide the functionality of a general syntax directed editor. The main class in this package will be called SledEditor, and must be extended to provide language specific behavior.

The package edu.LaTech.Watson.Graphics will contain the lab-specific portions of the new implementation of the graphics lab. This lab implements a simple language for drawing images. Programs can be implemented in this system by working with the syntax directed editor, or by just drawing on the drawing canvas.

The package edu.LaTech.Watson.Prolog will be created to contain the new Prolog lab. This lab will be implemented in terms of the new framework and the new version of the Sled editor. It will also make use of the Jinni system as a prolog run-time engine. While a series of student activities will be implemented for this lab, they may not be appropriate for final publication. The point is to prove the suitability of the framework, not to determine which exercises are most suitable for teaching students. The lab will be useful, since it can be easily modified to finalize these activities.

Implementation will be done in either JDK 1.1.6 with Swing version 1.0.3. JDK 1.1.6 with Swing version 1.0.3 is not source or binary compatible with JDK 1.2, but it can be updated by changing the name of the swing libraries imported. Development would be done in JDK 1.2, if it were not still in beta, and if there were support from any browser.

Verification

Three issues need to be tested to validate the new framework.

  1. Does it encapsulate enough behavior to be useful?

  2. Is it sufficiently flexible to work with any reasonable lab?

  3. Does the new lightweight-based implementation avoid the platform-dependent problems previously encountered with Watson?

The first issue can be tested by examining the two labs. If there is any code in both of the lab-specific areas that should also exist in other labs, then the framework is incomplete. Conversely, if the labs are missing any standard behavior, the same is true.

The second issue is addressed by the fact that there are two different labs based on the framework. Since both labs are language based (though not all Watson labs are) there could be some tendency towards this type of lab. However, this result is not expected based on the preliminary design but can only be determined by careful examination of the finished product.

The possibility of further platform dependencies can be tested by running the resulting labs in as many environments as possible. In particular, we expect to test on Windows NT, Windows 95, Macintosh, and Solaris using the Sun, Netscape, Apple, and Microsoft JVMs as possible. Other platforms will be used if available.

CHAPTER 2

Background

Watson Project

The Watson Project was started by Dr. Michael O’Neal and Dr. Barry Kurtz. Watson has at its goal the creation of a new introductory class for Computer Science students based on the breadth-first approach [KO94]. The idea behind this approach is to teach new students a little about many aspects of computer science so that students have an overall perspective onto which to fit all that they learn in later classes.

Dr. O’Neal has been developing a textbook for an introductory course based on a "layered" approach. It starts with sections on how to use common applications such as spread sheets and databases. This layer is considered to be the outermost. The textbook then begins to show each of the conceptual ideas in how these applications are developed. It covers (very briefly) concepts such as graphics used to introduce the first "programming language"; then several types of languages are quickly covered. The book then moves on to assembly language, machine language, and finally circuit design.

Obviously, to cover all of these topics, the text can give only the briefest of introductions to each subject. This brevity causes problems since the authors also want the students to have hands-on experience with the fields being covered. Conventional tools for each of these subjects are far too complicated for beginning students to use for even simple tasks without spending more time on the tools than on the tasks the students are trying to learn about. This problem is further compounded because students would have to learn a new set of tools each week of the class!

The second part of the Watson Project addresses this difficulty by creating customized software for each of the labs the students must perform. Because this software is coordinated with students’ assignments, it can provide a simplified interface that reduces the learning curve involved in each lab, thus allowing students to focus on what they are trying to learn and to avoid unnecessary impediments to learning.

Previous Watson labs

As the project was first begun, Watson labs were developed in C on Sun workstations using the SUIT library [Con92]. This library was supposed to be somewhat platform independent, which would allow a single source base to be used for X-Windows, MS Windows, and Macintosh platforms. Unfortunately, the SUIT libraries were not as effective as first assumed. The labs were eventually available on for X Windows and MS Windows platforms, but they were inherently unstable.

Simple User Interface Toolkit (SUIT) was the GUI library used for the initial Watson labs. SUIT was developed at the University of Virginia, designed as a basic programming environment for people first learning about GUI (Graphical User Interface) programming, and to be portable across the windowing systems: X-windows, Macintosh, and MS-Windows [Con92]. It does the latter by having a series of libraries for different platforms, all with a common interface. This library, Simple Raster Graphics Package (SRGP), opens a local format window as a pure bitmap, and translates all events into an SRGP format consistent between platforms[Skl90].

SUIT Labs

Spreadsheet
Database
FSA
Data Structures
Graphics
Lisp
Assembly
Digital Logic

Table 2:SUIT Labs

The original SUIT labs used a complex three layered approach that allowed the instructors and programmers to create detailed scripts for users to work through [GOK95]. These scripts were referred to as activities. Each user’s work was saved for each activity, and the system kept track of which activities had been completed.

The first layer consisted of text messages stored in keyed text files that could be edited without recompiling. The second layer consisted of activity scripts which were very flexible but had to be written in C code. The final layer was the lab-specific components which had specific support for loading and saving their states. This scripting was not very difficult but not very natural for most programmers on the project. In the end, the scripting ability was never heavily used because very few people knew how to write complex scripts.

It is interesting to note that Java has specific support for property files, a more comprehensive form of keyed text file. Property files outdate the keyed text files used in the SUIT labs. It also has support for serialization, which is a way to store/restore an object. These partially outdate two of the three layers from the SUIT labs. The problems using the scripting suggest that the third layer should be abandoned.

The SUIT labs were extended beyond their three-layer system by adding an intelligent assistant to several of the labs. Upon a request for help, this layer would test the current state of the lab for a correct solution and provide detailed English explanations of any problems discovered [KMO95]. This system depended mostly upon the concept of a retrievable lab state provided by the activity level.

Java Watson Labs

New Architecture. When Java was introduced, Dr. O’Neal saw it as a way to greatly simplify the distribution and use of the labs associated with this project. Since web browsers are very common and Java programs can be distributed by the web, he saw web distribution as a way to remove the confusion of installation associated with using the labs on home machines. He considered this simplification of use very important since the software was aimed at beginning students.

At this point, Dr. O’Neal chose to treat the original labs as prototypes and began reimplementation of all labs (with corrections for earlier mistakes) in Java. He personally implemented the Graphics lab using JDK 1.02 as an example for student programmers to use with the other labs. While most of the labs have been rewritten in Java, continuing problems arise due to incompatibilities between different implementations of the Java Virtual Machine and because of difficulties inherent in managing many independent projects.

The new labs looked and behaved somewhat like the original ones, but they were implemented differently. Most of the layering in the original design was removed for the sake of simplification. Activities continued to exist as before, but no step-by-step interaction with users leads them through the activities. They are given a goal (perhaps just to view an example) and are left alone with the lab specific components. Testing for proper completion is desired but not yet available for any of the labs, except digital. No intelligent assistant has yet been provided, but it is expected that this feature will be reimplemented as well.

JDK 1.0 Labs. Several features that are similar among all the labs: they all have a set of activities that the user can choose among, they all have a help system based on a "What is" button, they all have an activity control dialog, and they all have matching exit buttons.

Java Difficulties. The Java Virtual Machine (JVM) creates a computational environment for writing programs that can run on a virtual machine without changes, binary or otherwise. Unfortunately, programs must interact with the system they are running on to some degree to be useful (at the very least to report results). The JVM attempts to perform I/O by providing libraries with a standard interface and using native libraries specific to the host system to implement that interface. For many types of system interaction, this strategy works very well. For example, memory allocation appears to be the same on all platforms even though the underlying mechanism may vary wildly.

However, some portions of the standard libraries are not as successful. The package most notorious for these flaws is java.awt and its sub-packages. This package provides the only GUI framework available to Java programs on all platforms. It is expected to be a difficult package because GUI systems tend to vary far more in their implementation and exact behavior than other systems (such as memory allocation). Shortly before the initial release of Java, Sun chose to write a version of the AWT that uses native peers, done at the insistence of Netscape so that Java programs would always look like programs written to be native to the machine they were running on.

With heavyweight peers, it becomes the job of the native peer to translate the native behavior into the Java standard behavior. The problem is that that behavior is extremely complex, since these peers exist for each GUI widget (such as a button or label) and their behavior is not very well defined. If different native peers appear to work differently from the Java side, then platform specific behavior is introduced.

The platform specific behavior of native peers turned out to be a major problem. Different implementations of the JVM on the same platform tended to be incompatible because these peers were implemented differently, and because many of the peers had various and assorted bugs, meaning that the platform independence of GUI applications is heavily weakened.

Sun recognized the difficulties with these incompatibilities and began moving to correct it with the introduction of JDK 1.1. With this updated development kit, it became possible to write lightweight components that had a pure Java peer, meaning that their behavior is equivalent on all platforms. Heavyweight peers still exist (as they must to allow GUI interaction with the local system), but they do not have to be implemented separately for every type of widget. This increases the granularity of the interaction, and thus simplifies the total interface. Sun chose not to remove the old widgets or to implement any lightweight widgets at this time; they only made it possible for other people to implement lightweights.

Sun has since recognized the need to provide standard libraries of lightweight widgets, and the need to provide more complex and flexible components than the original AWT library. They have released the Java Foundation Classes which include a GUI component known as swing. The current package name is com.sun.java.swing.*. has been provided to allow preliminary testing and usage. Sun intends to release this package as java.swing.* as part of JDK 1.2. Sun does not seem to have any plans to remove the AWT package so all of the heavyweight peers will still be available (and required on every platform). To avoid the problems with heavyweight, it is necessary to switch to all swing/lightweight components.

The Swing libraries are entirely revised equivalents of the earlier AWT classes with lightweight peers. All standard swing components extend the class JComponent. This implements a good deal of behavior that was desired, but unavailable in the AWT classes. Improvements include automatic handling of double buffering, defined paint ordering, improved event handling, tool-tip style help, and a tremendous amount of flexibility in what components can display. For example, a label can hold an image or a custom class instance as well as the traditional text messages.

Heavyweight peers were originally designed to allow components to adjust to the native look and feel of any operating system. Swing components employ a system called plugable look and feel that uses a user-configurable look and feel for all of the standard components. This use achieves the same effect but is entirely implemented in Java so that it remains portable. This functionality does not have a finalized interface at this time, but will when JDK 1.2 is released.

Figure 1:Metal Look and Feel

Figure 2:Motif Look and Feel

Figure 3:Windows Look and Feel

Figure 1, Figure 2, and Figure 3 show the same dialog generated with the Metal, Motif/CDE, and Windows look and feel. All were generated from the exact same code and involved no differences other than the command line parameters passed to the program. They vary by color, size, and key strokes recognized for navigation. Further examples in this document will be shown in the Metal Look and Feel since it is the default for Java. It is expected that Sun will add additional choices in later releases of Swing.

CHAPTER 3

Contribution

Framework

Reason

The new framework is designed to implement standard behaviors for all labs so that the only work needed to create a new lab is the work of creating the lab-specific components and code to manipulate them. In the initial Java Watson labs (unlike the SUIT labs), the first lab was written as an entirely stand-alone effort. Additional labs copied the code from the first and then modified it as needed. This meant that all programmers had to learn how all of the lab behavior was implemented to customize to their specific labs. It also meant that bug fixes, changes, and improvements had to be rewritten separately and tested for each lab.

The design presented here qualifies as a framework, not just a shared library, because it encodes a large number of design decisions related to writing a lab [GHJV95]. The fact that is a framework reduces the amount of information that programmers have to learn about standard lab behavior. Instead of always starting from scratch, programmers have only to worry about the pieces of the system specific to their labs. By sharing code, the framework also reduces the difficulty of updating or improving systems that are shared among all labs.

Design Overview

The new framework for Watson is implemented in 21 classes contained in the package edu.LaTech.Watson. The central class in the design is WatsonLab. WatsonLab is an abstract class designed to be extended by the main class in each new lab. It implements the standardized portions of the user interface directly and contains managers that implement the rest of the standard interface. These are the ActivityManager, HelpManager, and DialogManager.

The standard components are shown in Figure 4. They constitute the main window itself, title bar (showing lab name and activity name), and the controls to change activities, ask for help, control the current activity, or exit.

Figure 4:Standard Lab Heading

The framework also includes a variety of general classes designed to help with various problems. These include such things as the SizeRegulator, which enforces minimum and maximum sizes for a window or dialog; LineLayout which is a Layout Manager that places components in a column or row with various options, or MultiLineLabel, which is a label component that can word-wrap text. Many other classes are implemented to support the various managers.

The class WatsonDialog is provided as a base class for all dialogs. It implements certain standard elements such as a size regulator to make certain that no dialog grows bigger than the screen, and a method to center a dialog over the lab. The most important function of this class is that it gives a central location for updates and solutions to problems with dialogs on any new system. This is also one of the purposes of WatsonLab.

For clarity of discussion, the new framework and labs based on it will be referred to as Watson 2.0. The first generation of Java-based Watson labs will be referred to as Watson 1.0. The SUIT based Watson labs will be called proto-Watson.

Activity manager

Overview. The activity manager is intended to implement all aspects of how activities behave. Some aspects of this behavior are split between the activity manager and WatsonLab, but most of the behavior is implemented by the manager. The implementation was split because a few aspects seemed to fit for naturally into WatsonLab. Some aspects of activity management have equivalent user-interface components directly on the main lab that are standardized across all labs (and thus belong to WatsonLab). Other aspects of activity management need to be specialized for each lab, such as getting and setting the state of the user’s work. It seemed simpler to have these aspects handled in a class that was already being extended for each new lab, especially since most of the values being read and set are stored on the specialized version of WatsonLab or on one of its members.

An activity is a task that the user should perform. These lab activities are directly related to assignments from the course textbook. The details of an activity are very lab specific. In the Graphics lab, some activities are prewritten example programs that the user should run to see what they do. Other activities involve creating programs in different ways.

User Interface. Whenever a lab is started, the activity manager begins with no activity loaded. To enforce this it disables all of the lab specific components. It also attaches a mouse listener to these components that will ask users to select activity if they try to use the disabled components.

Figure 5:Activity Selection Dialog

To pick an activity, users must press the Activity button at the top of the lab (see Figure 4) which displays a dialog with a list of the available activities (see Figure 5). If the users are currently in an activity when they select a new one, the state of the current activity will be saved and the new activity loaded. If a student had previously visited the new activity, then its previous state is restored. If an activity is being visited for the first time, the lab is initialized with a beginning state specific to that activity.

Figure 6:Activity Control Dialog

Whenever a new activity is started, or the Controls button is pressed (see Figure 4) the Activity Control Panel (see Figure 6) is displayed. This panel contains a description of the activity, and various activity related controls.

If the user thinks that an activity has been completed, he or she can press the Done button to have the lab test for a correct answer (not always implemented). If the student wants to start an activity over from scratch, it can be reset using the reset button. This move will cause all work for the activity to be lost, but it will reload the initial state. If a student is really lost and needs help, she or he can use the Assist button. However, at this time the assist button will not be much help since all it does is produce a dialog explaining that assistance has not yet been implemented in the Java version of Watson.

Programming Interface. In practice, the ActivityManager will have only one method that will be called by programmers adding new labs. That is registerActivitySet(). It is generally called from the constructor of each lab to inform the manager of the activities available. The parameters tell the manager the name of each activity, give a description of it, and give the starting state of the lab when the activity is begun.

However, programmers will have to override a few methods on WatsonLab that the ActivityManager will call. These are getState(), setState(), and isActivityComplete(). getState() and setState() are used to load and save the users work in the lab. The value returned by getState() is a Serializable.

Serializable is an interface, introduced in JDK 1.1, that is related to converting a class to a stream of bytes and restoring, meaning that the state value can be converted and then saved to disk or sent across the network, then converted back to a value at a later time. This flexibility is not now used, but it provides the needed functionality to add permanent storage of the users work, reporting of the users work to a grader, or it can provide many other possibilities.

Since the type returned by getState() is only loosely known, the only requirement is that setState() be able to accept any value returned from getState() or passed into registerActivitySet() as the initial state for an activity. It also accepts null as a signal to move to an empty state (for example, when between activities).

isActivityComplete() is a method used by the manager to determine if a user has successfully completed an activity. It is passed the state, and an activity identifier and expected to return a true or false. If there is no test to see if a user has finished an activity, it is assumed that any solution is correct (i.e., this method always returns true if not overridden). Otherwise, users would not be able to complete activities that lacked completion testing.

Help Manager

Overview. The help manager implements the help system. The help manager is independent of the type of window it provides help for. It is intended to be usable with any JRootPane (such as JDialog, or JFrame). All it requires is that there be some way to activate help mode and that calls be made to register the actual help messages. The components which have help associated with them do not need to have any support for the primary help mechanism at all. This means that the help system can be used with standard components, not just components developed as part of Watson. Tool tip help messages are also supported, but they use the Swing mechanism, and require that the components extend the class JComponent. Since all Swing components are based on this class, it should not impose a heavy difficulty.

User Interface.

Figure 7:Tool Tip

Tool tip help is a very simple style of help that has become popular in many windows applications. Whenever the mouse lingers over a piece of the interface, a small message will pop up explaining what that component does. Figure 7 shows an example of such a help message.

Figure 8:Help Selection Mode

The help manager offers another mechanism for viewing more complete help messages. Each lab (and some dialogs) have a "What is?" button that users can press to go into help selection mode. When they enter this mode, the cursor changes (as displayed in Figure 8). When in this mode, users can click on any component to see a dialog with a help message associated with that component. The cursor (and other behavior) returns to normal after a help dialog (shown in Figure 9) has been shown. If they click on an area with no help message, nothings happens and they remain in help selection mode.

Figure 9:Help Dialog

Programming Interface. When a help manager is constructed, it must be associated with a JRootPane and a Frame. The former is the area that help will be provided for, the latter is the frame associated with all dialogs. It is the responsibility of the dialog or window to provide some mechanism for entering help selection mode. This mechanism must call helpSelectionRequest().

Help messages must also be registered with the help manager for any component that is to have a help message. This is done by calling registerHelp(). registerHelp() requires a reference to the component for which help is being registered, the name of the component, a tool tip message, and a lengthy help message. The tool tip may be left empty if it is not desired (tool tips for an editor window are very annoying). Tool tip messages will be ignored if the component is not a Jcomponent, however, lengthy help messages can be used with any type of component.

Help messages can be registered for a container if there is a need to register a help message for all of the components in the container. Help requests for the specific components will return the help messages for the entire container. Help messages for specific components will override the help messages for the container. By registering a help message for the root frame, a default message can be set for all help requests.

Dialog Manager

Overview. The dialog manager contains very little code, but uses many other classes to do its job. It contains some standard user input dialogs for use throughout the Watson Project. For each type of dialog an access method creates and invokes each dialog in a standard way. Each of these methods returns the value entered by the user, which simplifies the code involved in invoking a dialog.

User Interface. Some of the dialogs are intended for number entry. These are displayed in Figure 10 Decimal Entry Pad, Figure 11:Hexadecimal Entry Pad, and Figure 12:Binary Entry Pad. These allow entry in binary, decimal, and hexadecimal respectively. Other dialogs allow the user to choose from a list of strings (Figure 13:Choice Selection Dialog), input a text string (Figure 14:String Input Dialog), select a simple yes or no (Figure 15:Yes No Dialog), or simply view a message (Figure 16:Message Dialog).

Figure 10:Decimal Entry Pad

Figure 11:Hexadecimal Entry Pad

Figure 12:Binary Entry Pad

 

 

Figure 13:Choice Selection Dialog

Figure 14:String Input Dialog

Figure 15:Yes No Dialog

Figure 16:Message Dialog

Programming Interface. The type of interaction supported (call a method, get a response) allows dialog interaction to be written in a very straightforward way. The code sample in Figure 17 implements the handler for the Activity button from WatsonLab. As this code shows, the dialog can be invoked and the results handled in the same method. Previously, dialogs were handled in an asynchronous manner which separated the invocation of a dialog and the handling of the result.

public void pickActivity()

{

// if an activity set was never registered, we can't show a

// list of them.

if (titles.length == 0)

{

lab.dialogManager.showMessage("No Activities",

"This lab has no activities to

"select from");

return;

}

// Ask the user to pick an activity from String[] on manager

int choice = lab.dialogManager.askChoiceIndex(titles);

// It's -1, if they cancelled out

if (choice != -1)

setActivity(choice);

}

 

Figure 17:Sample Code using DialogManager

The methods on the DialogManager are relatively simple. Figure 18:Sample Code implementing askChoiceIndex() shows an example method that implements askChoiceIndex() called in Figure 17.

public int askChoiceIndex(String[] choices)

{

ChoiceSelector dialog = new ChoiceSelector(frame, choices);

dialog.center();

dialog.setVisible(true);

return dialog.getSelectionIndex();

}

 

Figure 18:Sample Code implementing askChoiceIndex()

Since all of the wrapper methods are so simple, it seems worth explaining the importance of this manager. There are two related reasons for it. These operations are performed frequently from many different parts of the program. Unifying the dialog handling reduces code length, and increases the reliability and consistency of the application. It also gives a central location to make updates to this code. This is important since dialogs (even with Swing) involve heavy weight peers. It is quite likely that adjustments to the way that dialogs are used will be required before the application will run on the broadest possible variety of platforms. This is the same reason that WatsonDialog is used as a base class for all dialogs.

Sled

Overview. Another package associated with the framework is edu.LaTech.Watson.Sled. This is a heavily reworked version of the Sled editor first introduced for the Graphics lab in Watson 1.0. That editor was based loosely on the Syntax-aware Language Editor library written for proto-Watson by Alex Ramos in the early 1990’s. While the implementation of Sled has changed dramatically in Watson 2.0, its user interface is almost identical to the versions of Sled used in various Watson 1.0 labs.

User Interface.

Figure 19:SledEdit Component

Figure 19 shows an example of the GraphicsEditor class which is the Watson Graphics Language extension of the class SledEditor. The buttons to the right hand side are not part of the editor but interact with it, so they are are included.

The small black triangle to the left of a blank line shows the insertion point. It can be moved to different lines by clicking in the leftmost column. This "insertion point" shows where new lines will be added to the program. The buttons on the right will insert templates for different types of language constructs. Figure 19 illustrates with an example program. The color statement is an incomplete template. A finished line would show a specific color, not the placeholder COLOR_NAME.

Figure 20:SledEdit Choice Dialog

Moving the mouse pointer over different parts of the program in the editor will cause editable units to be highlighted. Clicking on them will bring up choice selection dialogs. The choices presented to the user are specific to both the type of unit and the language. Figure 19 illustrates a case where the cursor is pointing at the color name placeholder of a color statement. Clicking in that example would bring up a dialog showing the different colors that could be used in that statement. Figure 20 shows the exact choices that would be available in this example. Selecting one of these colors would cause the program in the editor to be updated so that the color statement would show the appropriate color.

The small circles that appear next to each program statement in Figure 19 allow deletion. Pointing at a deletion symbol will highlight a unit of code (usually either individual statement or multi-line code block). Clicking on the deletion symbol will cause the highlighted text to be deleted.

Programming Interface. The SledEditor class is an abstract class that must be extended to create a language specific editor. It provides two distinct functions (and should therefore probably be split into two different classes). The first function is to handle all user-interface aspects of the editor, meaning that the editor is a component which can be added, positioned, or sized like any normal component. It handles painting, display, and user events.

The second aspect is that it stores the state of the current program and provides many methods for editing, searching, and manipulating the program. The current program is actually stored in an internal format that includes special tags to store syntactic level knowledge about the program.

Internal Representation. These tags are of the form <~tag~> token contents <~/tag~>. They always consist of a matched tag pair with the tag name stored in both the open and close tag. Tags can be nested to any depth and can contain any content that does not include <~ or ~>. They cannot, however, be interleaved. A pair of tags are referred to as a token. The class SledToken is used as an atomic value that represents a pair of tags. Many manipulation methods accept or return SledToken. Since SledTokens hold specific line and indexes into the program being edited, they must be considered invalid after a program is updated.

color(red)

d1 := 50

p1 := (150, 150)

repeat 10 times

loop

c1 := (p1, d1)

draw(c1)

increment(d1, 10)

erase(c1)

endloop

 

Figure 21:Sample Graphics Program

A sample program such as Figure 21 might be represented internally with something like Figure 22. Extra line breaks were added to make the tagged version fit on the page.

<~color~>color(<~colorname~>red<~/colorname~>)<~/color~>

<~assign~><~assignLHS~>d1<~/assignLHS~> :=

<~dist~>50<~/dist~><~/assign~>

<~assign~><~assignLHS~>p1<~/assignLHS~> :=

<~point~>(<~dist~>150<~/dist~>,

<~dist~>150<~/dist~>)<~/point~><~/assign~>

<~loop~>repeat <~count~>10<~/count~> times

loop

<~assign~><~assignLHS~>c1<~/assignLHS~> :=

<~circle~>(<~point~>p1<~/point~>,

<~dist~>d1<~/dist~>)<~/circle~><~/assign~>

<~draw~>draw(<~object~>c1<~/object~>)<~/draw~>

<~incr~>increment(<~distvar~>d1<~/distvar~>,

<~amount~>10<~/amount~>)<~/incr~>

<~erase~>erase(<~object~>c1<~/object~>)<~/erase~>

endloop<~/loop~>

 

Figure 22:Internal Format of Sample Program

If the user points the mouse at the word ‘erase’ on the second to last line, the editor searches for the innermost token surrounding that word. In this case it would find <~erase~> and <~/erase~>. Since these tags surround the whole line, the whole line would be highlighted. If the user instead pointed at ‘c1’ on the same line, the smaller token for <~object~> would be found instead.

When the user clicks on a word, the edit method is passed the same token used for highlighting. The editing method bases the choices offered to the user (in part) on the tag of the token, such as ‘erase’ or ‘object’.

Operations such as deletion are based on finding the smallest token that surrounds a line. For example, clicking the delete symbol for the line with the erase statement would delete the ‘erase’ token and nothing else. Clicking to delete the endloop would delete the entire ‘loop’ token. This token extends across several lines from before the repeat until after the endloop.

Language Specialization. All editors have some outside means of inserting new statements and code. Usually insertion is done by having outside buttons that insert incomplete statement templates, but more complex means can also be used. The Graphics lab allows users to draw programs interactively and have the code to perform the same task written automatically. Such new code is normally added to the program at the current insertion point using the method insert().

The only method that must be written to create a Sled editor for a specific language is the onEdit() method. This method is called for whenever the user requests editing of a SledToken. The method is passed the SledToken surrounding the point that the user has requested to edit. This method normally does different processing for each type of token tag that can exist in the editor.

onDelete() can be overridden to catch all deletion requests from the user, allowing special processing to be performed if needed. For example, the GraphicsEditor class does not allow the final point in a polygon constant to be deleted. If onDelete() is not overridden, the method will prompt the user for confirmation and then delete the results of getToken() for the line which the user requested to delete. The block deleted should match the highlighting performed when the delete circle was pointed at.

setInsertLine() can be overridden if there is some reason to limit or control where the insertion point can be set. It is most commonly used to prevent new statements from being inserted in the middle of an existing statement. The convention is to move down from an illegal insertion point to the first legal position.

findIndent() allows specific editors to add indention to a language. It is called with a line number to discover what the proper indention for that line is. The default method returns 0 in all cases. The method reindent() is always called to recalculate indention after any line for group of lines is edited. If an edit may affect the indention of lines that are not otherwise modified, then reindent() must be explicitly called for the other affected lines.

Two methods are called to generate the tokens used for most editing methods. These are both named getToken(). The first is passed a line number, used when an operation is line specific (such as deletion). The second is passed a line number and an indention value (measured in untagged characters). It is used when the mouse points at some specific area. Editing methods may do specific searches to learn about additional information in the program. Token-searching methods such as findTokenForward(), findTokenBackward(), and findSurroundingToken() are provided.

The static method buildToken() creates a new string correctly tagged with open and close tags. New strings that contain tags should be built up with one or more calls to this method to make sure that all tags are correctly built. For example:

buildToken("point", "(" +

buildToken("dist", "X") +

',' +

buildToken("dist", "Y") +

')' );

Would build the string:

<~point~>(<~dist~>X<~/dist~>,<~dist~>Y<~/dist~>)<~/point~>

Debugging Support. SledEditor provides some debug support. Such support exists because it is possible that bugs in the implementation of a lab could result in the construction of programs with corrupted tags. The most common reason for this error is insertion of incorrectly built constant strings in the code (perhaps buildToken was not used), or because invalid SledTokens are used. It is very important that all language specific-versions of the SledEditor prevent this problem from occurring. The language specific version must pass a list of legal tags to the SledEditor class during construction.

If the language-specific version sets the debugLevel value member to DEBUG_VALIDATE (a constant on SledEditor), then the entire program is validated for correctly matched pairs of tags, and to make certain that no tags exist that do not match the tag names in the expected list. The validation is performed immediately after every edit operation. If debugLevel is set to DEBUG_DUMP, then this same validation is performed, but the tagged contents of the editor are also dumped to the console after every edit, allowing lab designers to see the exact effects of any edit operation. The debugLevel should be left to the default DEBUG_NONE when in production use for maximum efficiency.

Invocation and Distribution

The framework described in this thesis is in the package edu.LaTech.Watson. The framework extension for Sled is in the package edu.LaTech.Watson.Sled. The graphics lab and the prolog lab implemented with the framework are in the packages edu.LaTech.Watson.Graphics and edu.LaTech.Watson.Prolog. It is intended that each additional lab be added to its own package with a similar naming scheme. All of the class files in the project are normally bundled together into Watson.jar, allowing a single file to be distributed that includes all of the labs as well as all of the framework.

Application. One class has been defined in the default package. It is named Watson and is used to manage the various ways of launching the labs. It is both an applet and an application. If Watson.jar and swingall.jar (the jar file holding swing) is in the current directory, then the Watson class can be invoked from the Java Runtime Environment (JRE) with "jre -cp Watson.jar;swingall.jar Watson". This will attempt to launch the application Watson.

G:\public_html>jre -cp Watson.jar;swingall.jar Watson

No command line arguments found.

Syntax: Watson [-look lookName] labname

Example:

java Watson Graphics

Lab Names:

Graphics

Prolog

Look and Feel Names:

Metal

CDE/Motif

Windows

 

Figure 23:Watson Program Invocation

As one may see from Figure 23, Watson requires a parameter to tell it which lab the user wishes to invoke. The list of labs shown comes from an array in the Watson class that must be updated for new labs as they are written. Classes can also be invoked by their exact class name (example: edu.LaTech.Watson.GraphicsLab). The ability to invoke labs that are not yet listed as available is useful for labs which are under development but not ready to be advertised.

The command line also allows the user to set the look and feel to be used by swing. It will automatically list all look and feels supported by the swing library version in use.

A full command line that invokes the Graphics lab with the windows look and feel might look like

jre -cp Watson.jar;swingall.jar Watson –look Windows Graphics

Applet. The class Watson can also be embedded in web pages as an applet. This embedding will probably not be useful until after JDK 1.2 is released, and browsers are modified to support it. It will eliminate the need to download the swingall.jar file (2 meg in size), and give the browser makers another chance to make their Java support work correctly.

<APPLET CODE="Watson.class" ARCHIVE="Watson.jar,swingall.jar"

WIDTH=200 HEIGHT=100>

<PARAM NAME="Lab" VALUE="Graphics">

<PARAM NAME="Look" VALUE="Windows">

</APPLET>

 

Figure 24:HTML for Watson Applet

This HTML sample in Figure 24 shows how to invoke the Watson class as an applet and load the Graphics lab with the Windows look and feel. Changing the parameters passed to the applet would change which lab or look is used. The look parameter can be omitted (similar to the application version). Invoking a lab as an applet will place only a start button inside the web page. Pressing this button would cause an actual copy of the lab to start in its own window.

Labs Implemented

Graphics

Figure 25:Graphics Lab

Overview. The graphics lab was first developed as part of the proto-Watson Project. The lab was reimplemented by Michael O’Neal as the first lab in Watson 1.0. Dr. O’Neal’s source (along with the code contributed by J. J. Walker) was used as the basis of both the new framework and more specifically for the Graphics lab in Watson 2.0. This lab contains four major areas: Variable Declarations, Program Code, Drawing Window, and Program Execution Controls.

Variable Declarations. This area shows all variables that have been declared. The buttons in this area may be used to declare additional variables. The names of new variables are automatically chosen by the environment to minimize keyboard input. They consist of a single letter indicating the type of the variable along with a number to make it unique among all other variables of the same type. If the lists of variables become too large for the window, vertical or horizontal scrollbars will appear.

No variables can be used in the program area unless they have been declared in the variable declarations window. When the drawing area is used interactively (described below), each drawing operation declares a variable of the type being drawn. Once declared there is no way to remove a variable declaration, but there is nothing that forces variables to be used.

Program Code. This area is an instance of GraphicsEditor, the graphics language specific SledEditor. Like variables, it will sprout horizontal or vertical scroll bars if needed. The buttons included add template statements that must be completed with the editor. This editor can receive code added to it by the Drawing Window when interactive drawing is enabled. Any new code is always inserted at the insertion point.

Polygons help stretch and test the abilities of the Sled editor. They are shown as multi-line values with each point of the polygon on its own line. The first point and the last point always match exactly. Editing one causes the other to change automatically. Deleting a line out of the middle of a polygon is allowed and is the only way to remove a vertex. Attempting to place the insertion point inside a polygon will insert the template for a new vertex at the insertion point, but the insertion point will be moved below the polygon. It wouldn’t do to allow people to add new lines of code in the middle of a polygon.

Drawing Window. The drawing window has two different purposes. When a graphics program is run, the results are painted in the drawing window. When the lab is in interactive drawing mode (for some of the activities, but not all), the user can declare a variable, then draw an object of that type using the mouse directly on the drawing window. The code to perform the same operation is automatically generated and added to the program code area.

This window also shows the coordinates of the cursor whenever the cursor is over this window. These coordinates are measured in the same system that drawing is done in. Specifically, the Watson graphics coordinates for window are 300x300 measured from the bottom left. The actual number of pixels in the window depends on the size of the lab (drawn images are scaled appropriately). Java components use the top left for their coordinate origin.

Program Execution Controls. This area contains two buttons. The Walk button will button will execute the current program one line at a time. The line last executed is highlighted. If the program is modified, then this line-by-line execution is reset. If the Run button is pressed, the entire program is executed from scratch. If the Run button is pressed during a walk through, the program is reset and then executed. Dialog messages will be brought up if the program is not valid in any way.

Watson Graphics Language. The Watson Graphics Language is a very simple language. It is designed to be the very first programming introduction in the Watson Lab series. It has five data types: Distance, Point, Line, Polygon, and Circle. All of these directly correspond to an object that can be drawn except for Distance. Distance values represent distances across the drawing area. They can be used instead of constant numbers to create expressions of the other object types.

There are seven types of statements in this language: Assign, Draw, Erase, Color, Loop, Increment, and Decrement.

var := expression

No variable may be used for any purpose until a value has been assigned to it. The expression on the right hand side must match the type of the variable. It may either be a constant expression of the given type, or a variable of the given type which has already been assigned a value.

draw(var)

The draw statement paints the value of a variable in the drawing area using the current color. It can only accept variables that have valid contents. It can accept any variable type except Distance.

erase(var)

The erase statement does the same thing as paint except that it paints the object in the background color for the drawing area. Drawing an object then erasing it will make the object invisible.

color(color)

The color statement changes the default color that will be used for future paints. It accepts one of the words: red, blue, green, yellow, orange, black, or white as an argument. The default initial color is red.

repeat COUNTER times

loop

…contents…

endloop

The loop statement repeats the statements inside it a fixed number of times. Counter can be set to a number between 1 and 99, but a variable cannot be used. A loop can contain any number of statements, and they can be of any type (including nested loops).

increment(distance, amount)

decrement(distance, amount)

The increment and decrement statements are almost identical. Both of them accept a distance variable (which must already have a value in it) and increment it or decrement it by a constant integer amount.

Prolog

Figure 26: Prolog Lab

Figure 26:Prolog Lab

Overview. This lab is a prototype of a Prolog lab. It is currently functional but does not provide as much assistance and protection as a finished lab needs to do. It is possible to write and execute valid Prolog programs, but it is also possible to write programs that produce situations that the lab cannot handle. Execution of a program requires two parts. One is the program itself, and one is the goal to work towards. The program is edited in the Program Code area, and the goal is specified in the unlabeled box in the bottom left. Results are displayed in the Prolog Output Console area. Programs can be executed by pressing the Run button, or by pressing enter in the goal type-in box.

Program Code. This is an instance of the class PrologEditor, an extension of the class SledEditor. It is specialized for writing prolog facts and rules. These provide the information used to execute Prolog programs.

Goal Box. The goal box specifies what answers the inference engine is trying to reach during program execution. This box offers two ways of specifying a goal. For some activities, it allows the user to type in a goal. It also has a pull down list that shows the goals predefined by the activity, as well as legal goals that were previously typed in.

One of the problems with this component is that it allows students to type their own goals. These are not properly checked for correct syntax, or for usage of built in prolog statements that the lab does not properly support. Unsupported actions include file access or networking operations.

Prolog Output Console. The prolog output console is a scrolling text console that captures the output from the prolog engine when prolog programs are executed. It does not accept user input like a traditional prolog console. This area is cleared each time a new program is executed or the current activity is changed.

If the program output contains multiple solutions, they are all displayed in this console. If there is a very large (or infinite) number of solutions, then only the first hundred will be displayed.

While there has been an effort to make the output a little more friendly than the traditional prolog output, further effort is needed before the lab is released. In particular, since the lab attempts to find all solutions to a goal, solutions that can be found through more than one path appear more than once. It is possible that an infinite number of answers will be found if there are an infinite number of paths to the solution of a problem.

Program Execution Controls. This contains a run button. This button causes the current program and the current goal to be passed to the prolog engine to try to find one or more solutions. The results will be displayed in the output console.

Jinni. The prolog execution engine is provided by Dr. Paul Tarau [TAR98]. This system Java Inference engine and Networked Interactor (Jinni) is a general prolog system designed to complement his more traditional prolog system known as BinProlog. Jinni is much more comprehensive than the tools needed for this lab. It includes systems for multi-threaded evaluation, and distributed processing, as well as the more traditional prolog tasks (such as files access) that are outside the scope of our teaching environment.

Jinni is in the package tarau.jinni. The version used is 1.7.5. It is not modified from the standard distribution in any way, but some modifications were made to its interface to accommodate the needs of this project. This package was developed for JDK 1.02, but it also works correctly in JDK 1.1. It does use some deprecated portions of the Java libraries, but only causes compile warnings that can be safely ignored.

Watson Prolog Language. The Watson Prolog Lab uses a very minimal subset of prolog. The Jinni engine supports a trimmed down operatorless syntactic subset of Prolog. The Prolog editor used further restricts what can be written. These limitations are imposed in an attempt to make Prolog more digestible for the beginning students.

Prolog programs consist of collections of facts and rules that can be used to calculate additional facts.

fact(value).

fact(value1, value2).

fact(value1, value2, value3).

 

Figure 27:Fact Formats

Facts follow one of the forms in Figure 27. The names of facts are simple strings that start with a lower-case letter. The values are constant values. None of the more complex expressions allowed by Prolog are allowed here, including lists and variables.

Rules are somewhat more complex. They have a left hand side very similar to facts, but they have a right hand side that tells when the rule is true. Rules may have variables or constants on the left hand side. If they have variables, they will be named A, B, or C based on their position. The user has no choice.

No rules or facts may exist that have the same name but different arities. No rules or facts may exist with an arity not between one and three, inclusive. No rules or facts may exist that have matching names and arities for any built in expression. Lists are not supported in any way. List support is probably needed for the final version of this lab.

eq(VALUE, VALUE)

compute(OPERATOR, VALUE, VALUE, RESULT)

min(VALUE, VALUE, RESULT)

max(VALUE, VALUE, RESULT)

less(VALUE, VALUE)

greater(VALUE, VALUE)

lesseq(VALUE, VALUE)

greatereq(VALUE, VALUE)

 

Figure 28:Builtin Expressions

Rules will have one or more TERMs on the right hand side. If there are multiple TERMs, they will be anded together. A TERM may consist of a reference to a user-defined rule or fact, or else a reference to a native expression (listed in Figure 28). The arguments to any term may be a variable or a constant value. The variables are not constrained to match the variables from the header.

To execute a Prolog program there must also be a goal. The program lists all facts that are known, and rules for building additional facts. The goal is a fact that the Prolog engine attempts to show as true. If the goal contains all constant values, then the engine will return either true or false.

If the goal contains variables, then the engine attempts to find values for the variables that make the goal true. The current engine tries to find all possible values for the variables that make the goal true. Since the number of possible solutions may be infinite, the lab restricts itself to the first hundred answers found. Traditional Prolog systems provide only a single solution, but provide a means to solve for additional answers.

Cross Plateform Testing

Testing has been performed with the following environments:

All tests were performed using Swing version 1.02, and were performed by loading the program as an applet. Testing as an applet greatly simplified the process of providing the same binary in a uniform way to the different environments.

Sun JDK 1.1.5 on NT appears to be the implementation most strictly correct. The only problem is that repaints after closing a dialog flash horribly, if the application window is overlapping another windows application.

Sun JDK 1.1.6 with JIT disabled on NT appears to work correctly except that the sizes of dialog borders are not figured correctly or consistently. The errors are one or two pixels in size, and only cause problems for dialogs that have a very tight layout. A general workaround for this problem has been added to WatsonDialog.

Sun JDK 1.1.6 with JIT disabled on Windows 95 appears to have a more serious version of this problem. All applet windows contain a banner that announces them as applet windows (to keep applets from spoofing standard windows). The JDK on 95 does not seem to add the size of this banner into the size of the window borders, causing windows to be sized incorrectly. The problem does not affect programs running as applications.

Sun JDK 1.1.6 with JIT enabled on NT has the same problems as JDK 1.1.6 on NT with JIT disabled. It runs more quickly (but takes longer to load). However, Jinni appears to trigger serious bugs in the JIT. The environment will crash if there is any attempt to run a prolog program. The Jinni console application has similar problems. This behavior is defiantly caused by errors in the JIT since the Java environment crashes instead of performing an orderly shutdown.

Sun JDK 1.1.6 with updated JIT on NT is capable of running some prolog programs without crashing. However, repeatedly running any program quickly will cause the same type of crash.

Sun JDK 1.1.6 on Solaris is very promising when first started. It loads the Watson applet, and displays the lab correctly when the button is pushed. A limited number of additional button presses are processed correctly during which time the labs appear to work correctly. After this limited number of button presses (normally 1) the lab stops responding to mouse clicks.

FreeBSD JDK 1.1.5 version V98-2-25 on FreeBSD shows identical results to Sun JDK 1.1.6 on Solaris.

Macintosh Runtime Java 2.1 Early Access release 1 on Macintosh is similar to the FreeBSD environment. It appears to start correctly and draws the initial lab image perfectly. Unlike the FreeBSD version, mouse events continue to be received and processed. The labs appear to work correctly in all regards except that repaint events issued by the labs are not respected. Changes are not reflected some outside action causes the windows to be repainted (for example, resizing the window slightly).

No browsers are currently capable of running swing applications, so no testing was done with them.

CHAPTER 4

Conclusions

Summary

Three questions were raised about this project that needed to be answered:

  1. Does it encapsulate enough behavior to be useful?

    This framework standardizes behavior related to activities, help, common dialogs, and the main lab window itself. An empty lab can be created in under 50 lines of code. Already one glitch in JDK 1.1.6 has had a workaround added that did not require any modifications or support from the existing labs. In addition, it adds a library (Sled) used in two of the Watson 1.0 labs as well as in the prototype lab (Prolog) introduced here.

  2. Is it sufficiently flexible to work with any reasonable lab?

    The framework does not place any limitations on additional labs except that the lab specific contents are standard components. They fit in the standard-sized space, and that the user’s work can be saved in a serializable object. These limitations do not seem unreasonable. In addition, two different labs have been implemented on top of the framework. They are similar in nature, but not identical. There has also been an outside library (Jinni) merged into the project for one of the labs (Prolog) without difficulty.

  3. Does the new lightweight-based implementation avoid the platform-dependent problems previously encountered with Watson?

The platform independence testing was less than encouraging, but there are differences in the types of problems from those found previously. Some problems relate to the JVM itself (JIT and Jinni); this difficulty has never been seen before. The author believes it to be a different type of issue from the AWT problems encountered in the past. This type of problem will probably disappear as the JIT technology becomes more robust.

Other problems were very severe, but they were few and their general nature simple to deduce. They all involved the heavyweight peers for Dialog or Frame. The swing library removes the plethora of heavyweight peers for each widget but depends on the dialog and frame peers to work correctly all the time. As the swing libraries become more common, these peers will be more heavily stressed and the related problems easier to find and fix.

The AWT components frequently had much more subtle problems. For example, the TextArea widget had a 64k limit in the size of the text it could hold in Windows 95, but not in Windows NT (or any other environment). The List component could be emptied in Netscape Communicator only by removing its contents one item at a time, whereas it could be emptied only using the clear() method in Internet Explorer. The problems now encountered are now "all-or-nothing" types of problems.

While platform independence is very weak at this time, this situation is believed to exist because the swing libraries have just be introduced. After they have become standard (with JDK 1.2), manufacturers will be forced to fix these problems because of the blatant nature of the problems themselves.

Future Work

The most obvious task needed to follow up the project is to port the rest of the existing labs to this framework. This task should be straightforward. It will consist of removing code from many of the labs and converting the event models in the remaining components from JDK 1.02 to JDK 1.1. Finally the remaining custom components must be converted to lightweight or Swing equivalents. In most cases this work can be done simply by changing the parent classes of the custom components to JComponent.

Another change that should be very simple to implement is the conversion of this framework to JDK 1.2. This important change will involve converting to the version of the swing library to be included as part of the JDK 1.2 core classes. The conversion should require no effort outside of changing package names, and a recompile. The author of this paper has volunteered to make these changes as soon as a final release of JDK 1.2 is available.

In the past, Watson 1.0 has used no source control of any kind. Since the source code for each lab was completely independent, and only one author worked on a lab at a time, the lack of source control was acceptable. However, this framework does imply that multiple authors working on different labs will be sharing the code for the framework itself. This situation implies a new level of difficulty in coordination best resolved by version management tools. Free tools such as RCS or CVS are recommended.

Activity Completion and Reporting

The ActivityManager has a fully featured interface. However, it would be helpful if it could perform some additional tasks. For example, some mechanism for reporting to professors which activities a student has completed would be helpful. There are many different ways of accomplishing this.

Intelligent assistance has been desired for Watson since its inception. When this system is implemented in Java, it will probably need to integrate with the activity manager to some degree. This system will probably help the activity manager decide which tasks have been successfully completed, and which have not. The changes may require changes to the interface between the ActivityManager and the lab. The interface currently consists of the method isActivityComplete() defined on WatsonLab and intended to be overridden in a lab-specific way.

Property Files

One feature available in proto-Watson was the ability to modify most text used by the program by editing keyed text files, meaning that changes could be made to messages without recompiling. The Java libraries offer a system based on property files that allow the same type of behavior.

These property files can be placed in the Jar file being used to distribute the class files from the project, meaning that the project (and all labs) can still be distributed in a single file. Property files also offer the ability to internationalize the project somewhat easily. Watson does not make use of property files, but could rather easily.

ResourceBundle resources;

try

{

resources = ResourceBundle.getBundle("Watson",

Locale.getDefault());

}

catch (MissingResourceException mre)

{

System.error.println("Watson.properties not found");

System.exit(1);

}

 

Figure 29:Loading Resource Bundle

The previous code block shows how to load a properties file. This code sample will read the resources from a file named Watson.properties anywhere in the classpath. This includes from the web server Watson was loaded from (if it is running as an applet), or from inside the Jar file it was stored in either on the web, or local. There is no problem with having multiple property files for each lab or portion of the framework if needed.

Actually, the previous code is a little more complex. It would search for a local specific version of the properties file first. The name of a German version of Watson.properties would be Watson.properties.de. If this file did not exist, Watson.properties would be used instead. If the German version was incomplete, the missing pieces would be filled in the Watson.properties file. There is a complex scheme that allows language, country, and variant specific versions to coexist. The full details of the naming scheme is beyond the scope of this document [JDK98].

Reading a string from the resource bundle read from the file is very simple. On the resource bundle (named resources in our example) call getString("key") where "key" is the name of the property desired. These strings are suitable for button labels, titles, help messages, font names, and even activity descriptions. It is possible to store non-string values in a properties file, but the file format for it is binary. Binary file formats would remove the advantage of being able to edit these files with a text editor.

# Activity Button Properties

ActivityButtonLabel=Activities

ActivityButtonToolTip=Used to select/change and activity

ActivityButtonHelpMessage=\

Use this button to select a Watson \

graphics laboratory activity to work on. \

\n\n \

Some activities will involve drawing \

images using the mouse. Others will \

involve writing computer programs.

 

Figure 30:Sample Properties File

The property files themselves have a very simple format. The previous example shows a comment, several small strings, and a long message with embedded newlines.

Distribution

The current version of the project binds the framework, its libraries (other than swing), and all labs into a single Jar file named Watson.jar. It can be invoked from any sufficiently current version of the JVM. The process used to invoke it is more complex the targeted audience (beginning CS students) will be able to handle reliably. Some manner of distributing the project that allows people to invoke it easily will have to be devised.

Originally, the intention was to distribute Watson as a collection of HTML pages with embedded applets. It allows the project to be made available from any web server or from disk (perhaps a CD distributed with the text). Any user who can follow a link on a web page would be able to launch the program.

The problems with compatibility in the Java libraries have made this impossible for Watson 1.0, since no complex program that uses the AWT runs correctly on all major web browsers. A different version of the same problem exists with Watson 2.0. None of the browsers in widespread use supports the Swing libraries at this time. There is reason to hope that browsers supporting JDK 1.2 will run applications more uniformly, but since no such browsers exist yet, this is still hypothetical.

Another possibility for distribution is to compile the project into one or more Windows executables. This looses the platform independence and the ability to distribute the software (without an installation procedure) over the web. It does, however, allow complete control over the Java run time environment.

Another possibility is to provide the Watson.jar file, the Java Runtime Environment for one or more platforms, and platform-specific wrappers that simplify the complexity of invoking the environment. Batch files could be used for Windows. The Macintosh Java Runtime provides a way of creating such an file for the Mac. Unix and other platforms would require that the user fends for themselves. At least the generic Jar file would be provided so that this would be possible.

It is impossible to decide what the best mechanism is at this time. The Java environments are changing quickly. Java continues to gain momentum for many types of work. As other projects face the same types of difficulties, more pressure will be placed on Sun to create workable solutions. Decisions will have to be based on exactly what form these solutions take.