Õ¾ÄÚËÑË÷: ÇëÊäÈëËÑË÷¹Ø¼ü´Ê
µ±Ç°Ò³Ãæ: ͼÊéÊ×Ò³ > SWT: The Standard Widget Toolkit

SWT Overview - SWT: The Standard Widget Toolkit

Previous Section  < Day Day Up >  Next Section

SWT Overview

The SWT component home page on eclipse.org states the following.

The SWT component is designed to provide efficient, portable access to the user interface facilities of the operating systems on which it is implemented.

This is as strong an embodiment of the design philosophy of SWT as can be found anywhere.

Certainly, part of the reason why SWT is efficient is because it is predominantly a compatibility layer on top of the user interface facilities of the underlying operating system. Most of the "real" work is done by the highly optimized, platform-specific code that the operating system vendors have implemented. There is more to it than that, however. To the greatest extent possible, anything that would put extra overhead between the running program and the operating system has been avoided. For example, SWT does not have a separate internal implementation hierarchy, as is found in the AWT peer layer. This removes a layer of indirection from every public entry point and significantly reduces the size of the library. The trade-off with this strategy is that SWT implementations (called ports) have the same implementation hierarchy shape on every platform,[1] and there is very little sharing within the internals of the ports. This made the initial design of SWT somewhat challenging but in practice has not turned out to be a significant issue since then.

[1] In this book, the word platform, without qualifiers, is frequently used as a synonym for the GUI library provided by the operating system. In some cases, when the phrase operating system is used, it is also intended to have this meaning, although this is technically less correct because some operating systems (Linux, for example) provide more than one graphical user interface library, which they call window systems.

Implementations of SWT are available for all of the major desktop operating systems and some handheld devices.[2] Over time, areas of missing platform functionality that would have prevented particular operating systems from being targets for full SWT implementations (and thus, candidate Eclipse platforms) have been covered by emulated versions of that functionality. Using the emulated versions simplifies the task of getting an initial port of SWT running, making it possible to fill in the details incrementally.

[2] You can determine which platforms are supported and their port status at www.eclipse.org/swt.

Porting SWT

Because much of the implementation of SWT must be re-created for each port, SWT was carefully designed to make this as simple as possible. The first step in creating a new port is to construct a platform interface layer that mimics in Java the native (typically) C-based API of the platform's user interface library. To the greatest extent possible, this layer has the same entry points with the same names and arguments as the native routines. Typically, only a subset of the platform's user interface library (those that are needed by the SWT port) is required. It even keeps the operating system's standard naming conventions for data structures and variables. Programmers who are familiar with the API for a particular platform can develop the SWT port using their full knowledge of that API. A side effect of this is that it is also possible for knowledgeable programmers to use the SWT platform interface to code platform-specific functionality in their applications, although a discussion of that is beyond the scope of this book.

Once the platform interface has been created, all of the interesting aspects of the port can be written in Java. This allows the full power of the Eclipse Java development tools to be used to implement and debug the new library, including hot code replace (modifying the code of a program while it is running) and remote debugging (debugging a program on one system while it is running on a different one).

Before starting out on a port, interested programmers should contact the SWT developers on the platform-swt mailing list at eclipse.org.


Another way that SWT maintains efficiency is by avoiding the trap of attempting to "fix" fundamental limitations in the underlying operating system. There are three significant ways that this is visible in SWT.

  1. The SWT API has been designed to take the limitations that are common to all (or almost all) of the modern operating systems into account. An example of this would be the notion of a distinguished "user interface thread" to model the canonical operating system limitation that cross-threaded access to widgets is either limited or not allowed.

  2. The SWT API allows for the existence of platform-specific limitations, as long as they are in areas that most applications will not encounter. For example, most operating systems have a limit on the amount of text that can be passed to a single text drawing call. For some operating systems, this is based on the number of characters; for others, it is based on the number of pixels covered by the rendered result. Because this limit is typically quite large—32768 pixels, for example—most applications are not affected; thus, SWT neither constrains the amount of text that can be passed nor attempts to work around the limitation.

  3. Some of the capabilities SWT provides are not available on all platforms. Although this runs counter to the notion of a portable API, the SWT designers felt that it was important for SWT to provide more than the lowest common denominator of functionality. Because of this, the API allows programmers to provide hints that platform-specific capabilities should be used. In these cases, when it is possible for the SWT implementation to fall back to more generic capabilities, it will do so; otherwise, the requests are ignored. For example, some operating systems allow buttons to be rendered with either a default three-dimensional appearance or a "flat" appearance. SWT provides access to these two styles if they are available. If a particular operating system does not provide the capability, SWT simply renders all buttons using the default style.

Despite these potential sources of platform-specific behavior, writing SWT applications that run well on multiple operating systems is not difficult. Certainly, the star example of this is the Eclipse universal tools platform. SWT has also been used for many other applications ranging from simple text editors to development environments and large vertical market applications. By allowing access to platform-specific functionality but not requiring that you use it, SWT allows you to choose whether to optimize for a platform that is particularly important to you or to provide the same capabilities everywhere.

Look and Feel

Applications built with SWT native widgets inherently take on the appearance and behavior (the look and feel) of the platforms they run on because the widget implementations are provided by platform-specific code that the operating system vendors have written. Although the SWT API makes it simple to create applications that run on any supported platform, it is important to test your applications on each platform on which you intend to ship. You should expect the look and feel of the application to change to match the norm for the platform in any or all of the following ways.

  • The canonical sizes of widgets may vary. Every platform specifies, either through programming guidelines or by providing API, the appropriate size for each widget. SWT uses this information when computing the preferred sizes of widgets.

  • In some cases, platform-specific size constraints are applied. For example, Microsoft Windows does not allow applications to change the height of combo boxes, so SWT Combo widgets also exhibit this behavior on Windows.

  • The location of some of the standard user interface elements may change. The prime example of this is the menu bar that appears at the top of the screen on the Macintosh but within each application window on all other platforms.

  • Even the behavior of the widgets may change, as it does, for example, in the case of the Microsoft Windows "feature" that causes radio buttons to become selected in the user interface whenever they are given focus. Here, SWT generates a matching selection event on Windows so that the application will behave as though the user explicitly selected the button, and no special-case handling is required in your code.

In general, platform-specific differences in behavior are handled by the SWT implementation, either by modeling the platform-specific aspects in terms of the portable API (as was done in the Windows radio button selection case described above) or by introducing new abstractions to describe the differences. For example, the SWT.MenuDetect event was introduced to indicate that the user had performed the appropriate action to request a pop-up menu. The sequence of button and/or key presses and releases that are required to do this varies from platform to platform, but portable SWT application code can be written by simply watching for the SWT.MenuDetect event.

To handle platform-specific differences in appearance—the size differences, size constraints, and location differences described above—SWT provides a powerful framework for dynamically positioning and sizing widgets based on layouts. By associating a layout with a collection of widgets, it is possible to arrange them in terms of various kinds of abstract constraints. Within these constraints, the layouts and widgets will collaborate to ensure that the expected platform appearance is maintained without requiring platform-specific code to be written. Layouts are described in detail in the Layout chapter.

Custom Widgets

During the creation of Eclipse, two issues were uncovered that have affected the nature of SWT.

  1. Some of the features that people expect in the user interfaces of modern development tools cannot be provided by any of the native widgets that are available on any platform.

  2. To make Eclipse more recognizable and give it a style all its own,[3] some of its user interface elements need to maintain the same appearance (specified by the Eclipse user interface design team) on every platform.

    [3] Using the standard vernacular: "to give Eclipse a distinct brand."

Neither of these issues could be addressed by the native widget-based capabilities of SWT, so a set of support classes, called the custom widgets package, was designed for the specific needs of Eclipse. These classes are implemented entirely in terms of existing SWT API, requiring no new native routines. They can be found in the package org.eclipse.swt.custom.

It is important to note that the custom widgets package is not the basis of the Eclipse user interface. Most of what you see in Eclipse—shells, trees, tables, lists, text fields, labels, menu bars and menus, tool bars, dialogs, scroll bars, progress bars, etc.—is created from native widgets. Thus, Eclipse generally takes on the look and feel of the platform. The custom widgets package provides the "icing" on the user interface that makes it distinctly Eclipse.

Despite the fact that the custom widgets classes were created for Eclipse, they have been designed to be generically useful. If you are looking for a feature that the native widgets do not provide and can live with the fact that the appearance of the result may not necessarily match the platform look and feel, it is worth checking out the classes in the custom widget package. Some of the things you will find there include the following.

  • A powerful text editor framework (StyledText)

  • Support for adding editable fields to tables and trees (ControlEditor)

  • Labels (CLabel), combo boxes (CCombo), and tabbed views (CTabFolder) that avoid some of the limitations of their platform widget-based counterparts

  • Tools to simplify common coding patterns, such as resizing (SashForm) and scrolling subviews (ScrolledComposite), showing activity (BusyIndicator), and creating "stacks" of widgets that occupy the same area of the user interface (StackLayout).

As stated above, the custom widgets package is implemented entirely in terms of the existing SWT API. The widget and event handling support they use is described in the Widgets part of the book. The graphics routines that were used to draw them are covered in the Graphics part.

History

SWT was created by the group within the Rational Division of IBM—then Object Technology International, Inc. (OTI)—that had been responsible for implementing the user interface for IBM's VisualAge/Smalltalk product. Much of the design philosophy of SWT has its roots in the VisualAge/Smalltalk work, so a brief discussion of this history is in order.

At the time of VisualAge/Smalltalk's creation, most Smalltalk implementations used user interfaces that were drawn entirely by simple graphics primitives (BitBlt). By doing this, the Smalltalk environments had complete control over the presentation of the user interface and provided what were at the time state-of-the-art capabilities. However, the other side of the coin was that Smalltalk programs did not look or interact like native platform applications. Attempts were made to extend the standard Smalltalk user interface to be "pluggable," so that Smalltalk code could be written to emulate the appearance of native widgets on each platform. These were successful to some extent but never to the point where users were unable to tell the difference. Applications that were built using this user interface failed in at least three ways.

  1. Common interactions, such as scrolling and typing, typically felt different in Smalltalk applications than in native applications. Users found this more disconcerting when the application looked like a native application than they did when the application looked markedly different.[4]

    [4] This is a variant on the "near human" problem in computer animation, which states that the more humanlike an animated figure appears to be, the easier it is to recognize the flaws in the animation.

  2. Native operating system features that relied on interoperability, such as drag-and-drop support, document embedding, and systemwide national language support, were either not available or incompletely implemented.

  3. As new releases of the native operating systems came out, their appearance changed, leaving the Smalltalk applications looking "dated" because they continued to run code that emulated the old look and feel.

There was a growing sense among Smalltalk developers that these user interface issues significantly limited the acceptance of Smalltalk within the larger software developer community, despite the many advanced capabilities that the environment provided: pure object-oriented programming, garbage collection, pointer safety, cross-platform portability, and integrated development and debugging (with hot code replace support), to name just a few. Solving the problem would require the construction of a Smalltalk user interface that used the native widget code rather than emulating it.

The first incarnation of this was done at OTI to implement a simple, native widget-based user interface for the Digitalk Smalltalk/V Mac product. Although the implementation strategy used was closely tied to the Macintosh operating system, and the set of native widgets and their API was limited to the requirements of the existing Smalltalk/V GUI, it clearly showed that building Smalltalk user interfaces from native widgets was practical. Digitalk produced similar native widget-based user interfaces for OS/2 and Windows.

The VisualAge/Smalltalk user interface, called CommonWidgets, was implemented using a strategy that was similar to the one used by Smalltalk/V, but it differed from it in at least two interesting ways.

  1. The CommonWidgets API was modeled on the premier GUI library of the day, X/Motif, rather than on historical Smalltalk user interfaces. This meant both that the API was more familiar to a wider range of developers and that there was a simpler mapping between the Smalltalk user interface classes and the underlying native widgets.

  2. CommonWidgets had consistent, clearly defined rules for how the interface to the operating system API should be implemented. These included ensuring that the operating system API functions and structures, and the Smalltalk code that modeled them had the same names and arguments (modulo Smalltalk's unusual function call syntax).

VisualAge/Smalltalk provided excellent portability across all of the supported platforms: Microsoft Windows 3.11, 95, NT3.51 and NT4.0, OS/2 Warp 3.0 and 4.0, and X/Motif. Implementations for MacOS and OpenLook were also started but not completed. At the time, OTI did not have a business case that made it worth the effort to "productize" them.

To simplify the task of creating the various non-X/Motif implementations, another layer, called the OSWidget layer, was constructed that more closely matched the programming model of Windows and OS/2. The CommonWidgets API was implemented in terms of this layer, and it in turn was implemented on each of the platforms.

By the time Java began its massive rise to fame, VisualAge/Smalltalk was a robust, mature product. However, design decisions that had seemed to be perfectly reasonable at the inception were now definitely showing their age. Most notably, selecting X/Motif as the basis for the API now seemed positively arcane, given that Microsoft Windows had become the overwhelmingly dominant desktop platform.

In any case, it was clear that the world was moving to Java. OTI continued to use Smalltalk for its internal development long enough to create the award-winning VisualAge/Java development environment (with a GUI built from CommonWidgets), but beyond that, any new development would almost certainly be done with Java.

When work began on the next programming environment from OTI—a tool for developing embedded systems in Java that became IBM VisualAge/MicroEdition—Java was, as expected, chosen as the implementation language. The developers initially built a prototype of the user interface using AWT/Swing but in the process of doing so, they discovered a number of appearance and performance problems. They attempted to work around the problems but eventually came to the conclusion that at that time, AWT/Swing was not ready to be used as the basis for commercial application development. In addition, it seemed that Swing's use of emulated widgets was going to be prone to all of the negatives that the "emulated look and feel" Smalltalk user interfaces had been shown to exhibit.

At this point, a question needed to be answered: Would AWT and Swing mature sufficiently quickly that applications built using them would be commercially acceptable by the time VisualAge/MicroEdition went to market? And even if that happened, would an emulated approach effectively enable the implementation of tools that would appeal to demanding developers? After considerable internal discussion, it was decided that a different approach was required.

Given the amount of effort that had already gone into CommonWidgets, an obvious choice of action would have been to translate the existing Smalltalk code into Java and take that as the basis for a new toolkit. However, using X/Motif as the model for an API no longer seemed reasonable. The OSWidget layer that had been used to provide portability between the various non-X/Motif implementations was equally powerful and had a simpler API. This, then, filtered through the constraints of the new programming language and with the opportunity taken to clean up a few of the suboptimal design decisions but keeping the original philosophy and overall structure, became the basis for SWT.

Since then, SWT has continued to advance, with the conversion to open source; its use by Eclipse and the addition of the custom widgets package; new ports available for Windows CE, GTK 2, and Macintosh OS X; and many other new features. Despite the new capabilities, the philosophy remains the same: Make the platform capabilities available, keep the layers as thin as possible, and give people the tools they need to make real platform applications in a portable way.

    Previous Section  < Day Day Up >  Next Section