1 /* 2 * Copyright (c) 1997, 2014, 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™ 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 @SuppressWarnings("serial") // Same-version serialization only 60 public class MultiLookAndFeel extends LookAndFeel { 61 62 ////////////////////////////// 63 // LookAndFeel methods 64 ////////////////////////////// 65 66 /** 67 * Returns a string, suitable for use in menus, 68 * that identifies this look and feel. 69 * 70 * @return a string such as "Multiplexing Look and Feel" 71 */ 72 public String getName() { 73 return "Multiplexing Look and Feel"; 74 } 75 76 /** 77 * Returns a string, suitable for use by applications/services, 78 * that identifies this look and feel. 79 * 80 * @return "Multiplex" 81 */ 82 public String getID() { 83 return "Multiplex"; 84 } 85 86 /** 87 * Returns a one-line description of this look and feel. 88 * 89 * @return a descriptive string such as "Allows multiple UI instances per component instance" 90 */ 91 public String getDescription() { 92 return "Allows multiple UI instances per component instance"; 93 } 94 95 /** 96 * Returns <code>false</code>; 97 * this look and feel is not native to any platform. 98 * 99 * @return <code>false</code> 100 */ 101 public boolean isNativeLookAndFeel() { 102 return false; 103 } 104 105 /** 106 * Returns <code>true</code>; 107 * every platform permits this look and feel. 108 * 109 * @return <code>true</code> 110 */ 111 public boolean isSupportedLookAndFeel() { 112 return true; 113 } 114 115 /** 116 * Creates, initializes, and returns 117 * the look and feel specific defaults. 118 * For this look and feel, 119 * the defaults consist solely of 120 * mappings of UI class IDs 121 * (such as "ButtonUI") 122 * to <code>ComponentUI</code> class names 123 * (such as "javax.swing.plaf.multi.MultiButtonUI"). 124 * 125 * @return an initialized <code>UIDefaults</code> object 126 * @see javax.swing.JComponent#getUIClassID 127 */ 128 public UIDefaults getDefaults() { 129 String packageName = "javax.swing.plaf.multi.Multi"; 130 Object[] uiDefaults = { 131 "ButtonUI", packageName + "ButtonUI", 132 "CheckBoxMenuItemUI", packageName + "MenuItemUI", 133 "CheckBoxUI", packageName + "ButtonUI", 134 "ColorChooserUI", packageName + "ColorChooserUI", 135 "ComboBoxUI", packageName + "ComboBoxUI", 136 "DesktopIconUI", packageName + "DesktopIconUI", 137 "DesktopPaneUI", packageName + "DesktopPaneUI", 138 "EditorPaneUI", packageName + "TextUI", 139 "FileChooserUI", packageName + "FileChooserUI", 140 "FormattedTextFieldUI", packageName + "TextUI", 141 "InternalFrameUI", packageName + "InternalFrameUI", 142 "LabelUI", packageName + "LabelUI", 143 "ListUI", packageName + "ListUI", 144 "MenuBarUI", packageName + "MenuBarUI", 145 "MenuItemUI", packageName + "MenuItemUI", 146 "MenuUI", packageName + "MenuItemUI", 147 "OptionPaneUI", packageName + "OptionPaneUI", 148 "PanelUI", packageName + "PanelUI", 149 "PasswordFieldUI", packageName + "TextUI", 150 "PopupMenuSeparatorUI", packageName + "SeparatorUI", 151 "PopupMenuUI", packageName + "PopupMenuUI", 152 "ProgressBarUI", packageName + "ProgressBarUI", 153 "RadioButtonMenuItemUI", packageName + "MenuItemUI", 154 "RadioButtonUI", packageName + "ButtonUI", 155 "RootPaneUI", packageName + "RootPaneUI", 156 "ScrollBarUI", packageName + "ScrollBarUI", 157 "ScrollPaneUI", packageName + "ScrollPaneUI", 158 "SeparatorUI", packageName + "SeparatorUI", 159 "SliderUI", packageName + "SliderUI", 160 "SpinnerUI", packageName + "SpinnerUI", 161 "SplitPaneUI", packageName + "SplitPaneUI", 162 "TabbedPaneUI", packageName + "TabbedPaneUI", 163 "TableHeaderUI", packageName + "TableHeaderUI", 164 "TableUI", packageName + "TableUI", 165 "TextAreaUI", packageName + "TextUI", 166 "TextFieldUI", packageName + "TextUI", 167 "TextPaneUI", packageName + "TextUI", 168 "ToggleButtonUI", packageName + "ButtonUI", 169 "ToolBarSeparatorUI", packageName + "SeparatorUI", 170 "ToolBarUI", packageName + "ToolBarUI", 171 "ToolTipUI", packageName + "ToolTipUI", 172 "TreeUI", packageName + "TreeUI", 173 "ViewportUI", packageName + "ViewportUI", 174 }; 175 176 UIDefaults table = new MultiUIDefaults(uiDefaults.length / 2, 0.75f); 177 table.putDefaults(uiDefaults); 178 return table; 179 } 180 181 /////////////////////////////// 182 // Utility methods for the UI's 183 /////////////////////////////// 184 185 /** 186 * Creates the <code>ComponentUI</code> objects 187 * required to present 188 * the <code>target</code> component, 189 * placing the objects in the <code>uis</code> vector and 190 * returning the 191 * <code>ComponentUI</code> object 192 * that best represents the component's UI. 193 * This method finds the <code>ComponentUI</code> objects 194 * by invoking 195 * <code>getDefaults().getUI(target)</code> on each 196 * default and auxiliary look and feel currently in use. 197 * The first UI object this method adds 198 * to the <code>uis</code> vector 199 * is for the default look and feel. 200 * <p> 201 * This method is invoked by the <code>createUI</code> method 202 * of <code>MultiXxxxUI</code> classes. 203 * 204 * @param mui the <code>ComponentUI</code> object 205 * that represents the complete UI 206 * for the <code>target</code> component; 207 * this should be an instance 208 * of one of the <code>MultiXxxxUI</code> classes 209 * @param uis a <code>Vector</code>; 210 * generally this is the <code>uis</code> field 211 * of the <code>mui</code> argument 212 * @param target a component whose UI is represented by <code>mui</code> 213 * 214 * @return <code>mui</code> if the component has any auxiliary UI objects; 215 * otherwise, returns the UI object for the default look and feel 216 * or <code>null</code> if the default UI object couldn't be found 217 * 218 * @see javax.swing.UIManager#getAuxiliaryLookAndFeels 219 * @see javax.swing.UIDefaults#getUI 220 * @see MultiButtonUI#uis 221 * @see MultiButtonUI#createUI 222 */ 223 public static ComponentUI createUIs(ComponentUI mui, 224 Vector<ComponentUI> uis, 225 JComponent target) { 226 ComponentUI ui; 227 228 // Make sure we can at least get the default UI 229 // 230 ui = UIManager.getDefaults().getUI(target); 231 if (ui != null) { 232 uis.addElement(ui); 233 LookAndFeel[] auxiliaryLookAndFeels; 234 auxiliaryLookAndFeels = UIManager.getAuxiliaryLookAndFeels(); 235 if (auxiliaryLookAndFeels != null) { 236 for (int i = 0; i < auxiliaryLookAndFeels.length; i++) { 237 ui = auxiliaryLookAndFeels[i].getDefaults().getUI(target); 238 if (ui != null) { 239 uis.addElement(ui); 240 } 241 } 242 } 243 } else { 244 return null; 245 } 246 247 // Don't bother returning the multiplexing UI if all we did was 248 // get a UI from just the default look and feel. 249 // 250 if (uis.size() == 1) { 251 return uis.elementAt(0); 252 } else { 253 return mui; 254 } 255 } 256 257 /** 258 * Creates an array, 259 * populates it with UI objects from the passed-in vector, 260 * and returns the array. 261 * If <code>uis</code> is null, 262 * this method returns an array with zero elements. 263 * If <code>uis</code> is an empty vector, 264 * this method returns <code>null</code>. 265 * A run-time error occurs if any objects in the <code>uis</code> vector 266 * are not of type <code>ComponentUI</code>. 267 * 268 * @param uis a vector containing <code>ComponentUI</code> objects 269 * @return an array equivalent to the passed-in vector 270 * 271 */ 272 protected static ComponentUI[] uisToArray(Vector<? extends ComponentUI> uis) { 273 if (uis == null) { 274 return new ComponentUI[0]; 275 } else { 276 int count = uis.size(); 277 if (count > 0) { 278 ComponentUI[] u = new ComponentUI[count]; 279 for (int i = 0; i < count; i++) { 280 u[i] = uis.elementAt(i); 281 } 282 return u; 283 } else { 284 return null; 285 } 286 } 287 } 288 } 289 290 /** 291 * We want the Multiplexing LookAndFeel to be quiet and fallback 292 * gracefully if it cannot find a UI. This class overrides the 293 * getUIError method of UIDefaults, which is the method that 294 * emits error messages when it cannot find a UI class in the 295 * LAF. 296 */ 297 @SuppressWarnings("serial") // Superclass is not serializable across versions 298 class MultiUIDefaults extends UIDefaults { 299 MultiUIDefaults(int initialCapacity, float loadFactor) { 300 super(initialCapacity, loadFactor); 301 } 302 protected void getUIError(String msg) { 303 System.err.println("Multiplexing LAF: " + msg); 304 } 305 }