Occasionally, you may find that none of the controls provided in SWT meet the need of your application. In these cases, you may want to extend SWT by implementing your own custom widget. SWT itself provides a package, org.eclipse.swt.custom, which contains custom controls that are not in the core set of SWT controls but are needed to implement the platform workbench.
Control
| Purpose
| Styles
Events
|
|
| Similar to Combo, but custom drawn to allow for using a combo without a border. This class was developed for using combos inside table cells.
| BORDER, FLAT, READ_ONLY Dispose, Control*, Selection
|
|
| Similar to Label, but supports clipping of text with ellipsis. Also supports a gradient effect for the background color as seen in the active workbench view. Does not support wrapping.
| CENTER, LEFT, RIGHT, SHADOW_IN, SHADOW_OUT, SHADOW_NONE Dispose, Control*
|
|
| Similar to TabFolder, but supports additional configuration of the visual appearance of tabs (top or bottom) and borders.
| BORDER, FLAT, BOTTOM, TOP Dispose, Control*, Selection
|
|
| Selectable user interface object corresponding to a tab for a page in a CTabFolder.
| Dispose, Control*
|
|
| Composite control that lays out its children in a row or column arrangement and uses a Sash to separate them so that the user can resize them.
| BORDER, HORIZONTAL, VERTICAL Dispose, Control*
|
|
| Composite control that scrolls its contents and optionally stretches its contents to fill the available space.
| BORDER, H_SCROLL, V_SCROLL Dispose, Control*
|
|
| Editable control that allows the user to type text. Ranges of text inside the control can have distinct colors (foreground and background) and font styles (bold and regular).
| BORDER, FULL_SELECTION, MULTI, SINGLE, WRAP, READ_ONLY Dispose, Control*, ExtendedModify, LineGetBackground, LineGetSegments, LineGetStyle, Modify, Selection, Verify, VerifyKey
|
|
| Selectable control that displays a hierarchical list of items that can be selected by the user. Items are presented in rows that display multiple columns representing different aspects of the items.
| BORDER, SINGLE, MULTI, CHECK, FULL_SELECTION Dispose, Control*, Selection, DefaultSelection, Collapse, Expand
|
|
| Selectable user interface object that represents a hierarchy of tree items in a TableTree.
|
|
|
| Composite control that lays out three children horizontally and allows programmatic control of layout and border parameters. Used in the workbench to implement a view's label/toolbar/menu local bar.
| BORDER, FLAT Dispose, Control*
| |
---|
Control* = Events inherited from Control: FocusIn, FocusOut, Help, KeyDown, KeyUp, MouseDoubleClick, MouseDown, MouseEnter, MouseExit, MouseHover, MouseUp, MouseMove, Move, Paint, Resize
Before implementing a custom widget, you should consider several important issues:
Once you've determined that you need a custom widget and have decided which platforms must be supported, you can consider several implementation techniques for your widget. These techniques can be mixed and matched depending on what is available in the underlying OS platform.
If your application requires a native widget that is not provided by SWT, you will need to implement it natively. This may be a platform widget, a third party widget, or any other widget in a platform shared library.
Each SWT platform is shipped with both a shared library (for example, a DLL on Windows) and a JAR (for the Java class files). The shared library contains all of the native function required for SWT, but it was not meant to be a complete set of the functions available on the platform. To expose native function or native widgets that were not exposed by SWT, you need to write your own shared library. If you are using a combination of native code on one platform and portable code on another, make sure you call your shared library on the platform with the native widget, and your jar on the platform with the portable widget.
To implement a native widget, understand the Java Native Interface (JNI), the API of the widget in the shared library, and the underlying OS platform APIs in C.
The basic process for implementation is to decide which part of the API of the native widget will be exposed in the Java API and writing the Java code that calls the natives to implement the behavior. JNI C code must be written to call the shared library.
It is a good idea to follow the design principles used to implement SWT when building your own native widget implementation. For example, your JNI natives should map one to one with the API calls being made into the shared library.
A complete example of a native custom widget implementation can be found in Creating Your Own Widgets using SWT..
If your new widget is similar in concept or implementation to an existing widget, you may want to wrap an existing SWT widget. This technique is used for the implementation of TableTree.
To wrap a widget, you create a subclass of the Composite or Canvas widget (depending on whether your control will have children). In the constructor for the custom widget, create the wrapped widget. The resulting widget will be 100% Java portable since you are calling the wrapped widget's API for your implementation.
Wrapping a widget is often a simpler way to implement custom widgets than starting from scratch. However, be careful in designing the API of your new widget. Here are some important tips:
Consider whether your widget is a "kind of" wrapped widget or whether it just uses one for its implementation. For example, a table tree is not a kind of table. It doesn't refer to items by row number index. The TableTree just uses a table to implement the presentation and adds tree behavior. If you are wrapping a widget purely for implementation reasons, then your API may not look similar to the underlying widget's API.
Forward as few methods and events as possible. Don't reimplement the entire API of the wrapped widget or you'll be constantly playing catch-up when the wrapped API changes in a future release. Methods that are common to most widgets, such as setFont, setForeground, setBackground, should be forwarded.
If you find yourself implementing most of the wrapped widget's API, consider exposing the wrapped widget at the API level and letting the application code use the wrapped widget directly. In this case, you may want to reconsider whether providing a new widget makes sense at all. It may be better to implement your feature as an "adapter" which adds behavior to a widget but does not pretend to be a widget. (JFace viewers follow this pattern.)
Note: This discussion has focused solely on extending the behavior of a widget by wrapping it. Extending a widget by subclassing it is highly discouraged, since it will make your widget dependent on the implementation of the superclass.
In some cases, you don't have any native code or existing widgets that help you in the implementation of your new widget. This means draw the widget yourself using SWT graphics calls. Although this technique can become quite complicated, it has the advantage of producing a completely portable implementation.
Custom drawn controls are implemented by subclassing the Canvas or Composite class using these rules:
In a custom drawn control, your internal state is kept in Java instance variables. You define your API and styles according to the requirements of your widget.
The internal implementation of a custom drawn widget usually involves these major tasks:
Many of the widgets implemented in the org.eclipse.swt.custom use this approach. A simple example can be found in CLabel.
Further information on custom widgets can be found in Creating your own widgets using SWT.