Dr. Dobb's Journal September, 2004
When building desktop applications, you need to start with good design and architecture. Because there is no universally accepted desktop-application framework, most developers design their own architecture, then build it into a framework themselves. However, the costs of this approach are a considerable expense, time, debug effort, support, and aggravation expended on solving a problem that is peripheral to building the business functionality of the application.
Another approach is to find a framework that accommodates your needs to simplify and accelerate project development. A "wish list" for such a framework would (among other things):
Just to complete this wish list, we might as well throw in that it's created and maintained in an open-source community, royalty free, and licensed to provide worldwide redistribution rights. Although these requirements may sound like a pipe dream, Java application developers may already have this application framework installed on their machinesEclipse.
The short answer to the question of whether Eclipse is a Java IDE is, well, yes and no. According to the the Eclipse Project (http://www.eclipse.org/) FAQ:
The Eclipse Project is an open-source software development project dedicated to providing a robust, full-featured, commercial-quality, industry platform for the development of highly integrated tools.
So, by definition, Eclipse is an open platform for tool integration, not an IDE. The issue has been confused because a complete industrial-strength, full-function Java IDE is included with the Eclipse platform, in the form of plug-in components that extend Eclipse's basic framework facilities.
Eclipse provides the framework for combining disparate tools into a single integrated application with a seamless user interface. New tools are integrated into the Eclipse platform and user interface through plug-ins that extend Eclipse's facilities and provide new functionality. Additionally, Eclipse plug-ins can extend other plug-ins. When an Eclipse-based application initializes, it discovers and activates all plug-ins configured for the workstation. The Eclipse platform is literally the sum of its parts because it is capable of performing any function that has been added to it by the plug-ins it currently contains.
Because being able to write and test plug-ins is central to Eclipse, the Eclipse platform is bundled with a plug-in development environment (PDE) and a set of Java development tools (JDT) to support it. The Eclipse developers clearly trusted the power of the frameworks they created. The entire development environment is just another set of tools integrated into the platform using the standard plug-in techniques. The Eclipse platform itself was created using the Eclipse-based Java IDE (initially in beta form). Since it's open source, you can inspect the code and understand in detail exactly how the frameworks are used.
As an "IDE for anything, and nothing in particular," Eclipse embodies an extensible design that maximizes its flexibility as an IDE platform. However, the Eclipse architecture defines sets of layered subsystems that let it be used as a framework for a portable desktop application (or suite) that is not an IDE. These subsystems include:
Extensibility Model. Requirements change over time, so developers often expend effort designing applications that are flexible and extensible. Eclipse is built around a highly flexible and extensible plug-in model to enable any type of tool to be added to the platform. If you begin to think of a desktop application as a tool, or set of tools, it becomes apparent that your application functions and facilities can be added into an Eclipse-based desktop as a set of plug-ins, just as Eclipse's native Java IDE capabilities have been.
Content Model. Eclipse provides a content model built around the concept of a workspace into which tools (applications) can be installed. The tools operate on resources that are organized into projects within the workspace. Projects contain a tree structure of resources, which are folders and files containing any type of content. The core platform provides a large number of extension points that allow customization of all aspects of resource life-cycle management.
The hierarchical, categorized nature of the content model lends itself to many types of desktop applications with a bit of thought. For example, a simple e-mail client could be built upon a workspace that contains a single project associated with the user's e-mail account. The user's project could contain folders for the common functional e-mail elements such as inbox, outbox, and sent items. Each of these folders could contain the corresponding set of e-mail messages as project resources.
Widgets on Steroids. The Eclipse platform contains the Standard Widget Toolkit (SWT), which is implemented natively on all supported Eclipse platforms. SWT contains a large set of events, layout managers, and widgets. When a supported platform does not contain a native widget that is supported by Eclipse, such as a toolbar on Motif, an emulated widget for that platform is provided. SWT also interacts with native desktop features, such as drag and drop. Additionally, SWT can use OS-specific components, such as Windows Active/X controls, if such functionality is more desirable than full platform portability. So far, SWT has been proven on the Windows Win32 and PocketPC, Photon, Motif, and GNU window managers, covering deployment platforms from high-end workstations to embedded devices.
User-Interface Framework. To build a graphical interface, SWT may either be used directly or through JFace, the user interface framework of the Eclipse platform. JFace includes dialog, preference, progress reporting, and wizard frameworks as well as image and font registries that make user- interface creation straightforward.
The Eclipse platform supports a multi-window, MDI-like user-interface presentation. On top of JFace and SWT, the Eclipse workbench provides a framework for building perspectives, editors, and views that provide the structure for user interaction. Editors handle resource life-cycle interactions such as creation, editing, saving, and deleting. Views are used to provide supplementary information about an object with which the user is interacting. Examples include outline, pending tasks, and property views. A perspective is a stacked, tiled, or detached arrangement of views and editors. Only one perspective is visible within a window at a time, but you may open multiple windows to view multiple perspectives simultaneously.
The Eclipse user-interface framework is extensive, flexible, and powerful. And, even if it doesn't do everything you need, it can easily be extended for much less investment in time and resources than designing and building your own.
Update Manager. Historically, one of the biggest problems associated with desktop applications is the support cost incurred to package, distribute, maintain, and upgrade the application as new versions are released. This cost increases when a large and dispersed user community uses the application.
Component maintenance and upgrade facilities were part of the design of Eclipse from the beginning. To control ongoing cost and remove maintenance issues that could become barriers to project development and deployment, the Eclipse platform contains a flexible update manager. The update manager can be configured to perform both initial installations of new components or updates to existing components from a remote server. As you release new versions of your application or add-on components, distribution can be as easy as packaging them using Eclipse facilities and placing them on your update server.
Help System. Every professional desktop application has a help system, and Eclipse is no different. However, Eclipse's help system isn't simply built from a static group of HTML files that tell you about Eclipse. Rather, it is a framework for providing both searchable and context- sensitive help that is open for extension by documentation plug-ins. Once your application is complete, everything is available for constructing, packaging, and shipping a complete, custom, context-sensitive help system without third-party tools.
Eclipse satisfies the full function and facility wish list mentioned earlier, while providing the program development environment for building the project as a series of Eclipse-style plug-ins. You'll have an application that is architecturally sound, extendible for future enhancements, interoperable with other plug-ins (even those created by others), and can upgrade itself remotely. The main question then becomes how much of Eclipse do you need?
An application can be built upon the Eclipse framework by removing functions that you don't want and then adding functions that you do. Removing Eclipse functions is the easy part; just take out plug-ins that provide unneeded features. If you're not building another IDE, a good place to start is to remove all the JDT, PDE, and VCM (version-control management) plug-ins. With that starting point and a bit of experience, you can evaluate components and continue to remove unnecessary features by removing the corresponding plug-ins.
Once you pare down the plug-ins to the bare minimum, you'll find that Eclipse still has a few development capabilities represented in the UI. To remove these from the framework, slightly more invasive techniques have to be used. The workbench UI plug-in provides the base UI capabilities of Eclipse. Removing extensions from the plug-in's XML descriptor is an easy way to further reduce visibility to the extra features that your application doesn't require.
After all, unnecessary plug-ins are removed and you've minimized the extensions in the workbench UI, there is still one more avenue available to further reduce the base framework size. Because Eclipse really was intended to be a framework for integrating development tools, a few of Eclipse's low-level development concepts are built into the workbench UI plug-in directly rather than being provided as extensions. The easiest way to remove them is to comment out undesirable features in the source code and rebuild the plug-in. While this is unfortunate, keep in mind that "unwriting" a few bits of code is easier and faster than writing an entire application framework. Clearly, if you take this approach, you'll need to be able to repeat the changes when migrating to new versions of Eclipse source code, at least for a little while.
The good news is that the Eclipse team has recognized that such new and innovative uses of Eclipse should be supported at the platform level. Eclipse 3.0 specifically targets enabling the use of Eclipse as a rich client platform.
Even if you need to make other changes to Eclipse, the Common Public License that controls access and use of the Eclipse platform lets you make and distribute commercial derivative works from its source. There is no license requirement to remain compatible with Eclipse or donate changes back to the open-source project, but it's clearly to your advantage to stay as standard as possible.
Once unnecessary functions have been removed from the framework, building applications is simply a matter of writing your own plug-ins, adding features to the basic Eclipse framework, and branding them with your own logos. For a large application, consider writing it as multiple custom perspectives and supporting views. If you have a suite of small applications, each one can be a single perspective. Or, you can use Eclipse as a portal to integrate all your organization's homegrown applications.
The Standard Widget Toolkit is designed to provide portable UI facilities that directly call the window manager of the underlying operating system. This differs from the approach taken by Swing technology, which emulates user interfaces bit by bit, then presents the entire interface bitmap to the underlying window manager for display to the user. Speed and responsiveness result from letting the operating system's window manager do the work.
SWT itself is a thin layer that conforms the API calls for standard widget-like lists, buttons, and text boxes into a transportable interface. There is no separate peer layer as in the AWT class library. The SWT widget directly calls the underlying operating system's window manager. Platform integration is not just a matter of look-and-feel. Tight integration includes the ability to interact with native desktop features such as cut-and-paste or drag-and-drop, integrate with other desktop applications.
SWT establishes a functionally rich least common denominator of user interface widgets in three ways:
SWT has to remain simple to run successfully on multiple operating systems. Sometimes, the underlying behavior of the window manager impacts the way that applications paint and SWT generally lets the OS "win." Functional portability is established by ensuring that all but the lowest level direct interface calls to the OS are written in Java. This has proven itself as SWT has been ported to new environments. The calls across the Java Native Interface to the operating system's C/C++ APIs are straightforward, making it easier to accommodate new platforms. Most users like the fact that the resulting interfaces look just like others rendered by their workstations.
To bring some consistency to user interfaces implemented for the Eclipse Workbench, SWT includes support for creating custom widgets, leading to a specific application look and feel. This consists of a small set of carefully designed components that are generally useful. This includes extended support sensing user-selected default color selections and border widths using mechanisms provided by the operating-system window manager.
Since SWT is royalty free open source (licensed under the Common Public License), you can also review the actual source code (also at http://www.eclipse.org/). There are separate versions for each supported operating system/window-manager combination.
If, after evaluation, you decide that you don't want to use Eclipse as an application framework, but want to use the SWT widget set as a replacement for Swing or AWT, you can do that, too. Just add the SWT jar file to your application's classpath, place the SWT shared library on your library path, and build your SWT user interface. You've now got a completely new UI that makes your application look like a native on whatever platform it is running. Be forewarned that the programming model for SWT is different than Swing or AWT, but once you begin to use SWT, you realize that the differences are actually a benefit.
SWT applications start by creating a "Display" representing an SWT session. A "Shell" is created to serve as the main window for the application. Functional and display widgets are created within the shell. Characteristics and states of the widgets are initialized and event listeners are registered. When the shell window is opened, the application consumes the event dispatch loop until an exist condition is detected, typically when the main shell window is closed by users. At that point, the display must be disposed of.
The Display represents the connection between SWT and the underlying platform's GUI system. Displays are primarily used to manage the platform event loop and control communication between the UI thread and other threads. For most applications, you can follow the pattern just described. You must create a display before creating any windows, and you must dispose of the display when your shell is closed.
A shell is a "window" managed by the OS platform window manager. Top-level shells are those that are created as a child of the display. These windows are the windows that users move, resize, minimize, and maximize while using the application. Secondary shells are those that are created as the children of another shell. These windows are typically used as dialog windows or other transient windows that only exist in the context of another window.
When your application creates a widget, SWT immediately creates the underlying platform widget. This eliminates the need for code that operates differently depending on whether the underlying OS widget exists. It also allows a majority of the widget's data to be kept in the platform layer rather than replicated in the toolkit. This means that the toolkit's concept of a widget lifecycle must conform to the rules of the underlying GUI system.
Some widget properties are set by the operating system at the time a widget is created and cannot be changed. For example, a list may be single or multiselection, and may or may not have scroll bars. These properties, called "styles," must be set in the constructor. In some cases, a particular style is considered a hint, gracefully ignored on platforms that do not support it. The style constants are located in the SWT class as public static fields. A list of applicable constants for each widget class is contained in the API Reference for SWT.
SWT explicitly allocates and must explicitly free operating-system resources. In SWT, the dispose() method is used to free resources associated with a particular toolkit object. If you create the object, you must dispose of it. When the user closes a shell, the shell and all of its child widgets must be recursively disposed. It's possible in SWT to register a disposal listener for each widget that can automatically free associated graphic objects. There is one exception to these rules: Simple data objects such as Rectangle and Point do not use operating-system resources. They do not have a dispose() method and you do not have to free them.
A Control is a widget that typically has a counterpart representation (denoted by an OS window handle) in the underlying platform. The org.eclipse.swt.widgets package defines the core set of widgets in SWT.
Eclipse can be "both a floor wax and a dessert topping." It is a complete, universal tool-integration platform, a platform for building IDEs for any language, a Java IDE, a better Java UI widget set, and a portable, a la carte application framework. Serving a broad array of project development needs, Eclipse has something for everyone.
DDJ