| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> |
| <HTML> |
| <HEAD> |
| <TITLE>Using the Multiplexing Look and Feel</TITLE> |
| </HEAD> |
| |
| <BODY BGCOLOR="#FFFFFF" TEXT="#000000"> |
| |
| <b> |
| <font size=+3> |
| Using the Multiplexing Look and Feel |
| </font> |
| </b> |
| |
| <blockquote> |
| <hr> |
| <i> |
| <p> |
| This document is based on an article |
| originally published in |
| <a href="http://java.sun.com/products/jfc/tsc/" target="_top"><em>The Swing |
| Connection</em></a>. |
| </p> |
| </i> |
| <hr> |
| </blockquote> |
| |
| <p> |
| The Multiplexing look and feel lets |
| you supplement an ordinary look and feel |
| (called the <em>default</em> look and feel) |
| with one or more <em>auxiliary</em> look and feels. |
| For example, you could |
| simultaneously provide text-to-speech and Braille outputs, |
| in addition to the ordinary visual output that a Swing-based |
| application generates, |
| by adding |
| two auxiliary look and feels (one for text-to-speech, |
| the other for Braille) |
| to the default look and feel. |
| The default look and feel can be any ordinary look and feel -- |
| the Java or Windows look and feel, for example -- |
| and requires no modifications to work with auxiliary look and feels. |
| </p> |
| |
| </p> |
| |
| <p> |
| This document has the following sections: |
| <ul> |
| <li> <a href="#overview">Overview</a> |
| <li> <a href="#howtouse">How to Use Auxiliary Look and Feels</a> |
| <li> <a href="#howtowrite">Tips for Writing an Auxiliary Look and Feel</a> |
| <ul> |
| <li> <a href="#dosanddonts">Dos and Don'ts</a> |
| <li> <a href="#uidefaults">Extending UIDefaults</a> |
| <li> <a href="#defaultui">Examining Other UI Objects</a> |
| </ul> |
| <li> <a href="#implementation">How the Multiplexing Look and Feel is |
| Implemented</a> |
| <li> <a href="#custom">How to Provide a Custom Multiplexing |
| Look and Feel</a> |
| </ul> |
| |
| <p> |
| Before reading further, you should be familiar |
| with the concept of pluggable look and feels. |
| For basic information, see |
| <a href="http://java.sun.com/docs/books/tutorial/uiswing/lookandfeel/plaf.html">How to Set the Look and Feel</a>, |
| a section in |
| <em>The Java Tutorial</em>. |
| For architectural details, you can read |
| <a |
| href="http://java.sun.com/products/jfc/tsc/articles/architecture/#pluggable">Pluggable look-and-feel architecture</a>, a section within |
| a <em>Swing Connection</em> article. |
| </p> |
| |
| <p> |
| <a name="overview"> |
| <hr width=100% align=LEFT size=2> |
| </a> |
| <b> |
| <font color="#000080" size="+2">Overview</font> |
| </b> |
| |
| <p></p> |
| |
| <p> |
| |
| The classes in the |
| <code>javax.swing.plaf.multi</code> package |
| implement a |
| <i>multiplexing look and feel</i>. |
| A multiplexing look and feel transparently creates -- and |
| simultaneously supports -- UI objects from several different look and feels |
| in response to a component requesting its UI object |
| (with the <code>getUI</code> method). |
| |
| <p> |
| Without a multiplexing look and feel, a |
| developer who wanted to enhance a particular look and feel would |
| need to extend the classes supporting that look and feel. For example, to |
| add text-to-speech support to the Java look and feel without using a multiplexing |
| look and feel, the developer would need to create a group of |
| classes that extend those of |
| the Java look and feel, and add text-to-speech support to the new classes. |
| If the developer also wanted to add text-to-speech support to other look |
| and feels, |
| such as Motif or Windows, the developers would need to create subclasses |
| of those classes as well. |
| </p> |
| |
| <p> |
| This approach has at least two shortcomings: |
| <ul type="DISC"> |
| <li>First, each subclass must use what is |
| essentially a copy of the same code, potentially creating a difficult |
| support situation for the developer.<br></li> |
| <li>Second, and more significantly for the |
| end user, some application developers might force a |
| particular look and feel to be used. When this approach is used, |
| the end user can't even use the enhanced look and feel.</li> |
| </ul> |
| |
| <p> |
| A multiplexing look and feel |
| both these problems simultaneously because it allows multiple look |
| and feels to be combined. |
| The first problem (having to use what amounts to a second copy of the same |
| code) is solved because the developer can create a specialized look |
| and feel that can then be combined with other look and feels. |
| </p> |
| |
| <p> |
| The second problem (having to force the use of |
| a particular look and feel) is solved because a specialized look and feel |
| can be used with whatever default look and feel the |
| application may have locked in place. |
| </p> |
| |
| <p> |
| The default multiplexing look and feel implementation, |
| represented by the <code>MultiLookAndFeel</code> class |
| in the <code>javax.swing.plaf.multi</code> package, |
| is called (unsurprisingly) |
| the Multiplexing look and feel. |
| |
| <p> |
| <a name="howtouse"> |
| <hr width=100% align=LEFT size=2> |
| </a> |
| <b> |
| <font color="#000080" size="+2">How to Use Auxiliary Look and Feels</font> |
| </b> |
| |
| <p></p> |
| |
| <p> |
| It's easy to use auxiliary look and feels with Swing. To instruct |
| Swing to use the Multiplexing look and feel, all an application |
| has to do is modify the <code>$JDKHOME/lib/swing.properties</code> |
| file to include a definition of the <code>swing.auxiliarylaf</code> |
| property. Swing treats the <code>swing.auxiliarylaf</code> |
| property as a comma-separated list of <code>LookAndFeel</code> |
| subclasses that specify what auxiliary look and feels should be |
| used in addition to the default look and feel. If at least one valid |
| <code>LookAndFeel</code> |
| subclass is specified in the <code>swing.auxiliarylaf</code> |
| property, Swing automatically uses the Multiplexing look and feel |
| to load and support the default and auxiliary look and feels. |
| </p> |
| |
| <p> |
| For example, let's assume that an application |
| makes use of a look and feel that supports text-to-speech feedback, and also |
| uses an look and feel that adds support for a device |
| that emits perfume. |
| Let's assume that the text-to-speech |
| look and feel is named <code>com.myco.TextTalkerLookAndFeel</code>, |
| and the look and feel that adds support for perfume |
| is named <code>com.smellco.OlfactoryLookAndFeel</code>. |
| </p> |
| |
| <p> |
| To tell Swing to use both these look and feels |
| -- and to use a default look and feel at the same time -- your application |
| could simply add the following line to the <code>$JDKHOME/lib/swing.properties</code> file: |
| </p> |
| |
| <p> |
| <code> |
| swing.auxiliarylaf=com.myco.TextTalkerLookAndFeel,<br> |
| com.smellco.OlfactoryLookAndFeel</code> |
| </p> |
| |
| <p> |
| This statement tells Swing to obtain a component's UI from the Multiplexing |
| look and feel automatically, instead of obtaining it directly from |
| the default look and feel. The resulting multiplexing UI is a small |
| delegate that obtains and maintains UIs from the default and auxiliary |
| look and feels. As a result, when a method is invoked in a multiplexing |
| UI object, the multiplexing UI invokes the same method on each |
| of the UIs obtained from the default and auxiliary look and feels. |
| </p> |
| |
| <p> |
| <a name="howtowrite"> |
| <hr width=100% align=LEFT size=2> |
| </a> |
| <b> |
| <font color="#000080" size="+2">Tips for Writing an Auxiliary Look and Feel</font> |
| </b> |
| |
| <p></p> |
| |
| <p> |
| An auxiliary look and feel is like any other look and feel, |
| except that it doesn't have to provide the complete support |
| that a default look and feel must. For |
| example, an auxiliary look and feel that supports just text-to-speech feedback |
| doesn't need to provide any code for painting. |
| Also, it might not need to support all components -- |
| <code>JSeparator</code>s, for example, might be ignored. |
| |
| <p> |
| Auxiliary look and feels tend to be simple, |
| so developing one can be easier than developing a visual |
| look and feel. |
| The developer can concentrate solely |
| on providing the specialized functionality. |
| |
| <p> |
| Because the primary purpose of an auxiliary look and feel is to enhance the |
| default look and feel, auxiliary look and feels tend |
| be nonvisual. Since an auxiliary look and feel is a genuine |
| look and feel, however, there is nothing to prevent it |
| from rendering information on the display. |
| </p> |
| |
| <p> |
| Just like for any other look and feel, you |
| implement an auxiliary look and feel |
| by writing a subclass of <code>javax.swing.LookAndFeel</code> |
| and creating subclasses of the |
| <code><em>Foo</em>UI</code> classes defined in |
| the <code>javax.swing.plaf</code> package. |
| </p> |
| |
| <p> |
| <br> |
| <a name="dosanddonts"> |
| <font color="#000080" size="+1"><b>Dos and Don'ts</b></font> |
| </a> |
| </p> |
| <p></p> |
| |
| <p> |
| The following paragraphs provide some general recommendations for developing |
| auxiliary look and feels. |
| </p> |
| |
| <p> |
| <font color="#000080"><b>Use the <code>installUI</code> method |
| to perform all initialization, |
| and the <code>uninstallUI</code> method |
| to perform all cleanup.</b></font> |
| </font> |
| </p> |
| <ul> |
| <p> |
| The <code>installUI</code> and <code>uninstallUI</code> |
| methods are invoked when a component's look and feel is set. |
| The <code>installUI</code> method gives the new UI object |
| a chance to add listeners on the component and its data model. |
| Similarly, the <code>uninstallUI</code> method |
| lets the previous UI object remove its listeners. |
| </p> |
| </ul> |
| <p> <font color="#000080"><b>Don't extend |
| visual look and feels.</b></font></p> |
| <ul> |
| <p> We recommended that you <i>don't</i> implement |
| UI classes of an auxiliary look and feel as subclasses of the |
| UI classes of a visual look and feel. Why not? Because they might |
| accidentally inherit code that installs listeners on a component |
| object or renders the component on the display. As a result, |
| your auxiliary look and feel would compete with the default look |
| and feel rather than cooperating with it.<br> |
| <br> |
| Instead, we recommend that the UI classes of an auxiliary look |
| and feel directly extend the abstract UI classes in the <code>javax.swing.plaf</code> |
| package. By using this strategy, the developer of an auxiliary |
| look and feel can avoid competing with the default look and feel.</p> |
| </ul> |
| <p> <font color="#000080"><b>Override all UI-specific methods |
| your UI classes inherit.</b></font> |
| </p> |
| <ul> |
| <p> We recommend that each UI class of |
| an auxiliary look and feel override the methods |
| defined in the <code>javax.swing.plaf</code> |
| UI classes it descends from |
| The reasons for this recommendation are similar |
| to those for not extending a visual look and feel. |
| For example, the <code>ComponentUI</code> |
| class, from which all UI classes descend, |
| provides a default implementation for the <code>update</code> |
| method. This default implementation paints on the display |
| if the |
| component is opaque. If a UI class from a non-visual auxiliary |
| look and feel does not override this method, all |
| opaque components appear as blank areas on the screen!</p> |
| </ul> |
| <p> |
| |
| <br> |
| <a name="uidefaults"> |
| <font color="#000080" size="+1"><b>Extending UIDefaults</b></font> |
| </a> |
| <p></p> |
| |
| <p>In many cases, you |
| might want an auxiliary look and feel to be "incomplete." That |
| is, you might not need to support the complete set |
| of components. |
| For example, an auxiliary look and feel might choose |
| to provide a <code>ButtonUI</code> subclass but no |
| <code>LabelUI</code> subclass. |
| This |
| option is allowed, and the multiplexing look and feel gracefully |
| handles such situations.</p> |
| <p>By default, however, Swing issues an error message when it asks |
| a look and feel for a UI object and the look and feel does not |
| support that UI. This message can be annoying, especially to auxiliary |
| look-and-feel developers who don't want to support a particular |
| component.</p> |
| <p>Fortunately, you can prevent this error |
| message by creating a subclass of the <code>UIDefaults</code> |
| class and returning an instance of it from the |
| <code>getDefaults</code> method |
| of your <code>LookAndFeel</code> class. |
| For example: |
| </p> |
| <p><code>public class MyAuxLookAndFeel |
| extends LookAndFeel {<br> |
| ...<br> |
| public UIDefaults getDefaults() {<br> |
| <b>UIDefaults table = <br> |
| |
| new MyAuxUIDefaults();<br> |
| </b> Object[] uiDefaults = {<br> |
| "ButtonUI", "MyAuxButtonUI",<br> |
| ...<br> |
| }<br> |
| table.putDefaults(uiDefaults);<br> |
| return table;<br> |
| }<br> |
| }<br> |
| <br> |
| <b>class MyAuxUIDefaults extends UIDefaults {<br> |
| protected void getUIError(String msg) {<br> |
| //System.err.println<br> |
| // ("An |
| annoying message!");<br> |
| }<br> |
| }</b></code></p> |
| |
| <p> |
| In the preceding example, an auxiliary look and feel named <code>MyAux</code> |
| creates a <code>UIDefaults</code> subclass |
| that overrides the <code>getUIError</code> |
| method. The <code>getUIError</code> |
| method is the method that is invoked when Swing cannot find a UI |
| object in a look and feel. By merely doing nothing in this method, |
| you can avoid the error message.</p> |
| <p> |
| |
| <br> |
| <a name="defaultui"> |
| <b><font color="#000080" size="+1">Examining Other UI Objects</font></b> |
| </a> |
| <p></p> |
| |
| <p>In |
| rare instances, a UI object from an auxiliary look and feel |
| may be interested in the default UI object used by the component. In |
| these cases, the UI object from auxiliary look and feel can obtain |
| the UI from a component by calling its <code>getUI</code> |
| method. The returned UI is an instance of one of the multiplexing |
| look and feel UI classes (for example, <code>MultiButtonUI</code>). |
| The UI object from the auxiliary look and feel can call the <code>getUIs</code> |
| method of the returned object to obtain an array containing a complete list |
| of all UI objects handled by the multiplexing UI. The first element |
| is guaranteed to be the UI created from the default look and feel. |
| </p> |
| |
| <p> |
| <a name="implementation"> |
| <hr width=100% align=LEFT size=2> |
| </a> |
| <font color="#000080" size="+2"><b>How the Multiplexing Look and Feel |
| Is Implemented</b></font> |
| <p></p> |
| |
| <p> |
| The Multiplexing look and feel |
| (represented by |
| <code>javax.swing.plaf.multi.MultiLookAndFeel</code>) |
| is meant to be transparent to |
| all developers and users. It should "just work" -- and |
| it is used only when the user tells Swing to use an auxiliary look |
| and feel.</p> |
| |
| <p> |
| When the Multiplexing look and |
| feel is in use, the type of the UI object |
| associated with each component |
| depends on whether |
| any of the auxiliary look and feels currently in use |
| support the component. |
| If so, the component's UI object is |
| an instance of a multiplexing UI. |
| If only the default look and feel supports the component, |
| then the component gets |
| a UI object from the default look and feel, |
| just as if no auxiliary look and feels were installed. |
| |
| <p> |
| A multiplexing UI object |
| obtains and maintains UI objects |
| from the default and auxiliary look |
| and feels, |
| referring to these UIs in the following manner: |
| |
| <ul type="DISC"> |
| <li> The UI object from the default look |
| and feel is always the first to be created. After that, a UI object |
| is created from each auxiliary look and feel in the order |
| they are specified in the <code>swing.auxiliarylaf</code> |
| property.</li> |
| <p> |
| <li> When a method that requests information |
| from a UI object is invoked, the multiplexing UI object |
| invokes the method on all the UI objects, but returns |
| only the results from the UI for the default look and feel. |
| For example, when the <code>getPreferredSize</code> |
| method is invoked on a multiplexing UI, the UI returns only the |
| results of invoking <code>getPreferredSize</code> |
| on the UI obtained from the default look and feel. |
| The <code>getPreferredSize</code> method |
| is also invoked on the UI object for each auxiliary look and feel, |
| but the return values are ignored. |
| </li> |
| <p> |
| <li> When a method that does not request information |
| from the UI object is invoked, the multiplexing UI object |
| invokes that method on all UIs -- |
| on the UI object obtained from the default look |
| and feel |
| and on all the UIs obtained from the auxiliary look and feels, |
| as well. |
| For example, invoking the <code>installUI</code> |
| method on a multiplexing UI causes the multiplexing UI to invoke |
| <code>installUI</code> |
| on the UI obtained from the default look and feel and the UIs obtained from |
| the auxiliary factories.</li> |
| </ul> |
| <p> In all cases, the UI object obtained from |
| the default look and feel is acted upon first, and then the auxiliary |
| look and feels are acted upon in the order they are specified in |
| the <code>swing.auxiliarylaf</code> |
| property. |
| </p> |
| |
| <p> |
| |
| <a name="custom"> |
| <hr width=100% align=LEFT size=2> |
| </a> |
| <font color="#000080" size="+2"><b>How to Provide a Custom Multiplexing Look |
| and Feel</b></font> |
| <p></p> |
| |
| <p><font color="#000080" size="+2"><b></b></font>While |
| we hope the behavior of the Multiplexing look and feel is |
| flexible enough not to require an alternative multiplexing look |
| and feel, Swing allows the user to specify another multiplexing look |
| and feel to use. |
| </p> |
| |
| <p> To do that, all the user has to do is modify |
| the <code>$JDKHOME/lib/swing.properties</code> |
| file to include a definition of the <code>swing.plaf.multiplexinglaf</code> |
| property. Swing then treats the <code>swing.plaf.multiplexinglaf</code> |
| property as a <code>LookAndFeel</code> |
| subclass that supports multiplexing. |
| </p> |
| <p> For example, if a user has a multiplexing |
| look and feel represented by <code>com.myco.SuperMultiLookAndFeel</code> |
| that is a better match for their needs than the Multiplexing |
| look and feel |
| (<code>javax.swing.plaf.multi.MultiLookAndFeel</code>), |
| the user could include the following line in <code>$JDKHOME/lib/swing.properties</code>: |
| </p> |
| |
| <p> |
| <code>swing.plaf.multiplexinglaf = com.myco.SuperMultiLookAndFeel</code> |
| </p> |
| |
| <p> |
| This statement instructs Swing to use <code>com.myco.SuperMultiLookAndFeel</code> |
| instead of <code>javax.swing.plaf.multi.MultiLookAndFeel</code>. But |
| if you use this kind of statement, be careful, because the suppliers |
| of auxiliary look and feels will most likely have developed and |
| tested against our Multiplexing look and feel. |
| </p> |
| |
| </BODY> |
| </HTML> |