text2gui Overview

Goals

The first and foremost goal of the text2gui package is to make Swing application programming easier, especially for programmers that write internationalized (i18n) applications. Without the text2gui package, a large amount of tedious code needs to be written to create and configure components, or a clumsy GUI builder tool needs to used that either inserts code into your source files (how dare they touch your code!), or stores components in a form indecipherable by humans (serialized form).

If component creation and configuration is done with compiled code, then whenever the configuration of a component needs to be changed, the source file for the GUI needs to be recompiled, even for something as minor as changing the spacing between two components. The edit - compile - run - edit cycle wastes a lot of programming time and effort.

Furthermore, the code itself is a big mess, littered with tons of references to components that might have their properties changed. Instead of a single object that changes the properties of the GUI, there is one object for each small part of the GUI. It is a maintenance nightmare.

Regarding the use of serialization, see Problems with Using Serialization for Component Creation.

As we will see, the "code" that describes a GUI can be specified by a more natural and compact language compared to Java. This is because GUI's are basically containment hierarchies; frames contain panels which contain buttons, etc. Java is more or less a procedural language which is also good at describing implementation hierarchies, but clumsy at describing containment.

Java's strong type system is also a significant hindrance to writing GUI code. Pesky casts are needed everywhere or else the code fails to compile. Also, exceptions must be caught and handled, even if the programmer is confident that no exception can occur, or if no ill effects would result from ignoring an exception.

The core of an application that uses the text2gui library is still implemented in ordinary Java, but the GUI is specified with a different, simpler language more suitable for describing GUI's. This language is interpreted during runtime at minimal cost by a small Java library, so no recompilation is necessary.

The second goal of the text2gui package is to standardize the interface between GUI model and GUI view / controller code. This allows the application state and the GUI implementation to be separated. Programmers specializing in either part may largely ignore the implementation details of the other part. The result of this separation is simpler, more maintainable application code.

Also, this separation allows the implementation of the GUI to be upgraded or chosen from a set, without forcing the user to download the entire program again. Compared to simply changing the Look and Feel, much more radical changes are possible -- the choice, properties, behavior, and arrangement of all components can change.

How Does It Work?


 The text2gui package accomplishes these goals with the following mechanisms:
Preview of text2gui Code

Want to see what text2gui code looks like before you start? The following is a text file which describes the component hierarchy for a slide show application:

mainFrame.title=Slideshow Demo
mainFrame.contentPane=%contentPanel
mainFrame.windowListeners.0={  
  new WindowAdapter() {
    public void windowClosing(WindowEvent event) {     
      System.exit(0);                  
    }
  }
}

contentPanel.layout=box axis=y
contentPanel.contents=[
  {jscrollpane viewportView=%pictureLabel},
  %controlPanel
]

pictureLabel.icon=$icon
pictureLabel.border=etched
pictureLabel.hAlign=center

controlPanel.layout=box axis=x
controlPanel.contents=[{glue},
  %indexLabel, {strut}, %indexField, {strut length=20},
  %backButton, %forwardButton, {strut length=20},
  %randomCheckBox, {glue}
]
controlPanel.maxSize={width=1200, height=50}

indexLabel.text=Picture Index

indexField.dispatchType=jformattedtextfield
indexField.value=$pictureIndex:ruw
indexField.prefSize={width=50, height=20}
indexField.maxSize={width=75, height=50}

backButton.icon.location=Back24.gif
backButton.pressed=$back:w
backButton.tooltip=Go to the previous picture

forwardButton.icon.location=Forward24.gif
forwardButton.pressed=$forward:w
forwardButton.tooltip=Go to the next picture

randomCheckBox.text=Randomize order
randomCheckBox.selected=$random:rw#true

The following is the Java code that creates the component hierarchy, controls it, and responds to user input:
/** A demo slideshow application that displays pictures of Lily. */
public class SlideShow extends AppBase
implements PropertyChangeListener {
/** Respond to user input. */
public void propertyChange(PropertyChangeEvent event) {
String propertyName = event.getPropertyName();
Object value = event.getNewValue();

if ("pictureIndex".equals(propertyName)) {
int index = ((Number) value).intValue();

if ((index >= 0) && (index < _images.length)) {
_pictureIndex = index;
_argMap.putNoReturn("icon", _images[index]);
}
} else if ("back".equals(propertyName)) {
_changePictureIndex(-1);
} else if ("forward".equals(propertyName)) {
_changePictureIndex(1);
}
}

public static void main(String[] args) {
start(new SlideShow(), args);
}

protected INoReturnObservableMap _makeArgMap() {
// Creates the argument map used to control the GUI: "_argMap"
super._makeArgMap();

// Put initial property values in the map.
_argMap.putNoReturn("pictureIndex", new Integer(0));
_argMap.putNoReturn("icon", _images[0]);
_argMap.putNoReturn("random", Boolean.TRUE);
return _argMap;
}

/** Register this instance as a listener of 3 user input events. */
protected void _addArgMapListeners() {
_argMap.addPropertyChangeListener("pictureIndex", this);
_argMap.addPropertyChangeListener("back", this);
_argMap.addPropertyChangeListener("forward", this);
}

/** Update the picture index by the increment, or if we want to get a
* random index, generate a new picture index. Update the GUI
* appropriately.
*/
protected void _changePictureIndex(int increment) {
if (MapUtilities.getBooleanValue(_argMap, "random")) {
// Generate a NEW index
int pictureIndex = -1;
do {
pictureIndex = _random.nextInt(_images.length);
} while (pictureIndex == _pictureIndex);

_pictureIndex = pictureIndex;
} else {
_pictureIndex = (_pictureIndex + increment) % _images.length;
if (_pictureIndex < 0) {
_pictureIndex += _images.length;
}
}
// Update the GUI
_argMap.putNoReturn("pictureIndex",
new Integer(_pictureIndex));
_argMap.putNoReturn("icon", _images[_pictureIndex]);
}

protected int _pictureIndex = 0;
protected Random _random = new Random();

protected Icon[] _images = new Icon[] {
new ImageIcon("lily1.png"),
new ImageIcon("lily2.png"),
new ImageIcon("lily3.png"),
new ImageIcon("lily4.png"),
};
}
Because this class extends AppBase, the actual code to do component creation is not shown above. It is performed in AppBase with the one-liner:
_frame = (JFrame)
DispatchingComponentConverter.DEFAULT_INSTANCE.toComponent(
_bundle, "mainFrame", _argMap);
Finally, here's a screenshot of the result:

SlideShow Screenshot

Changing the picture index or clicking the back or forward buttons changes the image.

The important points to notice:
  • The Java code is simple and clean. It only has one purpose: as a model of the GUI state.
  • The component hierarchy definition is compact and easily understood
  • The Java code is almost independent of the component hierarchy definition. It doesn't need to know anything about buttons, text fields, scroll bars, etc. The component hierarchy can change considerably without requiring recompilation of the Java code.
  • The Java code receives user input events by implementing a single type of listener: property change listener
  • The Java code changes properties of the view by associating keys with values in a map
  • The English text in the component hierarchy definition can easily be replaced with text from another language
Next Steps

Start learning how to use the text2gui library in the Basics. There are many pieces of detailed documentation, but don't let this discourage you. You don't need to know all of the details before writing your own component hierarchies for text2gui. We're confident the time you spend learning how to use the text2gui library will pay off big in terms of the time you save writing GUI applications, and the improved quality of your applications.