1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
2 <HTML>
3 <HEAD>
4 <TITLE>Using the Multiplexing Look and Feel</TITLE>
5 </HEAD>
6
7 <BODY BGCOLOR="#FFFFFF" TEXT="#000000">
8
9 <b>
10 <font size=+3>
11 Using the Multiplexing Look and Feel
12 </font>
13 </b>
14
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>
27
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>
45
46
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>
63
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>
76
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>
83
84
85 <p>
86
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).
95
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>
109
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>
121
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>
130
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>
137
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.
144
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>
151
152
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>
167
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>
178
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>
184
185 <p>
186 <code>
187 swing.auxiliarylaf=com.myco.TextTalkerLookAndFeel,<br>
188 com.smellco.OlfactoryLookAndFeel</code>
189 </p>
190
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>
200
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>
207
208
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.
217
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.
224
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>
232
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>
241
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>
248
249 <p>
250 The following paragraphs provide some general recommendations for developing
251 auxiliary look and feels.
252 </p>
253
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>
304
305 <br>
306 <a name="uidefaults">
307 <font color="#000080" size="+1"><b>Extending UIDefaults</b></font>
308 </a>
309
310 <p>In many cases, you
311 might want an auxiliary look and feel to be "incomplete." 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
338 new MyAuxUIDefaults();<br>
339 </b> Object[] uiDefaults = {<br>
340 "ButtonUI", "MyAuxButtonUI",<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 // ("An
352 annoying message!");<br>
353 }<br>
354 }</b></code></p>
355
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>
365
366 <br>
367 <a name="defaultui">
368 <b><font color="#000080" size="+1">Examining Other UI Objects</font></b>
369 </a>
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 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>
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 "just work" -- 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 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>
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 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>
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>