Contents

Swinging Duke
Feedback Button
Left ArrowRight Arrow

Because of Swing's pluggable look-and feel architecture, every component can be associated with a single user interface, and each UI can be obtained from a different UI factory (see the specification titled "The UIFactory Class.") Although this arrangement is very flexible, there are occasions where more extensibility might be helpful. For example, if you wanted to add audio feedback to set of components, Swing's single-UI-per-component approach would require you either to rewrite a UI factory or to subclass one. The same would be true if you wanted to keep the view part of a UI factory unchanged, but wanted to change its control part to support alternative input devices.

To make it easier to extend the capabilities of a user interface without modifying or subclassing a UI factory, Swing now has a multiplexing UI factory class. This new class can simultaneously and automatically create multiple user interfaces for different components from different UI factories. For example, you could use Swing's new multiplexing UI factory to automatically load and maintain a visual UI, an audio UI, and a Braille UI for a given component -- at the same time, and without requiring modifications to the visual UI.


Basic Concepts

When the multiplexing UI factory is used with a component, the component transparently obtains its user interface from the multiplexing UI factory instead of the default UI factory. This multiplexing UI factory is a small delegate that obtains and maintains UIs from the default factory and several auxiliary factories that represent the extra UI factories to be used in addition to the default UI factory.

These auxiliary factories are specified as a comma-separated list in the AuxiliaryProperties property in the uimanager.properties file. If this property is not set, the mutiplexing UI factory is not used. When the multiplexing UI factory that is used, you can customize it by using the MultiplexingFactory property in the uimanager.properties file. For example, to specify the default multiplexing UI factory, com.sun.java.swing.multi.MultiFactory, you would add the following line to uimanager.properties:

MultiplexingFactory=com.sun.java.swing.multi.MultiFactory

Note that it is not necessary to specify the multiplexing UI factory unless you want to override the default factory. If you don't want to override the default factory, the preceding line of code is not necessary because Swing automatically uses com.sun.java.swing.multi.MultiFactory if the MultiplexingFactory property is not set.

When the default multiplexing UI factory is in use, it creates UI delegates for all components that request a UI using the getUI method in the multiplexing UI factory. These delegates treat all UI methods in the following manner:

When the multiplexing UI is in use, changing the default factory continues to work as expected, but the change also results in the reinstallation of the auxiliary UIs as well.


Swing Infrastructure for the Multiplexing UI Factory

To support the multiplexing UI factory in Swing, we modified the static initializer for the UIManager class to check for the AuxiliaryFactories property in the uimanager.properties file. If this property exists, the UIManager's static initializer attempts to load each factory specified in the property. If the results of these attempts are successful -- that is, if at least one auxiliary factory is successfully loaded -- the static initializer then attempts to load the multiplexing UI factory itself. If this attempt succeeds, the multiplexing factory is used to obtain the UIs for the Swing components. If the attempt doesn't succeed, the auxiliary factories are effectively unloaded, and the default factory is used in place of of the multiplexing UI factory.

Before multiplexing UI factory support was added to Swing, each Swing component obtained its UI by asking the UIManager for the default UI factory, and then obtained its UI from the default factory by making a call something like this:

setUI((TabbedPaneUI)UIManager.getDefaultFactory().getUI( 
        "TabbedPaneUI", 
        "com.sun.java.swing.basic.BasicTabbedPaneUI", 
        this));

In order to provide a centralized location to support the multiplexing UI factory, we added a getUI method to UIManager itself, and modified the components to use this method instead:

setUI((TabbedPaneUI)UIManager.getUI( 
        "TabbedPaneUI", 
        "com.sun.java.swing.basic.BasicTabbedPaneUI", 
        this));

This new getUI method in UIManager is fairly simple and only uses the multiplexing UI factory if it is needed:

    static public ComponentUI getUI(String widgetName, 
                                    String defaultClassName,
                                    JComponent target) {
        if ((multiFactory != null) && (auxiliaryFactories != null)) {
            return multiFactory.getUI(widgetName,
                                      defaultClassName,
                                      target);
        } else {
            return getDefaultFactory().getUI(widgetName, 
                                             defaultClassName, 
                                             target);
        }
    }

Because Swing now uses the strategy shown above to support multiplexing UIs, no additional factory classes are loaded (not even the multiplexing factory class itself) if the multiplexing UI support is not desired. Furthermore, the supporting code for the multiplexing UI factory is small, simple, and adds a negligible amount of overhead.


The Default Multiplexing UI Factory

As mentioned previously, you can specify that you want Swing to use the multiplexing UI factory by adding the MultiplexingFactory property to the uimanager.properties file. The default multiplexing UI factory, com.sun.java.swing.multi, is included in swing.jar. We hope it is flexible enough not to require an alternative multiplexing UI factory.

The multiplexing UI factory implements the getUI method differently from the way in which getUI is implemented by a typical visual UI factory, such as the one one used by basic. In a typical UI factory, the getUI method is inherited from its parent class, UIFactory. The UIFactory's getUI method first tries to locate the UI class for widgetName in the factory itself (refer to the getUI method code snippet above for a list of the parameters to getUI), and resorts to using the UI class specified by defaultClassName if the factory does not support a class for widgetName. In any case, once the appropriate UI class is found, the UIFactory getUI method calls the createUI method on the UI class, passing only the target parameter.

Because the UIFactory's getUI method only passes the target parameter to the createUI method of the UI class, this method does not permit a multiplexing UI class to implement the same fallback mechanism for locating the default UI class. To fix this, the multiplexing UI factory overrides the getUI method of UIFactory and passes the same three parameters passed to the getUI method to the createUI methods of the multiplexing UI classes. When called, the createUI methods of the multiplexing UI classes first obtain the "real" UI using the same fallback mechanism implemented in the UIFactory getUI method. Then, the createUI methods obtain the auxiliary UIs from the auxiliary classes. If none of the auxiliary factories supports the UI for widgetName, the multiplexing UI class returns just the "real" UI class to help conserve memory. If at least one auxiliary factory supports the UI for widgetName, however, the multiplexing UI returns itself as a delegate UI.


Additions to the API

In order to support the multiplexing UI factory, we added a public getAuxiliaryFactories class method to the UIManager class:

static public UIFactory[] getAuxiliaryFactories();

This method returns the list of auxiliary factories to be used in obtaining the auxiliary UIs for a component and is used primarily by the multiplexing UIs to determine what extra UIs should be obtained.

In addition, the multiplexing UI classes provide a getUIs method that allows classes aware of multiplexing UIs to obtain the set of UIs used by a class:

public ComponentUI[] getUIs();

The first element in the array is guaranteed to be the "real" UI for the component.


What's Next

For this release of Swing, the multiplexing UI factory is meant to be relatively latent and just enough to support those who have requested this feature. Possible future work for the multiplexing UI factory will be additions to the UIManager class that allow procedural determination of the auxiliary and multiplexing UI factories.


Version 0.5. Last modified 09/04/97.
Copyright © 1995-97 Sun Microsystems, Inc. All Rights Reserved.

Sun's Home Page