- What Is a Widget?
- Widget Hierarchy
- Events and Listeners
- Application Data
- Querying the Display
- Summary
1.2 Widget Hierarchy
The class Widget is the root of an inheritance hierarchy of diverse user interface elements such as buttons, lists, trees, and menus. Subclasses, both within the widgets package and outside it, extend the basic behavior of widgets by implementing events and adding API that is specific to the subclass. The inheritance hierarchy of the class Widget is static. For example, the class Button will always inherit from its superclass, Control. [9] Instances of Button will always respond to messages that are implemented in the class Control.
The containment hierarchy of a widget is defined by the parent/child relationship between widgets. It is built dynamically at runtime. For example, the parent of an instance of Button might be a group box or tab folder but instances of the class Button do not inherit from the classes that represent these widgets. As we have already seen, the containment hierarchy of a widget is defined when the widget is created, using the parent argument of the constructor.
1.2.1 Subclassing in SWT
Generally speaking, subclassing is not the safest way to extend a class in an object-oriented language, due to the fragile superclass problem.
The term fragile superclass comes from the C++ programming world. It normally refers to the fact that when a new method or field is added to a superclass, subclasses need to be recompiled or they might corrupt memory. Java solves the static or binary compatibility portion of the problem using a name-lookup mechanism that is transparent to the programmer. However, there is also a dynamic portion of the problem where subclasses can inadver-tently depend on the implementation of a superclass. For example, a subclass may depend on the fact that the internal implementation of the superclass calls a certain public method that is reimplemented in the subclass. Should the superclass be changed to no longer call this method, the subclass will behave differently and might be subtly broken. In SWT, where the implementation of most classes differs between platforms, the chances of this happening are increased. For this reason, subclassing in arbitrary places in the Widget class hierarchy is discouraged by the implementation.
In order to allow subclassing where it is normally disallowed, the Widget method checkSubclass() must be redefined.
-
checkSubclass() Throws an SWTException("Subclassing not allowed") when the instance of the class is not an allowed subclass.
The protected method checkSubclass() is called internally by SWT when an instance of a widget is created. Subclasses can override this method to avoid the check and allow the instance to be created. The following code fragment defines an inner class that is a subclass of the class Label and reimplements the setText() method.
Label label = new Label(shell, SWT.NONE) { protected void checkSubclass() { } public void setText(String string) { System.out.println("Setting the string"); super.setText(string); } };
Why Aren't the Widget Classes "final"?
Java allows the programmer to tag a class as final, disallowing subclasses. In fact, in very early versions of SWT, classes that should not be subclassed were clearly marked as such using the final keyword. Unfortunately, this proved to be too inflexible. In particular, it meant that if a problem was found in an SWT class, only the SWT team could fix it. There was no way to temporarily "patch" the class by creating a subclass to override the problem method(s). Customers who needed to ship their product before a fix could be integrated into the next SWT release were willing to risk the dynamic fragile superclass problem in order to have the freedom to make this kind of patch. The checkSubclass() method is a compromise that allows them to do this without removing all constraints on subclassing.
It is important to note that this really is the only reason why the checkSubclass() method was added. Well-written SWT programs should never override checkSubclass().
In SWT, user interfaces are constructed by composition of widget instances. Event listeners (see Events and Listeners, below) are added to widgets to run application code when an event occurs, rather than overriding a method. Application programmers use listeners instead of subclassing to implement the code that reacts to changes in the user interface.
Subclassing is allowed in SWT but only at very controlled points, most notably, the classes that are used when implementing a custom widget: Composite or its subclass Canvas. To indicate this, the checkSubclass() method in Composite does not constrain the allowable subclasses. To create a new kind of widget in SWT, you would typically subclass Canvas, then implement and use event listeners to give it the required appearance and behavior. Note that you should still not reference internal details of the superclasses, because they may vary significantly between platforms and between subsequent versions of SWT. For an example of creating a custom widget, see MineSweeper in the Applications part of the book. [10]
1.2.2 Controls, Composites, Shells, and the Display
A control is a user interface element that is contained somewhere within a top-level window, called a Shell. Controls are common in all user interfaces. Buttons, labels, progress bars, and tables are all controls. Users are familiar with the standard set of controls that come with the operating system. In SWT, operating system controls are, by definition, instances of subclasses of the abstract class Control.
Taking a bottom-up view of the world, every control has a parent that is an instance of the class Composite or one of its subclasses. The class Shell, which represents the top-level windows of your application, is a subclass of Composite. Shells are created on a Display, which represents the "screen."
Stated another way, this time from the top down, a display contains a list of top-level shells, where each shell is the root of a tree composed of composites and controls. Composites can contain other composites, allowing the tree to have arbitrary depth. If the child of a shell is another shell, the child is commonly called a dialog shell. A dialog shell always stays in front of the parent shell.
1.2.3 Widgets That Are Not Controls
Unfortunately, the picture is not quite that simple. Some of the user interface elements that make up an SWT application are not represented by controls. In general, these are objects that are interesting enough to warrant being represented by instances of some class but do not have the operating system resource requirements of controls. For example, operating systems do not represent each of the items in a tree using other controls. Instead, to improve performance, the tree is responsible for drawing the items. Because the items no longer behave like controls, it would be a mistake to model them as such. The set of widgets that are not controls are exactly those that are not modeled as controls on all operating systems. [11]