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