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, 2017, 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
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>
202 swing.auxiliarylaf=com.myco.TextTalkerLookAndFeel,<br>
203 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">
255 <h3>Dos and Don'ts</h3>
256 </a>
257
258 <p>
259 The following paragraphs provide some general recommendations for developing
260 auxiliary look and feels.
261 </p>
262
263 <p>
264 <h4>Use the <code>installUI</code> method
265 to perform all initialization,
266 and the <code>uninstallUI</code> method
267 to perform all cleanup.</h4>
268
269 <blockquote>
270 The <code>installUI</code> and <code>uninstallUI</code>
271 methods are invoked when a component's look and feel is set.
272 The <code>installUI</code> method gives the new UI object
273 a chance to add listeners on the component and its data model.
274 Similarly, the <code>uninstallUI</code> method
275 lets the previous UI object remove its listeners.
276 </blockquote>
277 <h4><b>Don't extend visual look and feels.</b></h4>
278 <blockquote>
279 We recommended that you <i>don't</i> implement
280 UI classes of an auxiliary look and feel as subclasses of the
281 UI classes of a visual look and feel. Why not? Because they might
282 accidentally inherit code that installs listeners on a component
283 object or renders the component on the display. As a result,
284 your auxiliary look and feel would compete with the default look
285 and feel rather than cooperating with it.<br>
286 <br>
287 Instead, we recommend that the UI classes of an auxiliary look
288 and feel directly extend the abstract UI classes in the <code>javax.swing.plaf</code>
289 package. By using this strategy, the developer of an auxiliary
290 look and feel can avoid competing with the default look and feel.
291 </blockquote>
292 <h4><b>Override all UI-specific methods your UI classes inherit.</b></h4>
293
294 <blockquote>
295 We recommend that each UI class of
296 an auxiliary look and feel override the methods
297 defined in the <code>javax.swing.plaf</code>
298 UI classes it descends from
299 The reasons for this recommendation are similar
300 to those for not extending a visual look and feel.
301 For example, the <code>ComponentUI</code>
302 class, from which all UI classes descend,
303 provides a default implementation for the <code>update</code>
304 method. This default implementation paints on the display
305 if the
306 component is opaque. If a UI class from a non-visual auxiliary
307 look and feel does not override this method, all
308 opaque components appear as blank areas on the screen!
309 </blockquote>
310
311 <a id="uidefaults"></a>
312 <h3>Extending UIDefaults</h3>
313
314 <p>In many cases, you
315 might want an auxiliary look and feel to be "incomplete." That
316 is, you might not need to support the complete set
317 of components.
318 For example, an auxiliary look and feel might choose
319 to provide a <code>ButtonUI</code> subclass but no
320 <code>LabelUI</code> subclass.
321 This
322 option is allowed, and the multiplexing look and feel gracefully
323 handles such situations.</p>
324 <p>By default, however, Swing issues an error message when it asks
325 a look and feel for a UI object and the look and feel does not
326 support that UI. This message can be annoying, especially to auxiliary
327 look-and-feel developers who don't want to support a particular
328 component.</p>
329 <p>Fortunately, you can prevent this error
330 message by creating a subclass of the <code>UIDefaults</code>
331 class and returning an instance of it from the
332 <code>getDefaults</code> method
333 of your <code>LookAndFeel</code> class.
334 For example:
335 </p>
336 <p><code>public class MyAuxLookAndFeel
337 extends LookAndFeel {<br>
338 ...<br>
339 public UIDefaults getDefaults() {<br>
340 <b>UIDefaults table = <br>
341
342 new MyAuxUIDefaults();<br>
343 </b> Object[] uiDefaults = {<br>
344 "ButtonUI", "MyAuxButtonUI",<br>
345 ...<br>
346 }<br>
347 table.putDefaults(uiDefaults);<br>
348 return table;<br>
349 }<br>
350 }<br>
351 <br>
352 <b>class MyAuxUIDefaults extends UIDefaults {<br>
353 protected void getUIError(String msg) {<br>
354 //System.err.println<br>
355 // ("An
356 annoying message!");<br>
357 }<br>
358 }</b></code></p>
359
360 <p>
361 In the preceding example, an auxiliary look and feel named <code>MyAux</code>
362 creates a <code>UIDefaults</code> subclass
363 that overrides the <code>getUIError</code>
364 method. The <code>getUIError</code>
365 method is the method that is invoked when Swing cannot find a UI
366 object in a look and feel. By merely doing nothing in this method,
367 you can avoid the error message.</p>
368 <p>
369
370 <a id="defaultui"></a>
371 <h3>Examining Other UI Objects</h3>
372
373 <p>In
374 rare instances, a UI object from an auxiliary look and feel
375 may be interested in the default UI object used by the component. In
376 these cases, the UI object from auxiliary look and feel can obtain
377 the UI from a component by calling its <code>getUI</code>
378 method. The returned UI is an instance of one of the multiplexing
379 look and feel UI classes (for example, <code>MultiButtonUI</code>).
380 The UI object from the auxiliary look and feel can call the <code>getUIs</code>
381 method of the returned object to obtain an array containing a complete list
382 of all UI objects handled by the multiplexing UI. The first element
383 is guaranteed to be the UI created from the default look and feel.
384 </p>
385
386 <p>
387 <a id="implementation"></a>
388 <hr>
389 <h2>How the Multiplexing Look and Feel Is Implemented</h2>
390
391 <p>
392 The Multiplexing look and feel
393 (represented by
394 <code>javax.swing.plaf.multi.MultiLookAndFeel</code>)
395 is meant to be transparent to
396 all developers and users. It should "just work" -- and
397 it is used only when the user tells Swing to use an auxiliary look
398 and feel.</p>
399
400 <p>
401 When the Multiplexing look and
402 feel is in use, the type of the UI object
403 associated with each component
404 depends on whether
405 any of the auxiliary look and feels currently in use
406 support the component.
407 If so, the component's UI object is
408 an instance of a multiplexing UI.
409 If only the default look and feel supports the component,
410 then the component gets
411 a UI object from the default look and feel,
412 just as if no auxiliary look and feels were installed.
413
414 <p>
415 A multiplexing UI object
416 obtains and maintains UI objects
417 from the default and auxiliary look
418 and feels,
419 referring to these UIs in the following manner:
420
421 <ul>
422 <li> The UI object from the default look
423 and feel is always the first to be created. After that, a UI object
424 is created from each auxiliary look and feel in the order
425 they are specified in the <code>swing.auxiliarylaf</code>
426 property.<br><br></li>
427
428 <li> When a method that requests information
429 from a UI object is invoked, the multiplexing UI object
430 invokes the method on all the UI objects, but returns
431 only the results from the UI for the default look and feel.
432 For example, when the <code>getPreferredSize</code>
433 method is invoked on a multiplexing UI, the UI returns only the
434 results of invoking <code>getPreferredSize</code>
435 on the UI obtained from the default look and feel.
436 The <code>getPreferredSize</code> method
437 is also invoked on the UI object for each auxiliary look and feel,
438 but the return values are ignored.
439 <br><br></li>
440
441 <li> When a method that does not request information
442 from the UI object is invoked, the multiplexing UI object
443 invokes that method on all UIs --
444 on the UI object obtained from the default look
445 and feel
446 and on all the UIs obtained from the auxiliary look and feels,
447 as well.
448 For example, invoking the <code>installUI</code>
449 method on a multiplexing UI causes the multiplexing UI to invoke
450 <code>installUI</code>
451 on the UI obtained from the default look and feel and the UIs obtained from
452 the auxiliary factories.</li>
453 </ul>
454 <p> In all cases, the UI object obtained from
455 the default look and feel is acted upon first, and then the auxiliary
456 look and feels are acted upon in the order they are specified in
457 the <code>swing.auxiliarylaf</code>
458 property.
459 </p>
460
461 <p>
462
463 <a id="custom"></a>
464 <hr>
465 <h2>How to Provide a Custom Multiplexing Look and Feel</h2>
466
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>
473
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>
488
489 <p>
490 <code>swing.plaf.multiplexinglaf = com.myco.SuperMultiLookAndFeel</code>
491 </p>
492
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>
500
501 </body>
502 </html>