Dr. Dobb's Journal, January 2006
The Eclipse Visual Editor is an Eclipse tools subproject that provides a framework for creating Eclipse-based GUI builders. The Visual Editor (http://www.eclipse.org/vep/) is built around a series of layers designed to be extended or swapped in and out. At its core is an Eclipse Modeling Framework (EMF) model of the components that make up the user interface being built, and Graphical Editor Framework (GEF) viewers for WYSIWYG editing. A good framework proves its mettle by being used successfully in different problem domains. Out-of-the-box, the Visual Editor (VE) provides implementations for the AWT and Swing Java foundation classes, and the Eclipse Standard Widget Toolkit (SWT). The VE has also been extended by Canoo for its Ultra Lightweight Client toolkit (http://www.canoo.com/ulc/), which provides a J2EE runtime for a true Java client experience through a browser. Additionally, IBM has extended the VE for its Application User Interface Markup Language (http://www.alphaworks.ibm.com/tech/auiml/), a cross-platform XML GUI markup language. Other projects include providing support for Java GUIs on mobile devices and XML-based GUI formats such as XSWT.
In Eclipse 3.1, support was added to the Visual Editor for Eclipse views and editors, allowing for Rich Client Platform (RCP) development. RCP lets end users tackle specific problem domains with Eclipse workbench technology. Ease-of-use is crucial for RCP development because user expectations include having a set of high-level design tools, like those found in competitive visual design studio offerings. Prior to RCP, developers of Java GUIs could use the Visual Editor or write their own programs using Eclipse's Java Development Tooling (JDT). For programmers to use a visual design tool, there had to be sufficient value added, and highly skilled SWT developers might always be more comfortable with JDT's Java Editor in the same way highly skilled Java developers might prefer notepad and javac to JDT's tools. With RCP, however, the broader range of users expect a first-class GUI builder as de rigueur for application development.
The Visual Editor can be opened against any .java file within Eclipse from the pop-up menu of choices; see Figure 1. If the Java file is recognized as having visual controls, then a graphical representation of the class is shown. Figure 2 shows the Visual Editor opened over one of the RCP example views supplied with the Plugin Development Environment (PDE). Unlike some GUI builders that only work with classes that they built, the view in Figure 2 was created by a PDE wizard that wrote a standard .java file with no knowledge of the Visual Editor. When the VE was opened on the file, however, it recognized the class as being visual and determined its controls by parsing the source file, allowing a preview of the GUI to be created.
One of the goals of the Visual Editor is that it work in incomplete environments including compile, build, and other errors. This often reflects the natural way in which RCP projects are built, where sandboxing and experimentation are a natural part of the development process, yet you still want to be able to design your screens without waiting for completion of the plug-in. For example, to fully deploy and test an RCP view requires a perspective, workbench advisor, plug-in manifest, and that other RCP artifacts exist, as well as the view being able to successfully compile. When all are present and correctly configured, the Eclipse Application launcher can launch the application and see the view at runtime. Without having the Visual Editor in such a development environment, it can be difficult to see the effect of how a coding change affects a view because to do so requires launching a fully baked application.
In contrast, the Visual Editor can be opened on the view when it is in a partially built state (such as uncompiled with errors in the source) and inside unfinished plug-ins. This allows WYSIWYG design and preview of the views and editors as the RCP application is being built without having to wait for its completion. The Run As Java Bean launcher provided with the VE also lets an RCP view or editor be launched and tested inside a harness that doesn't incur the overhead and expense of launching a full RCP application.
A key design point of the Visual Editor was not to replace the Java Editor, but to complement it. For this reason, its default layout is to split into two halvesthe top being a rendering of the GUI, and the bottom a fully functional embedded Java Editor. A JavaBeans viewer shows a tree representation of the GUI controls and the Properties view lets properties for the selected control(s) be viewed and modified. This lets simple properties (such as background color or font) be viewed and set, as well as widget constructor style bits (such as SWT.MULTI and SWT.WRAP) for Text controls (Figure 3). The definition of the list of properties and their edit-time experience follows the J2SE JavaBeans specification standard, with the SWT constructor style bits following the pattern described by the open-source Sweet specification. The ability to have style bits for SWT widgets categorized and edited with comboboxes in the property sheet means coding errors with incorrect values entered in the source code are eliminated.
Selection is synchronized so that if a control is selected in the GUI or a property is selected in the Properties view, then the embedded Java Editor is driven to the relevant line of source. Modifying the GUI through the viewers updates the Java code (and vice versa), so changes made in the source are reflected in the GUI. This synchronous round tripping between the GUI and the source was essential to the Visual Editor's success so that its use is not a question of Visual Editor on/off, but more like that of a dimmer switch. The Java Editor is always there with its powerful features (such as quick fix, code assist, or refactoring) and the Visual Editor use depends on the user's experience level or scenario. This can be anything from a viewer that avoids having to compile and run the class through, to a powerful set of viewers from which the visual controls can be manipulated. To add a new widget, there is a traditional palette containing drawers of commonly used controls that can be selected and dropped onto the GUI. If a particular control is not available on the palette, it can always be selected using the "Choose Bean" palette entry that displays a list of all available classes.
One of the hardest parts of building a Java GUI is how to deal with layout management of controls. An analogy to describe doing this without a Visual Editor is painting with the lights off. In this case, artists might look at their canvas and decide what they want to change, turn the lights out and use a brush to apply some new paint, and then switch the lights on to view the result. In the same way, developers coding without a GUI builder might run their class and look at how the controls were laid out, close the builder, alter various layoutData constraints before relaunching the GUI to observe the result of their changes, and alter the constraints and relaunch, and so forth. The Visual Editor assists greatly in this kind of scenario because the result of a visual layout change is seen instantly by developers. Apart from the benefits of this instant feedback, the Visual Editor helps with the initially esoteric rules of layout management by providing a "Customize Layout" dialog as in Figure 4.
The layout dialog lets Control's layoutData attributes be viewed and set with a user-friendly GUI. Grid lines are drawn on the GUI itself to show the arrangement of the composite's controls and assist when dropping new controls; and if layouts are switched, the Visual Editor automatically corrects the code to generate correct constraints for the new layout. An example of this is changing from Grid to null layout, where the code for the setting of the controls' layoutData properties are removed and replaced with setBounds(Rectangle) methods that keep the controls in the same relative position they previously occupied.
The goal of the Visual Editor is to reach the same function point that the JDT has with its editor, where it becomes the de facto tool for the creation of GUIs and does so by providing added value for all developers from SWT novices through to experts.
When the Visual Editor is opened, it parses the .java file and builds an EMF model of the controls as well as their properties and relationships. This model is used as the basis for the viewers, such as the GEF graph viewer, JavaBeans tree viewer, and Properties view. In addition, this model instantiates the actual live Java instances. In Figure 2, there are a number of SWT controls including several labels, a Text widget, and some composites making up the RCP view. One technique that a GUI tool could use is to instantiate these SWT controls inside the same virtual machine as the Eclipse workbench. While this solution is often used by other tools, there is a fundamental problem with such an approach.
This issue relates to the loading of their classes and instantiation by Java virtual machines. A powerful feature of Eclipse's Java tooling is the ability to configure each project's build path to a controlled set of prerequisite projects, libraries, and jars. For a PDE project, a typical use of this is to make the target platform different from the workbench in which the plug-in code is being developed. For a Java project, you might want to use a different JRE level or introduce external jar files into the build path. The list of dependent jars makes up the set used by the Java Development Tooling for compilation of a project's classes, and when the Run As Java Application launcher is used, a separate JVM is created in which to test and debug the code. The Visual Editor uses a similar approach where, for each .java file, a sandbox target JVM is created whose -classpath matches the entries on the project's build path and into which all of the classes are loaded and instantiated. Because of this insulation of environments, if any of the classes being used by the Visual Editor are altered while an editor is open (for example, a custom widget is being altered and used at the same time) or a project's build path is changed while an editor is open, the Visual Editor can drop and recycle the target JVM and keep the editor open whilst reflecting a fresh sandbox with the correct class definitions loaded. The Visual Editor's use of separate target VMs means that, for example, an editor can be open simultaneously on projects at differing JRE or target PDE platforms without any cross contamination of classes being loaded into the same memory space. Figure 5 shows the Visual Editor's architecture built around a central EMF model with adapters communicating between various subsystems, including the target VM, GEF viewers, and code-generation portion.
By having development insulation for each of the Visual Editor's JVMs, this also means that new environments (such as Java) on pervasive devices or new languages can be supported by plugging in new target environments. The collective experience of the Visual Editor's architects was that, although running widgets inside the same JVM as the workbench has the advantage of being easier than hosting target environments, it ultimately leads to an inflexible and inextensible design. Having said that, running separate JVMs does come with the priceextra work involved to create each sandbox and communicate to each target through sockets. One major goal of the Eclipse 3.1 release was to work on the performance implications of having target VMs so that any time difference between running the widgets locally in the same VM or on a separate target became insignificant.
A key design goal of the Visual Editor was to provide a high function end-user tool for building Java GUIs that is extensible and open. A typical scenario might be that developers of, say, a new custom widget can plug into the Visual Editor so that the edit time experience of their control is a first-class citizen no different to any other control. This level of integration might involve:
Because the Visual Editor's implementations of the JFC and SWT widget toolkits is done through its own API, there are no special rules or hard wiring that are not available to anyone else wishing to extend the Visual Editor.
DDJ