The Abstract Window Tookit (AWT) is a toolkit for building graphical user-interfaces (GUIs) for Java software. The AWT divides the task of supplying GUI services between high-level GUI classes and platform-level peer components supplied by the underlying platform. Java software interacts only with the high-level GUI classes while the AWT maps these high-level classes to peer components. This architecture allows Java software with GUIs to run on different target platforms without modification.
Truffle provides a flexible implementation of the platform-level peer components required by the AWT. To achieve this goal while meeting the needs of different platforms, Truffle includes a framework for delivering alternate look & feel designs for different Java application environments.
As an example of a specific look & feel design, Truffle includes the Touchable look & feel design for the PJAE operating on touchscreen-based consumer devices. Touchable can be either modified or replaced to support the product identity or product design needs of specific licensees.
Truffle does not add any new APIs for application developers to learn. It provides a set of peer components that Java software can use through the standard java.awt API. In addition, Truffle includes a special-purpose window and graphics system for platforms that lack a native window and graphics systems.
The following list defines some of the important terms in the Truffle vocabulary. Some of these definitions describe how concepts differ between the Truffle context and the desktop context.
In particular, the PersonalJava Application Environment Specification allows an implementation of the PJAE to support a subset of the java.awt API.
Truffle is designed to meet the following goals:
The amount of computing resources that can be delivered in consumer devices has increased substantially in recent years to the point where these products represent a software platform comparable to desktop systems. This has led to efforts to modify desktop technology for use with consumer devices. In some cases borrowing technology from desktop systems has been successful. But the use of desktop-centric human interface design techniques in consumer devices has not been successful.
Consumer devices are tightly integrated and reflect a careful balance between several competing design criteria. Over time the consumer device market will see a shift where much of the value contained in a given product will be transferred into software. As this shift occurs, designers will need a GUI toolkit that is flexible enough to handle a variety of different product design scenarios.
Consumer devices need different human interface designs for several reasons. These devices are smaller and their input devices are simpler. Consumers may not have any computer experience, so human interface metaphors like drag and drop that are borrowed from desktop environments may be inappropriate. Moreover, consumers -- even those with computer experience -- have very different expectations when they interact with a consumer device. Psychologically, they expect these products to be simple and predictable and they have a low tolerance for learning how to use them.
Truffle represents both an engineering achievement and an advance in human interface design. The engineering effort shows in the design and implementation of Truffle itself. The Touchable look & feel is the result of several years of human interface research into consumer behavior. Many lessons learned from developing Touchable will be used to develop additional look & feel designs for different kinds of consumer devices.
Characteristic | Touchable (Screen Phone) |
Couchable (Set-Top Box) |
Metal (Desktop) |
---|---|---|---|
applications | telephony, voice mail, address book, email, web browsing | TV, EPG, web browsing, email | word processing, presentations, web browsing, email, productivity applications, vertical applications |
input device | finger, stylus | remote control | mouse |
mouse support | none | none (although some remote controls have track balls) | yes |
keyboard support | virtual or physical keyboard | virtual or physical keyboard | physical keyboard |
viewing distance | 1-2 feet | 10-15 feet | 1-2 feet |
display size | 6 inches | 13 inches to wall-size | 13-28 inches |
screen resolution | 1/4 VGA (320x240) to full VGA (640x480) | broadcast television | 640x480 to 1800x1440 |
screen colors | 2, 4 or 8-bit displays; both black & white and color | broadcast television | 16-bit or 24-bit |
pixel density | ~102 dpi | N/A | ~72 dpi |
multiple screens | no | no | yes |
audio input | telephone handset, microphone | none | microphone |
audio output | telephone handset, perhaps speaker | TV speakers up to full surround-sound | computer speakers to high-end speakers |
data bandwidth | 28.8Kbps to ISDN | 28.8Kbps to cable modem throughput | 28.8Kbps to Ethernet |
printer connection | optional | optional | yes |
Why should the PJAE support multiple look & feel designs, particularly for consumer devices? The short answer is that different products have different needs and the level of integration in consumer devices challenges the platform developers to provide unique and elegant solutions to human interface design problems.
Multiple look & feel designs are needed to support both the product design needs of consumer devices and the product identity needs of licensees. If the API for the GUI toolkit (java.awt) must remain unchanged so that applications can run on different platforms, and if consumer device manufacturers must develop widely differentiated products, then the PJAE must be able to supply different look & feel designs. Truffle provides this flexibility so that licensees can deliver product-specific look & feel designs in a small memory footprint.
The need for simplicity in human interface design does not imply the need for a single look & feel. Successful consumer devices must be simple to use so that consumers can intuitively understand how to use them.
It is useful to compare Truffle with Swing because they share many design goals. Both Truffle and Swing are written in the Java programming language and both support multiple look & feel designs. Swing's pluggable look & feel architecture allows an application to select a look & feel design at runtime. This level of flexibility in Swing may add too much complexity or require too many resources for consumer devices operating in a small amount of memory. In contrast, Truffle provides a replaceable look & feel architecture where a single look & feel design is selected at startup time.
Although Swing contains a rich set of GUI components that extends GUI functionality beyond what is provided by the AWT, Truffle provides only core AWT functionality. This has two benefits: it keeps the Truffle implementation compact and it removes the need for application developers to learn a new API to write software for Truffle-based platforms.
The PersonalJava Application Environment Specification places a further constraint on the peer components supplied through Truffle by defining a minimum subset of the AWT components. These components were selected for their appropriateness for consumer device applications. For example, java.awt.Frame is a modified GUI component in a PJAE implementation.
The optional and modified peer components are described in the table below.
Peer | PJAE Support Level | ||
---|---|---|---|
Required | Optional | Modified | |
Button | x | ||
Canvas | x | ||
CheckboxMenuItem | x | ||
Checkbox | x | ||
Choice | x | ||
Component | x | ||
Container | x | ||
Dialog | x | ||
FileDialog | x | ||
Font | x | ||
Frame | x | ||
Label | x | ||
Lightweight | x | ||
List | x | ||
MenuBar | x | ||
MenuComponent | x | ||
MenuItem | x | ||
Menu | x | ||
Panel | x | ||
PopupMenu | x | ||
ScrollPane | x | ||
Scrollbar | x | ||
TextArea | x | ||
TextComponent | x | ||
TextField | x | ||
Window | x |
The Touchable look & feel design supports touchscreen-based consumer devices like screenphones. A consumer using a screenphone expects it to behave much like a conventional phone, so that most interaction will be driven by pressing a finger on a button to select a choice. The figure below shows a dialog for an address book application. While this application may run without modification on another Java application environment like the JDK, on the PJAE using the Touchable look & feel it has a distinctive consumer-friendly appearance. Buttons are wide and rounded while vertical scrollbars have been replaced with button pairs to simplify finger-based operation.
Touchable Example
Look & feel designs are usually crafted for a specific resolution. For example, the first version of Touchable is designed for VGA resolution (640x480).
There are two approaches to developing versions of Touchable for other resolutions. The first is to simply scale each graphical element in the look & feel design by a constant scale factor. The drawback to this approach is that it often causes roundoff errors. For example, if a certain graphical element is a single pixel wide, then it may disappear or remain the same size. In any event, the relative sizes of the different graphical elements might shift due to scaling.
The second approach to scaling a look & feel design is to create a derivative look & feel design based on the original. This is not as difficult as creating a new look & feel design because it is based on the graphical design principles of the original look & feel design and because it is limited only to the graphical elements. In a way, it is like designing a screen font for a different resolution based on an existing screen font design.
Truffle can support implementations that need multiple look & feel designs, for example to support multiple display resolutions. But Truffle can only support a single look & feel design at runtime. The classes that represent a specific look and feel design are not memory intensive.
Truffle was designed to meet several requirements. It supplies an AWT peer set written in the Java programming language. Furthermore, it provides a framework for supplying alternate look & feel designs that are targeted at different kinds of platforms, including consumer devices and desktop systems. This section describes how Truffle's architecture supports these goals.
The figure below illustrates the major components of the Truffle architecture and compares them with desktop implementations of the JDK. Truffle fulfills the goal of providing a cross-platform GUI toolkit by providing a set of peer components and the window and graphics system necessary to support them. Truffle plays the same role in a Java application environment like the PJAE that native peer sets perform in desktop implementations of the JDK. In fact, Truffle can be used to replace these native peer sets.
It is much easier to understand Truffle's purpose and design by thinking of Truffle in its relationship with the AWT rather than seeing it as sitting on top of a window and graphics system. The reason lies in Truffle's goal of providing just enough GUI services to meet the requirements of the AWT. In other words, Truffle is not a general-purpose GUI toolkit with a large number of widgets like Motif and Swing. It is specifically designed to support the API requirements of the AWT and the human-interface needs of consumer devices.
Truffle Architecture
Truffle contains a toolkit-within-a-toolkit named Object Toolkit (OTK) that can be used by licensees to construct new look & feel designs. For example, the Touchable look & feel design is represented by a set of classes in sun.awt.touchable that use OTK classes to implement AWT peer components that appear and behave in a way that is suitable for touchscreen-based consumer devices like screenphones. Another look & feel design could be an implementation of Metal, the Java look & feel design used in Swing.
Truffle uses the Model-View-Controller (MVC) architecture to organize the peer set implementation into groups of classes that perform different roles:
Model | data state |
View | appearance |
Controller | synchronization or behavior |
MVC is an example of a design pattern. See Design Patterns: Elements of Reusable Object-Oriented Software. for a more thorough introduction to design patterns.
MVC allows effective use of code sharing that leverages functionality between components and thus reduces code size. From a licensee's perspective, OTK reduces the software development task for creating a platform-specific look & feel design by focusing effort on the appearance and behavior of the peer components and avoiding the implementation of the underlying support systems.
Truffle is part of the PJES but it can also be used with other Java application environments like the EmbeddedJava application environment, JavaOS and JDK-based systems.
Truffle can support a variety of look & feel designs. A specific look & feel design is attached to a given Java application environment at startup time. So only a single look & feel design is available for that platform during a user session. This is called a replaceable look & feel architecture to distinguish it from Swing's pluggable look & feel architecture which allows each application to select a look & feel design at runtime.
Look & Feel Design | Target System |
---|---|
Touchable | touchscreen-based screen phones |
Couchable | remote control-based set-top boxes |
Metal | network computers & PCs |
In addition, licensees can use OTK to build product-specific look & feel designs that support their product identity or product design needs. This can be done by modifying an existing design like Touchable with a different color scheme or by developing a new look & feel design from scratch.
Truffle includes a special-purpose window and graphics system written mostly in the Java programming language. The platform-dependent portion of the graphics system is usually based on a platform's graphics library.
Truffle provides I18N services required by the AWT. In particular, Truffle includes an input method framework written in the Java programming language and virtual keyboard support. Native input methods can be integrated with this input method framework with an adapter class. Beyond portability, the main advantages of the Truffle input method framework is its integration with both virtual keyboards and lightweight components.
One of the characteristics that makes Truffle configurable is that it can support an underlying platform at several different levels. Each layer in Truffle depends on the layers beneath it. So if a licensee chooses to replace a certain layer, they will also need to replace each of the layers beneath it. For example, if an implementation replaces sun.awt.aw with a native window system, then it must supply the graphics system as well.
Here are the options for porting Truffle to a new platform:
The Truffle graphics system is a portability layer that provides all the functionality required by the Truffle window system to paint components on the screen and receive user input. In order to simplify the porting task, it is recommended that support for the various features is implemented in the order described below.
It is important to note that support for images and fonts constitutes a large and complex portion of the porting effort. For this reason, it is recommended that the more basic drawing functionality be implemented first so that correct behavior of the graphics system can first be verified.
Porting Truffle is significantly easier than porting AWT. Sample ports are available for both Solaris/Motif and Microsoft Windows 95/NT. The Solaris port is a better implementation for learning purposes while the Microsoft Windows 95/NT port is intended for use as an emulation environment for desktop-based software development.
The namespace for the classes in the Truffle graphics system is sun.awt.platform.*. The tables in Source Code Organization describe how the source code in the sample implementations is organized.
The Truffle graphics porting layer requires a RTOS-supplied library with basic 2D graphics, font rendering support and image support.
Input devices should be handled by an RTOS-level library that provides Truffle with fairly high-level input events. See the Focus Events technical note for a description of how events are routed for Truffle.
The following tables describe the organization of the source code for the Truffle graphics system.
Class | Java Source Code | Native Source Code |
---|---|---|
CursorImage | classes\sun\awt\gfW\CursorImageImpl.java | native\sun\awt\gfW\CursorImageImpl.cpp |
Font | classes\sun\awt\gfW\FontImpl.java | native\sun\awt\gfW\FontImpl.cpp |
FontMetrics | classes\sun\awt\gfW\FontMetricsImpl.java | native\sun\awt\gfW\FontMetricsImpl.cpp |
Graphics | classes\sun\awt\gfW\GraphicsImpl.java | native\sun\awt\gfW\GraphicsImpl.cpp |
GraphicsSystem | classes\sun\awt\gfW\GraphicsSystem.java | native\sun\awt\gfW\GraphicsSystem.cpp |
Image | classes\sun\awt\gfW\ImageImpl.java | N/A |
ImageRepresentation | N/A | native\sun\awt\gfW\ImageRepresentation.cpp |
OffScreenImageSource | N/A | native\sun\awt\gfW\OffScreenImageSource.cpp |
Screen | classes\sun\awt\gfW\ScreenImpl.java | native\sun\awt\gfW\ScreenImpl.cpp |
Class | Java Source Code | Native Source Code |
---|---|---|
CursorImage | classes/sun/awt/gfX/CursorImageImpl.java | native/sun/awt/CursorImageImpl.c |
Font | classes/sun/awt/gfX/FontImpl.java | native/sun/awt/FontImpl.c |
FontMetrics | classes/sun/awt/gfX/FontMetricsImpl.java | native/sun/awt/FontMetricsImpl.c |
Graphics | classes/sun/awt/gfX/GraphicsImpl.java | native/sun/awt/GraphicsImpl.c |
GraphicsSystem | classes/sun/awt/gfX/GraphicsSystem.java | native/sun/awt/GraphicsSystem.c |
Image | classes/sun/awt/gfX/ImageImpl.java | native/sun/awt/ImageImpl.c |
ImageRepresentation | classes/sun/awt/gfX/ImageRep.java | native/sun/awt/ImageRepresentation.c |
OffScreenImageSource | N/A | native/sun/awt/ImageRepresentation.c |
Screen | classes/sun/awt/gfX/ScreenImpl.java | native/sun/awt/ScreenImpl.cpp |
At the heart of the Truffle graphics system is an implementation of java.awt.Graphics. Graphics objects are created by the Truffle window system or application code any time a drawing operation needs to take place. When porting the Truffle graphics system, this is the class that ultimately must map the java.awt.Graphics drawing primitives to the native calls that write to a screen or offscreen image.
Create this class by extending the abstract class java.awt.Graphics. Implement the basic drawing primitives (lines, rectangles, etc.). Include a mechanism for keeping the origin translation synchronized with a GeometryProvider object. The GeometryProvider.getValidationID method exists to simplify this task.
Create this class by implementing the sun.porting.graphicssystem.Drawable interface to implement functionality that accesses one or more native graphics contexts for drawing on a screen. Implement the getGraphics method to return a new instance of the Graphics class that can draw on the screen.
It is important to note that multiple instances of the Graphics class may be created by multiple concurrent threads, so a suitable synchronization policy needs to be in place to avoid screen corruption.
Create this class by extending the abstract class sun.porting.graphicssystem.GraphicsSystem. Implement the getScreen method to return a new instance of the Screen class. The Truffle window system will use this to display components on the screen.
The clipping behavior required by the Truffle window system is relatively simple. The Truffle graphics system must provide an implementation of a Region class for the Truffle window system to use for describing the visible area of a component. sun.porting.utils.RegionImpl is an implementation of such a class written in the Java programming language that can be used in the early stages of the porting process. But better performance can probably be achieved by providing an implementation that wraps a native region implementation.
The Graphics class will use Regions to clip its output accordingly. In the case of a wrapped native region, this could be as simple as selecting the native region into the native graphics context as the new clip region. When using the the sun.porting.utils.RegionImpl class however, the clip region could be broken down into its component rectangles which in turn could be used to define a more complex clip region in the native graphics context.
Create this class by implementing the sun.porting.graphicssystem.Region interface. If wrapping a native region implementation, note that it is important that the ability to enumerate component rectangles be provided for the Truffle window system.
Implement the makeRegion method to construct new instances of the Region class at the request of the Truffle window system.
Implement functionality required to select a region described by a Region object into the native graphics context so that further output is clipped within that region. Include a mechanism for keeping the clipping region synchronized with a GeometryProvider object. The GeometryProvider.getValidationID method exists to simplify this task.
Mouse, keyboard and repaint events are delivered to the Truffle window system via the EventHandler interface. The Truffle window system will register an EventHandler object with the GraphicsSystem object on startup. Events should be formatted according to the EventHandler specifications and delivered in a timely manner.
Add the necessary native callbacks to respond to mouse, keyboard and repaint events by formatting them and passing them on to the EventHandler object.
Implement the registerEventHandler method to gain access to the Truffle window system's event handler to which events will be sent. Where necessary, add code to start a system event handling thread to poll the native event queue for new events.
Supporting images is no small task. Although much of the decoding of file formats, etc., is handled by the Java class library, the Truffle graphics system must provide the ability to create native bitmaps for the device, which can be drawn into by instances of the Graphics class. The ability to read and write pixel data to and from a native image is required. In addition, dithering and scaling support should also be provided to enable the display of any supported format on each supported device.
For palette-based devices, the image classes are the most likely to be affected by the current palette selection. The native code will have to handle palette mapping for ImageRepresentation objects as it would for any other bitmap.
Create this class by extending the abstract class sun.awt.image.Image. Implement all required methods, most importantly, the makeImageRep method for creating native representations of the image.
It is not necessary to create an implementation of the sun.awt.image.ImageRepresentation class, but it is necessary to implement the native methods required by this class. These methods need to support creating native bitmaps, reading and writing pixel data in numerous formats, drawing the image into a native graphics context and allowing a new native graphics context to be created that allow a Graphics object to draw into this image.
It is not necessary to create an implementation of the sun.awt.image.OffScreenImageSource class, but it is necessary to implement the sendPixels native method required by this class. This method should provide the ability to request pixel data from a native image.
Implement the drawImage methods for drawing images into the native graphics context owned by each instance of the Graphics class.
Supporting single font strings is relatively straightforward. The Font class is used to wrap a single native font and the Graphics and FontMetrics classes access this native font to display and measure strings. However, support for multifont strings is considerably more involved. The sun.awt.PlatformFont class allows for strings of text to be represented using multiple fonts where the string contains characters from different character sets. To support this feature, the native code must be able to process each string as a sequence of substrings, using a different font for each piece.
Create this class by extending the abstract class sun.awt.PlatformFont. Implement all required methods, remembering that Java strings contain Unicode characters and may need conversion for the native graphics library.
Create this class by extending the abstract class java.awt.FontMetrics. Implement all required methods for measuring the attributes of a font. When implementing string size methods, this class must allow for multi-font strings.
Implement the text related methods for selecting fonts and displaying and measuring strings.
Implement the getFont and getFontMetrics methods for the Truffle window system.
The AWT recognizes system and custom cursors. To support system cursors, an implementation of the CursorImage class need only provide the means to identify system cursors for later selection. To support custom cursors, the CursorImage class should provide the means to create a native cursor based on an ImageRepresentation object, which ultimately contains a native bitmap. The GraphicsSystem class should then be able to select a Cursor as the currently active cursor when requested.
Create this class by extending the abstract class sun.porting.graphicssystem.CursorImage. Implement all required methods, most importantly, those needed to to identify system cursors and create custom cursors.
Implement cursor specific methods for creating, showing and hiding cursors.
Truffle uses the Model-View-Controller design pattern to provide a flexible framework for developing multiple look & feel designs. The look is represented by the view and control. Touchable is an example of a look with an implementation in src/reference that can be modified or replaced. The feel is represented by the controller which is implemented by classes in the OTK.
This architecture allows an implementor to concentrate on developing a look while reusing the feel implementation in OTK.
The following steps outline the procedure for developing a new look & feel design.
Truffle provides an input method framework that supports input methods written in the Java programming language or a language like C.
Because it is written entirely in the Java programming language, the Truffle input method framework itself does not require any porting effort. The basic task for a licensee is to write an input method adapter class for supporting a platform-based input method. This adapter class should extend sun.awt.otk.InputMethodAdapter. Example input method adapters are described below.
src/share/classes/sun/awt/otk/SampleInputMethod.java is a short example of an input method written in the Java programming language.
The Truffle virtual keyboard is implemented as an input method adapter. While it is more complex than an input method adapter for a platform-level input method, it represents a better example than the X11 adapter described below because it is fully based on sun.awt.otk.InputMethodAdapter. The source code is in share/classes/sun/awt/otk/InputMethodAdapter.java.
The X11 input method adapter is an example of how to write an input method adapter class based on a native input method.
Source File | Description |
---|---|
src/solaris/sun/sun/awt/motif/X11InputMethod.java | Java class for X11 input method adapter. |
src/solaris/sun/sun/awt_InputMethod.c | Native method for X11 input method adapter. |
Note: The X11 input method adapter is not ideal for the following reasons:
A production input method adapter class for a Truffle implementation should avoid these limitations.
Truffle includes support for a virtual keyboard as an alternate text input device. The PJAE does not provide any application-level API for virtual keyboards. Applications still use the standard API in java.awt.
Since the virtual keyboard implementation is written entirely in the Java programming language, there is no porting effort required. There are two areas where a licensee can modify the virtual keyboard functionality:
The two reference virtual keyboard layouts are provided in src/reference/classes/sun/awt/touchable can be used as examples for building alternate keyboard layouts:
Layout Class | Description |
---|---|
VirtualKeyboard_en_US_QWERTY_1.java | QWERTY keyboard for the English/US locale. |
VirtualKeyboard_ja_JP_GOJUUON.java | Kana keyboard for the Japanese locale. This keyboard has a three position radio button at the bottom that switches between Latin-1, Katakana and Hiragana input. |
Key events and key sequence events are associated with action classes. The table below shows three levels of action classes.
Event Type | Virtual | Touchable | Kana |
---|---|---|---|
Key Event | VirtualKey | TouchableVirtualKey | TouchableVirtualKanaKey |
Key Sequence Event | VirtualKeySet | TouchableVirtualKeySet | TouchableVirtualKanaKeySet |
In many cases, the default action class for the look & feel design is sufficient. More complex virtual keyboards may require additional support. TouchableVirtualKanaKey.java and TouchableVirtualKanaKeySet.java in src/reference/classes/sun/awt/touchable are examples of how to do this. They are used by the keyboard layout class in VirtualKeyboard_ja_JP_GOJUUON.java.
In JDK 1.1, input method support for non-text components is only provided to components that have key listeners attached to them. Since these listeners are a feature of the JDK 1.1 event model, Java applications that use the JDK 1.0 event model are unsupported.
The Truffle input method framework provides the IMForOldEvents class as optional support for non-text components that use the JDK 1.0 event model.
Because Truffle's virtual keyboard implementation is based on the Truffle input method framework, it is important to use IMForOldEvents to avoid losing virtual keyaboard support for Java software that uses the JDK 1.0 event model.
To provide this support, IMForOldEvents examines the target class and determines if the JDK 1.0 event model is being used. If so, it adds the appropriate listeners to enable the input method support. When a listener callback is invoked, it creates a JDK 1.0-style event and forwards it the target class.
All that is required to provide input method support is a key listener. However, once a listener is added, java.awt.Component assumes that the component entirely supports the JDK 1.1 event model and hence does not deliver any events via the JDK 1.0 mechanism. To work around this, when IMForOldEvents receives a request to add a key listener, all relevant listeners are added. When invoked, these listeners create a JDK 1.0 equivalent event (where one exists) and forward it to the component. In cases where no matching JDK 1.0 event exists, it is ignored.
Here's how to use IMForOldEvents:
imSupport = new IMForOldEvents(this);
imSupport.addListeners(target, model);
imSupport.removeListeners((Component)target, (ComponentModel)peer);