1. /*
  2. * @(#)MultiLookAndFeel.java 1.33 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing.plaf.multi;
  8. import java.util.Vector;
  9. import java.lang.reflect.Method;
  10. import javax.swing.*;
  11. import javax.swing.plaf.*;
  12. /**
  13. * <p>A multiplexing look and feel that allows more than one UI
  14. * to be associated with a component at the same time.
  15. * The primary look and feel is called
  16. * the <em>default</em> look and feel,
  17. * and the other look and feels are called <em>auxiliary</em>.
  18. * <p>
  19. *
  20. * For further information, see
  21. * <a href="doc-files/multi_tsc.html" target="_top">Using the
  22. * Multiplexing Look and Feel.</a>
  23. *
  24. * <p>
  25. * <strong>Warning:</strong>
  26. * Serialized objects of this class will not be compatible with
  27. * future Swing releases. The current serialization support is
  28. * appropriate for short term storage or RMI between applications running
  29. * the same version of Swing. As of 1.4, support for long term storage
  30. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  31. * has been added to the <code>java.beans</code> package.
  32. * Please see {@link java.beans.XMLEncoder}.
  33. *
  34. * @see UIManager#addAuxiliaryLookAndFeel
  35. * @see javax.swing.plaf.multi
  36. *
  37. * @version 1.33 01/23/03
  38. * @author Willie Walker
  39. */
  40. public class MultiLookAndFeel extends LookAndFeel {
  41. //////////////////////////////
  42. // LookAndFeel methods
  43. //////////////////////////////
  44. /**
  45. * Returns a string, suitable for use in menus,
  46. * that identifies this look and feel.
  47. *
  48. * @return a string such as "Multiplexing Look and Feel"
  49. */
  50. public String getName() {
  51. return "Multiplexing Look and Feel";
  52. }
  53. /**
  54. * Returns a string, suitable for use by applications/services,
  55. * that identifies this look and feel.
  56. *
  57. * @return "Multiplex"
  58. */
  59. public String getID() {
  60. return "Multiplex";
  61. }
  62. /**
  63. * Returns a one-line description of this look and feel.
  64. *
  65. * @return a descriptive string such as "Allows multiple UI instances per component instance"
  66. */
  67. public String getDescription() {
  68. return "Allows multiple UI instances per component instance";
  69. }
  70. /**
  71. * Returns <code>false</code>
  72. * this look and feel is not native to any platform.
  73. *
  74. * @return <code>false</code>
  75. */
  76. public boolean isNativeLookAndFeel() {
  77. return false;
  78. }
  79. /**
  80. * Returns <code>true</code>
  81. * every platform permits this look and feel.
  82. *
  83. * @return <code>true</code>
  84. */
  85. public boolean isSupportedLookAndFeel() {
  86. return true;
  87. }
  88. /**
  89. * Creates, initializes, and returns
  90. * the look and feel specific defaults.
  91. * For this look and feel,
  92. * the defaults consist solely of
  93. * mappings of UI class IDs
  94. * (such as "ButtonUI")
  95. * to <code>ComponentUI</code> class names
  96. * (such as "javax.swing.plaf.multi.MultiButtonUI").
  97. *
  98. * @return an initialized <code>UIDefaults</code> object
  99. * @see javax.swing.JComponent#getUIClassID
  100. */
  101. public UIDefaults getDefaults() {
  102. UIDefaults table = new MultiUIDefaults();
  103. String packageName = "javax.swing.plaf.multi.Multi";
  104. Object[] uiDefaults = {
  105. "ButtonUI", packageName + "ButtonUI",
  106. "CheckBoxMenuItemUI", packageName + "MenuItemUI",
  107. "CheckBoxUI", packageName + "ButtonUI",
  108. "ColorChooserUI", packageName + "ColorChooserUI",
  109. "ComboBoxUI", packageName + "ComboBoxUI",
  110. "DesktopIconUI", packageName + "DesktopIconUI",
  111. "DesktopPaneUI", packageName + "DesktopPaneUI",
  112. "EditorPaneUI", packageName + "TextUI",
  113. "FileChooserUI", packageName + "FileChooserUI",
  114. "FormattedTextFieldUI", packageName + "TextUI",
  115. "InternalFrameUI", packageName + "InternalFrameUI",
  116. "LabelUI", packageName + "LabelUI",
  117. "ListUI", packageName + "ListUI",
  118. "MenuBarUI", packageName + "MenuBarUI",
  119. "MenuItemUI", packageName + "MenuItemUI",
  120. "MenuUI", packageName + "MenuItemUI",
  121. "OptionPaneUI", packageName + "OptionPaneUI",
  122. "PanelUI", packageName + "PanelUI",
  123. "PasswordFieldUI", packageName + "TextUI",
  124. "PopupMenuSeparatorUI", packageName + "SeparatorUI",
  125. "PopupMenuUI", packageName + "PopupMenuUI",
  126. "ProgressBarUI", packageName + "ProgressBarUI",
  127. "RadioButtonMenuItemUI", packageName + "MenuItemUI",
  128. "RadioButtonUI", packageName + "ButtonUI",
  129. "RootPaneUI", packageName + "RootPaneUI",
  130. "ScrollBarUI", packageName + "ScrollBarUI",
  131. "ScrollPaneUI", packageName + "ScrollPaneUI",
  132. "SeparatorUI", packageName + "SeparatorUI",
  133. "SliderUI", packageName + "SliderUI",
  134. "SpinnerUI", packageName + "SpinnerUI",
  135. "SplitPaneUI", packageName + "SplitPaneUI",
  136. "TabbedPaneUI", packageName + "TabbedPaneUI",
  137. "TableHeaderUI", packageName + "TableHeaderUI",
  138. "TableUI", packageName + "TableUI",
  139. "TextAreaUI", packageName + "TextUI",
  140. "TextFieldUI", packageName + "TextUI",
  141. "TextPaneUI", packageName + "TextUI",
  142. "ToggleButtonUI", packageName + "ButtonUI",
  143. "ToolBarSeparatorUI", packageName + "SeparatorUI",
  144. "ToolBarUI", packageName + "ToolBarUI",
  145. "ToolTipUI", packageName + "ToolTipUI",
  146. "TreeUI", packageName + "TreeUI",
  147. "ViewportUI", packageName + "ViewportUI",
  148. };
  149. table.putDefaults(uiDefaults);
  150. return table;
  151. }
  152. ///////////////////////////////
  153. // Utility methods for the UI's
  154. ///////////////////////////////
  155. /**
  156. * Creates the <code>ComponentUI</code> objects
  157. * required to present
  158. * the <code>target</code> component,
  159. * placing the objects in the <code>uis</code> vector and
  160. * returning the
  161. * <code>ComponentUI</code> object
  162. * that best represents the component's UI.
  163. * This method finds the <code>ComponentUI</code> objects
  164. * by invoking
  165. * <code>getDefaults().getUI(target)</code> on each
  166. * default and auxiliary look and feel currently in use.
  167. * The first UI object this method adds
  168. * to the <code>uis</code> vector
  169. * is for the default look and feel.
  170. * <p>
  171. * This method is invoked by the <code>createUI</code> method
  172. * of <code>MultiXxxxUI</code> classes.
  173. *
  174. * @param mui the <code>ComponentUI</code> object
  175. * that represents the complete UI
  176. * for the <code>target</code> component;
  177. * this should be an instance
  178. * of one of the <code>MultiXxxxUI</code> classes
  179. * @param uis a <code>Vector</code>
  180. * generally this is the <code>uis</code> field
  181. * of the <code>mui</code> argument
  182. * @param target a component whose UI is represented by <code>mui</code>
  183. *
  184. * @return <code>mui</code> if the component has any auxiliary UI objects;
  185. * otherwise, returns the UI object for the default look and feel
  186. * or <code>null</code> if the default UI object couldn't be found
  187. *
  188. * @see javax.swing.UIManager#getAuxiliaryLookAndFeels
  189. * @see javax.swing.UIDefaults#getUI
  190. * @see MultiButtonUI#uis
  191. * @see MultiButtonUI#createUI
  192. */
  193. public static ComponentUI createUIs(ComponentUI mui,
  194. Vector uis,
  195. JComponent target) {
  196. ComponentUI ui;
  197. // Make sure we can at least get the default UI
  198. //
  199. ui = UIManager.getDefaults().getUI(target);
  200. if (ui != null) {
  201. uis.addElement(ui);
  202. LookAndFeel[] auxiliaryLookAndFeels;
  203. auxiliaryLookAndFeels = UIManager.getAuxiliaryLookAndFeels();
  204. if (auxiliaryLookAndFeels != null) {
  205. for (int i = 0; i < auxiliaryLookAndFeels.length; i++) {
  206. ui = auxiliaryLookAndFeels[i].getDefaults().getUI(target);
  207. if (ui != null) {
  208. uis.addElement(ui);
  209. }
  210. }
  211. }
  212. } else {
  213. return null;
  214. }
  215. // Don't bother returning the multiplexing UI if all we did was
  216. // get a UI from just the default look and feel.
  217. //
  218. if (uis.size() == 1) {
  219. return (ComponentUI) uis.elementAt(0);
  220. } else {
  221. return mui;
  222. }
  223. }
  224. /**
  225. * Creates an array,
  226. * populates it with UI objects from the passed-in vector,
  227. * and returns the array.
  228. * If <code>uis</code> is null,
  229. * this method returns an array with zero elements.
  230. * If <code>uis</code> is an empty vector,
  231. * this method returns <code>null</code>.
  232. * A run-time error occurs if any objects in the <code>uis</code> vector
  233. * are not of type <code>ComponentUI</code>.
  234. *
  235. * @param uis a vector containing <code>ComponentUI</code> objects
  236. * @return an array equivalent to the passed-in vector
  237. *
  238. */
  239. protected static ComponentUI[] uisToArray(Vector uis) {
  240. if (uis == null) {
  241. return new ComponentUI[0];
  242. } else {
  243. int count = uis.size();
  244. if (count > 0) {
  245. ComponentUI[] u = new ComponentUI[count];
  246. for (int i = 0; i < count; i++) {
  247. u[i] = (ComponentUI)uis.elementAt(i);
  248. }
  249. return u;
  250. } else {
  251. return null;
  252. }
  253. }
  254. }
  255. }
  256. /**
  257. * We want the Multiplexing LookAndFeel to be quiet and fallback
  258. * gracefully if it cannot find a UI. This class overrides the
  259. * getUIError method of UIDefaults, which is the method that
  260. * emits error messages when it cannot find a UI class in the
  261. * LAF.
  262. */
  263. class MultiUIDefaults extends UIDefaults {
  264. protected void getUIError(String msg) {
  265. System.err.println("Multiplexing LAF: " + msg);
  266. }
  267. }