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