2 <HTML>
   3 <HEAD>
   4 <TITLE>Using the Multiplexing Look and Feel</TITLE>
   5 </HEAD>
   7 <BODY BGCOLOR="#FFFFFF" TEXT="#000000">
   9 <b>
  10 <font size=+3>
  11 Using the Multiplexing Look and Feel
  12 </font>
  13 </b>
  15 <blockquote>
  16 <hr>
  17 <p>
  18 <i>
  19 This document is based on an article
  20 originally published in
  21 <a href="http://www.oracle.com/technetwork/java/javase/tech/articles-jsp-139072.html" target="_top"><em>The Swing
  22 Connection</em></a>.
  23 </i>
  24 </p>
  25 <hr>
  26 </blockquote>
  28 <p>
  29 The Multiplexing look and feel lets
  30 you supplement an ordinary look and feel
  31 (called the <em>default</em> look and feel)
  32 with one or more <em>auxiliary</em> look and feels.
  33 For example, you could
  34 simultaneously provide text-to-speech and Braille outputs, 
  35 in addition to the ordinary visual output that a Swing-based 
  36 application generates,
  37 by adding 
  38 two auxiliary look and feels (one for text-to-speech,
  39 the other for Braille)
  40 to the default look and feel.
  41 The default look and feel can be any ordinary look and feel --
  42 the Java or Windows look and feel, for example --
  43 and requires no modifications to work with auxiliary look and feels.
  44 </p>
  47 <p>
  48 This document has the following sections:
  49 <ul>
  50 <li> <a href="#overview">Overview</a>
  51 <li> <a href="#howtouse">How to Use Auxiliary Look and Feels</a>
  52 <li> <a href="#howtowrite">Tips for Writing an Auxiliary Look and Feel</a>
  53      <ul>
  54      <li> <a href="#dosanddonts">Dos and Don'ts</a>
  55      <li> <a href="#uidefaults">Extending UIDefaults</a>
  56      <li> <a href="#defaultui">Examining Other UI Objects</a>
  57      </ul>
  58 <li> <a href="#implementation">How the Multiplexing Look and Feel is
  59      Implemented</a>
  60 <li> <a href="#custom">How to Provide a Custom Multiplexing
  61      Look and Feel</a>
  62 </ul>
  64 <p>
  65 Before reading further, you should be familiar 
  66 with the concept of pluggable look and feels.
  67 For basic information, see
  68 <a href="https://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html">How to Set the Look and Feel</a>,
  69 a section in 
  70 <em>The Java Tutorial</em>.
  71 For architectural details, you can read
  72 <a
  73 href="http://www.oracle.com/technetwork/java/architecture-142923.html#pluggable">Pluggable look-and-feel architecture</a>, a section within
  74 a <em>Swing Connection</em> article.
  75 </p>
  77 <p> 
  78 <a name="overview"></a>
  79 <hr width=100% align=LEFT size=2>
  80 <b>
  81 <font color="#000080" size="+2">Overview</font>
  82 </b>
  85 <p>
  87 The classes in the 
  88 <code>javax.swing.plaf.multi</code> package
  89 implement a 
  90 <i>multiplexing look and feel</i>.
  91 A multiplexing look and feel transparently creates -- and 
  92 simultaneously supports -- UI objects from several different look and feels
  93 in response to a component requesting its UI object
  94 (with the <code>getUI</code> method).
  96 <p>
  97 Without a multiplexing look and feel, a 
  98 developer who wanted to enhance a particular look and feel would 
  99 need to extend the classes supporting that look and feel. For example, to 
 100 add text-to-speech support to the Java look and feel without using a multiplexing 
 101 look and feel, the developer would need to create a group of
 102 classes that extend those of
 103 the Java look and feel, and add text-to-speech support to the new classes. 
 104 If the developer also wanted to add text-to-speech support to other look
 105 and feels, 
 106 such as Motif or Windows, the developers would need to create subclasses 
 107 of those classes as well.
 108 </p>
 110 <p>
 111 This approach has at least two shortcomings: 
 112 <ul type="DISC">
 113   <li>First, each subclass must use what is 
 114       essentially a copy of the same code, potentially creating a difficult 
 115       support situation for the developer.<br></li>
 116   <li>Second, and more significantly for the 
 117       end user, some application developers might force a
 118       particular look and feel to be used. When this approach is used, 
 119       the end user can't even use the enhanced look and feel.</li>
 120 </ul>
 122 <p>
 123 A multiplexing look and feel 
 124 both these problems simultaneously because it allows multiple look 
 125 and feels to be combined.
 126 The first problem (having to use what amounts to a second copy of the same 
 127 code) is solved because the developer can create a specialized look 
 128 and feel that can then be combined with other look and feels.
 129 </p>
 131 <p>
 132 The second problem (having to force the use of 
 133 a particular look and feel) is solved because a specialized look and feel 
 134 can be used with whatever default look and feel the 
 135 application may have locked in place.
 136 </p>
 138 <p>
 139 The default multiplexing look and feel implementation, 
 140 represented by the <code>MultiLookAndFeel</code> class
 141 in the <code>javax.swing.plaf.multi</code> package,
 142 is called (unsurprisingly) 
 143 the Multiplexing look and feel.
 145 <p> 
 146 <a name="howtouse"></a>
 147 <hr width=100% align=LEFT size=2>
 148 <b>
 149 <font color="#000080" size="+2">How to Use Auxiliary Look and Feels</font>
 150 </b>
 153 <p>
 154 It's easy to use auxiliary look and feels with Swing. To instruct 
 155 Swing to use the Multiplexing look and feel, all an application 
 156 has to do is modify the <code>$JDKHOME/conf/swing.properties</code>
 157 file to include a definition of the <code>swing.auxiliarylaf</code>
 158 property. Swing treats the <code>swing.auxiliarylaf</code>
 159 property as a comma-separated list of <code>LookAndFeel</code>
 160 subclasses that specify what auxiliary look and feels should be 
 161 used in addition to the default look and feel. If at least one valid 
 162 <code>LookAndFeel</code>
 163 subclass is specified in the <code>swing.auxiliarylaf</code>
 164 property, Swing automatically uses the Multiplexing look and feel 
 165 to load and support the default and auxiliary look and feels.
 166 </p>
 168 <p>
 169 For example, let's assume that an application 
 170 makes use of a look and feel that supports text-to-speech feedback, and also 
 171 uses an look and feel that adds support for a device
 172 that emits perfume.
 173 Let's assume that the text-to-speech
 174 look and feel is named <code>com.myco.TextTalkerLookAndFeel</code>, 
 175 and the look and feel that adds support for perfume
 176 is named <code>com.smellco.OlfactoryLookAndFeel</code>.
 177 </p>
 179 <p>
 180 To tell Swing to use both these look and feels 
 181 -- and to use a default look and feel at the same time -- your application 
 182 could simply add the following line to the <code>$JDKHOME/conf/swing.properties</code> file:
 183 </p>
 185 <p>
 186 <code>&nbsp;&nbsp;&nbsp; 
 187               swing.auxiliarylaf=com.myco.TextTalkerLookAndFeel,<br>
 188               &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; com.smellco.OlfactoryLookAndFeel</code>
 189 </p>
 191 <p>
 192 This statement tells Swing to obtain a component's UI from the Multiplexing 
 193 look and feel automatically, instead of obtaining it directly from 
 194 the default look and feel. The resulting multiplexing UI is a small 
 195 delegate that obtains and maintains UIs from the default and auxiliary 
 196 look and feels. As a result, when a method is invoked in a multiplexing 
 197 UI object, the multiplexing UI invokes the same method on each 
 198 of the UIs obtained from the default and auxiliary look and feels.
 199 </p>
 201 <p> 
 202 <a name="howtowrite"></a>
 203 <hr width=100% align=LEFT size=2>
 204 <b>
 205 <font color="#000080" size="+2">Tips for Writing an Auxiliary Look and Feel</font>
 206 </b>
 209 <p>
 210 An auxiliary look and feel is like any other look and feel,
 211 except that it doesn't have to provide the complete support 
 212 that a default look and feel must. For 
 213 example, an auxiliary look and feel that supports just text-to-speech feedback 
 214 doesn't need to provide any code for painting. 
 215 Also, it might not need to support all components --
 216 <code>JSeparator</code>s, for example, might be ignored.
 218 <p>
 219 Auxiliary look and feels tend to be simple,
 220 so developing one can be easier than developing a visual 
 221 look and feel.
 222 The developer can concentrate solely 
 223 on providing the specialized functionality. 
 225 <p>
 226 Because the primary purpose of an auxiliary look and feel is to enhance the 
 227 default look and feel, auxiliary look and feels tend 
 228 be nonvisual. Since an auxiliary look and feel is a genuine
 229 look and feel, however, there is nothing to prevent it
 230 from rendering information on the display.
 231 </p>
 233 <p>
 234 Just like for any other look and feel, you
 235 implement an auxiliary look and feel
 236 by writing a subclass of <code>javax.swing.LookAndFeel</code>
 237 and creating subclasses of the 
 238 <code><em>Foo</em>UI</code> classes defined in
 239 the <code>javax.swing.plaf</code> package.
 240 </p>
 242 <p> 
 243 <br>
 244 <a name="dosanddonts">
 245 <font color="#000080" size="+1"><b>Dos and Don'ts</b></font> 
 246 </a>
 247 </p>
 249 <p>
 250 The following paragraphs provide some general recommendations for developing 
 251 auxiliary look and feels.
 252 </p>
 254 <p>
 255 <font color="#000080"><b>Use the <code>installUI</code> method
 256 to perform all initialization,
 257 and the <code>uninstallUI</code> method
 258 to perform all cleanup.</b></font>
 259 </p>
 260 <blockquote>
 261 The <code>installUI</code> and <code>uninstallUI</code>
 262 methods are invoked when a component's look and feel is set.
 263 The <code>installUI</code> method gives the new UI object
 264 a chance to add listeners on the component and its data model.
 265 Similarly, the <code>uninstallUI</code> method
 266 lets the previous UI object remove its listeners.
 267 </blockquote>
 268             <p> <font color="#000080"><b>Don't extend 
 269               visual look and feels.</b></font></p>
 270 <blockquote>
 271                We recommended that you <i>don't</i> implement 
 272                 UI classes of an auxiliary look and feel as subclasses of the 
 273                 UI classes of a visual look and feel. Why not? Because they might 
 274                 accidentally inherit code that installs listeners on a component 
 275                 object or renders the component on the display. As a result, 
 276                 your auxiliary look and feel would compete with the default look 
 277                 and feel rather than cooperating with it.<br>
 278                 <br>
 279                 Instead, we recommend that the UI classes of an auxiliary look 
 280                 and feel directly extend the abstract UI classes in the <code>javax.swing.plaf</code> 
 281                 package. By using this strategy, the developer of an auxiliary 
 282                 look and feel can avoid competing with the default look and feel.
 283 </blockquote>
 284             <p> <font color="#000080"><b>Override all UI-specific methods
 285             your UI classes inherit.</b></font>
 286             </p>
 287 <blockquote>
 288                We recommend that each UI class of 
 289                 an auxiliary look and feel override the methods 
 290                 defined in the <code>javax.swing.plaf</code>
 291                 UI classes it descends from
 292                 The reasons for this recommendation are similar 
 293                 to those for not extending a visual look and feel.
 294                 For example, the <code>ComponentUI</code>
 295                 class, from which all UI classes descend,
 296                 provides a default implementation for the <code>update</code>
 297                 method. This default implementation paints on the display
 298                 if the 
 299                 component is opaque. If a UI class from a non-visual auxiliary 
 300                 look and feel does not override this method, all 
 301                 opaque components appear as blank areas on the screen!
 302 </blockquote>
 303             <p> 
 305 <br>
 306 <a name="uidefaults">
 307 <font color="#000080" size="+1"><b>Extending UIDefaults</b></font> 
 308 </a>
 310             <p>In many cases, you 
 311               might want an auxiliary look and feel to be &quot;incomplete.&quot; That 
 312               is, you might not need to support the complete set 
 313               of components.
 314             For example, an auxiliary look and feel might choose 
 315             to provide a <code>ButtonUI</code> subclass but no 
 316               <code>LabelUI</code> subclass.
 317              This 
 318               option is allowed, and the multiplexing look and feel gracefully 
 319               handles such situations.</p>
 320             <p>By default, however, Swing issues an error message when it asks 
 321               a look and feel for a UI object and the look and feel does not 
 322               support that UI. This message can be annoying, especially to auxiliary 
 323               look-and-feel developers who don't want to support a particular 
 324               component.</p>
 325             <p>Fortunately, you can prevent this error 
 326               message by creating a subclass of the <code>UIDefaults</code> 
 327               class and returning an instance of it from the 
 328               <code>getDefaults</code> method
 329               of your <code>LookAndFeel</code> class.
 330               For example:
 331               </p>
 332             <p><code>public class MyAuxLookAndFeel 
 333               extends LookAndFeel {<br>
 334                   ...<br>
 335                   public UIDefaults getDefaults() {<br>
 336                       <b>UIDefaults table = <br>
 337               &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
 338               new MyAuxUIDefaults();<br>
 339               </b>        Object[] uiDefaults = {<br>
 340                         &quot;ButtonUI&quot;, &quot;MyAuxButtonUI&quot;,<br>
 341                         ...<br>
 342                       }<br>
 343                       table.putDefaults(uiDefaults);<br>
 344                       return table;<br>
 345                   }<br>
 346               }<br>
 347               <br>
 348               <b>class MyAuxUIDefaults extends UIDefaults {<br>
 349                   protected void getUIError(String msg) {<br>
 350                       //System.err.println<br>
 351               &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; (&quot;An 
 352               annoying message!&quot;);<br>
 353                   }<br>
 354               }</b></code></p>
 356 <p>
 357 In the preceding example, an auxiliary look and feel named <code>MyAux</code> 
 358               creates a <code>UIDefaults</code> subclass 
 359               that overrides the <code>getUIError</code> 
 360               method. The <code>getUIError</code> 
 361               method is the method that is invoked when Swing cannot find a UI 
 362               object in a look and feel. By merely doing nothing in this method, 
 363               you can avoid the error message.</p>
 364             <p> 
 366 <br>
 367 <a name="defaultui">
 368 <b><font color="#000080" size="+1">Examining Other UI Objects</font></b> 
 369 </a>
 371             <p>In 
 372               rare instances, a UI object from an auxiliary look and feel 
 373               may be interested in the default UI object used by the component. In 
 374               these cases, the UI object from auxiliary look and feel can obtain 
 375               the UI from a component by calling its <code>getUI</code>
 376               method. The returned UI is an instance of one of the multiplexing 
 377               look and feel UI classes (for example, <code>MultiButtonUI</code>). 
 378               The UI object from the auxiliary look and feel can call the <code>getUIs</code> 
 379               method of the returned object to obtain an array containing a complete list 
 380               of all UI objects handled by the multiplexing UI. The first element 
 381               is guaranteed to be the UI created from the default look and feel.
 382               </p>
 384 <p> 
 385 <a name="implementation"></a>
 386 <hr width=100% align=LEFT size=2>
 387 <font color="#000080" size="+2"><b>How the Multiplexing Look and Feel
 388 Is Implemented</b></font> 
 390 <p>
 391 The Multiplexing look and feel
 392 (represented by
 393 <code>javax.swing.plaf.multi.MultiLookAndFeel</code>)
 394 is meant to be transparent to 
 395 all developers and users. It should &quot;just work&quot; -- and 
 396               it is used only when the user tells Swing to use an auxiliary look 
 397               and feel.</p>
 399             <p>
 400               When the Multiplexing look and 
 401               feel is in use, the type of the UI object 
 402               associated with each component 
 403               depends on whether 
 404               any of the auxiliary look and feels currently in use
 405               support the component.
 406               If so, the component's UI object is
 407               an instance of a multiplexing UI.
 408               If only the default look and feel supports the component,
 409               then the component gets
 410               a UI object from the default look and feel,
 411               just as if no auxiliary look and feels were installed. 
 413               <p>
 414               A multiplexing UI object
 415               obtains and maintains UI objects
 416               from the default and auxiliary look
 417               and feels,
 418               referring to these UIs in the following manner: 
 420 <ul type="DISC">
 421               <li> The UI object from the default look 
 422                 and feel is always the first to be created. After that, a UI object 
 423                 is created from each auxiliary look and feel in the order 
 424                 they are specified in the <code>swing.auxiliarylaf</code> 
 425                 property.<br><br></li>
 427               <li> When a method that requests information 
 428                 from a UI object is invoked, the multiplexing UI object 
 429                 invokes the method on all the UI objects, but returns 
 430                 only the results from the UI for the default look and feel.
 431                 For example, when the <code>getPreferredSize</code> 
 432                 method is invoked on a multiplexing UI, the UI returns only the 
 433                 results of invoking <code>getPreferredSize</code> 
 434                 on the UI obtained from the default look and feel.
 435                 The <code>getPreferredSize</code> method
 436                 is also invoked on the UI object for each auxiliary look and feel,
 437                 but the return values are ignored.
 438                 <br><br></li>
 440               <li> When a method that does not request information 
 441                 from the UI object is invoked, the multiplexing UI object 
 442                 invokes that method on all UIs --
 443                 on the UI object obtained from the default look
 444                 and feel
 445                 and on all the UIs obtained from the auxiliary look and feels,
 446                 as well. 
 447                 For example, invoking the <code>installUI</code> 
 448                 method on a multiplexing UI causes the multiplexing UI to invoke 
 449                 <code>installUI</code> 
 450                 on the UI obtained from the default look and feel and the UIs obtained from 
 451                 the auxiliary factories.</li>
 452             </ul>
 453             <p> In all cases, the UI object obtained from 
 454               the default look and feel is acted upon first, and then the auxiliary 
 455               look and feels are acted upon in the order they are specified in 
 456               the <code>swing.auxiliarylaf</code> 
 457               property.
 458 </p>
 460 <p> 
 462 <a name="custom"></a>
 463 <hr width=100% align=LEFT size=2>
 464 <font color="#000080" size="+2"><b>How to Provide a Custom Multiplexing Look
 465 and Feel</b></font> 
 467             <p>While 
 468               we hope the behavior of the Multiplexing look and feel is 
 469               flexible enough not to require an alternative multiplexing look 
 470               and feel, Swing allows the user to specify another multiplexing look 
 471               and feel to use.
 472 </p>
 474             <p> To do that, all the user has to do is modify 
 475               the <code>$JDKHOME/conf/swing.properties</code> 
 476               file to include a definition of the <code>swing.plaf.multiplexinglaf</code> 
 477               property. Swing then treats the <code>swing.plaf.multiplexinglaf</code> 
 478               property as a <code>LookAndFeel</code> 
 479               subclass that supports multiplexing.
 480 </p>
 481             <p> For example, if a user has a multiplexing 
 482               look and feel represented by <code>com.myco.SuperMultiLookAndFeel</code> 
 483               that is a better match for their needs than the Multiplexing 
 484               look and feel 
 485               (<code>javax.swing.plaf.multi.MultiLookAndFeel</code>), 
 486               the user could include the following line in <code>$JDKHOME/conf/swing.properties</code>:
 487 </p>
 489 <p>
 490 <code>swing.plaf.multiplexinglaf = com.myco.SuperMultiLookAndFeel</code>
 491 </p>
 493 <p>
 494 This statement instructs Swing to use <code>com.myco.SuperMultiLookAndFeel</code> 
 495 instead of <code>javax.swing.plaf.multi.MultiLookAndFeel</code>. But 
 496 if you use this kind of statement, be careful, because the suppliers 
 497 of auxiliary look and feels will most likely have developed and 
 498 tested against our Multiplexing look and feel.
 499 </p>
 501 </BODY>
 502 </HTML>