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