Java tutorial
/* * Copyright (c) 2001-2013 JGoodies Software GmbH. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * o Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * o Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * o Neither the name of JGoodies Software GmbH nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jgoodies.looks.windows; import java.awt.Color; import java.awt.Font; import java.awt.Insets; import java.lang.reflect.Method; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.LookAndFeel; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; import javax.swing.plaf.IconUIResource; import javax.swing.plaf.InsetsUIResource; import javax.swing.plaf.basic.BasicBorders; import com.jgoodies.common.base.SystemUtils; import com.jgoodies.looks.FontPolicies; import com.jgoodies.looks.FontPolicy; import com.jgoodies.looks.FontSet; import com.jgoodies.looks.LookUtils; import com.jgoodies.looks.MicroLayout; import com.jgoodies.looks.MicroLayoutPolicies; import com.jgoodies.looks.MicroLayoutPolicy; import com.jgoodies.looks.Options; import com.jgoodies.looks.common.MinimumSizedIcon; import com.jgoodies.looks.common.RGBGrayFilter; import com.jgoodies.looks.common.ShadowPopupFactory; /** * The main class of the JGoodies Windows Look&Feel. * This look provides several corrections and extensions to Sun's Windows L&F. * In addition it tries to provide a unified look for the J2SE 1.4.0x, 1.4.1x, * 1.4.2, and 1.5 environments. * * @author Karsten Lentzsch * @version $Revision: 1.48 $ */ public class WindowsLookAndFeel extends com.sun.java.swing.plaf.windows.WindowsLookAndFeel { /** * An optional client property key for JMenu and JToolBar * to set a border style - shadows the header style. */ public static final String BORDER_STYLE_KEY = "jgoodies.windows.borderStyle"; /** * Returns the String "JGoodies Windows". * Note that this L&f's ID ("Windows") is inherited * from the superclass, because we don't do any fundamental changes. * * @see LookAndFeel#getID() */ @Override public String getName() { return "JGoodies Windows"; } @Override public String getDescription() { return "The JGoodies Windows Look and Feel" + " - \u00a9 2001-2013 JGoodies Software GmbH"; } // Optional Settings ****************************************************** /** * Looks up and retrieves the FontPolicy used by * the JGoodies Windows Look&Feel. * If a FontPolicy has been set for this look, it'll be returned. * Otherwise, this method checks if a FontPolicy or FontSet is defined * in the system properties or UIDefaults. If so, it is returned. * If no FontPolicy has been set for this look, in the system * properties or UIDefaults, the default Windows font policy * will be returned. * * @return the FontPolicy set for this Look&feel - if any, * the FontPolicy specified in the system properties or UIDefaults * - if any, or the default Windows font policy. * * @see #setFontPolicy * @see Options#WINDOWS_FONT_POLICY_KEY * @see FontPolicies * @see FontPolicies#customSettingsPolicy(FontPolicy) * @see FontPolicies#getDefaultWindowsPolicy() */ public static FontPolicy getFontPolicy() { FontPolicy policy = (FontPolicy) UIManager.get(Options.WINDOWS_FONT_POLICY_KEY); if (policy != null) { return policy; } FontPolicy defaultPolicy = FontPolicies.getDefaultWindowsPolicy(); return FontPolicies.customSettingsPolicy(defaultPolicy); } /** * Sets the FontPolicy to be used with the JGoodies Windows L&F. * If the specified policy is {@code null}, the default will be reset. * * @param fontPolicy the FontPolicy to be used with the JGoodies Windows * L&F, or {@code null} to reset to the default * * @see #getFontPolicy() * @see Options#WINDOWS_FONT_POLICY_KEY */ public static void setFontPolicy(FontPolicy fontPolicy) { UIManager.put(Options.WINDOWS_FONT_POLICY_KEY, fontPolicy); } /** * Looks up and retrieves the MicroLayoutPolicy used by * the JGoodies Windows Look&Feel. * If a MicroLayoutPolicy has been set for this look, it'll be returned. * Otherwise, the default Windows micro layout policy will be returned. * * @return the MicroLayoutPolicy set for this Look&feel - if any, * or the default Windows MicroLayoutPolicy. * * @see #setMicroLayoutPolicy * @see Options#WINDOWS_MICRO_LAYOUT_POLICY_KEY * @see MicroLayoutPolicies * @see MicroLayoutPolicies#getDefaultWindowsPolicy() */ public static MicroLayoutPolicy getMicroLayoutPolicy() { MicroLayoutPolicy policy = (MicroLayoutPolicy) UIManager.get(Options.WINDOWS_MICRO_LAYOUT_POLICY_KEY); return policy != null ? policy : MicroLayoutPolicies.getDefaultWindowsPolicy(); } /** * Sets the MicroLayoutPolicy to be used with the JGoodies Windows L&F. * If the specified policy is {@code null}, the default will be reset. * * @param microLayoutPolicy the MicroLayoutPolicy to be used with * the JGoodies Windows L&F, or {@code null} to reset * to the default * * @see #getMicroLayoutPolicy() * @see Options#WINDOWS_MICRO_LAYOUT_POLICY_KEY */ public static void setMicroLayoutPolicy(MicroLayout microLayoutPolicy) { UIManager.put(Options.WINDOWS_MICRO_LAYOUT_POLICY_KEY, microLayoutPolicy); } // Overriding Superclass Behavior *************************************** /** * Invoked during {@code UIManager#setLookAndFeel}. In addition * to the superclass behavior, we install the ShadowPopupFactory. * * @see #uninitialize */ @Override public void initialize() { super.initialize(); ShadowPopupFactory.install(); } /** * Invoked during {@code UIManager#setLookAndFeel}. In addition * to the superclass behavior, we uninstall the ShadowPopupFactory. * * @see #initialize */ @Override public void uninitialize() { super.uninitialize(); ShadowPopupFactory.uninstall(); } /** * Returns an icon with a disabled appearance. This method is used * to generate a disabled icon when one has not been specified.<p> * * This method will be used only on JDK 5.0 and later. * * @param component the component that will display the icon, may be null. * @param icon the icon to generate disabled icon from. * @return disabled icon, or null if a suitable icon can not be generated. */ @Override public Icon getDisabledIcon(JComponent component, Icon icon) { Icon disabledIcon = RGBGrayFilter.getDisabledIcon(component, icon); return disabledIcon != null ? new IconUIResource(disabledIcon) : null; } /** * Initializes the class defaults, that is, overrides some UI delegates * with JGoodies Windows implementations. */ @Override protected void initClassDefaults(UIDefaults table) { super.initClassDefaults(table); final String windowsPrefix = "com.jgoodies.looks.windows.Windows"; final String commonPrefix = "com.jgoodies.looks.common.ExtBasic"; // Overwrite some of the uiDefaults. Object[] uiDefaults = { // Modified size "ComboBoxUI", windowsPrefix + "ComboBoxUI", // Modified preferred height: can be even or odd "ButtonUI", windowsPrefix + "ButtonUI", // Can installs an optional etched border "ScrollPaneUI", windowsPrefix + "ScrollPaneUI", // Optional style and optional special borders "MenuBarUI", windowsPrefix + "MenuBarUI", // Provides an option for a no margin border "PopupMenuUI", windowsPrefix + "PopupMenuUI", // Honors the screen resolution and uses a minimum button width "OptionPaneUI", windowsPrefix + "OptionPaneUI", // 1.4.1 has ugly one touch triangles "SplitPaneUI", windowsPrefix + "SplitPaneUI", // Work in progress: Can have a flat presentation "TabbedPaneUI", windowsPrefix + "TabbedPaneUI", // Selects text after focus gained via keyboard "TextFieldUI", windowsPrefix + "TextFieldUI", "FormattedTextFieldUI", windowsPrefix + "FormattedTextFieldUI", // Selects text after focus gained via keyboard // Renders a dot, not the star ("*") character on Java 1.4 and 5 "PasswordFieldUI", windowsPrefix + "PasswordFieldUI", // Updates the disabled and inactive background "TextAreaUI", windowsPrefix + "TextAreaUI", // Corrected position of the tree button icon "TreeUI", windowsPrefix + "TreeUI", // Just to use shared UI delegate "SeparatorUI", windowsPrefix + "SeparatorUI", "SpinnerUI", windowsPrefix + "SpinnerUI" }; // Aligned menu items if (!SystemUtils.IS_OS_WINDOWS_6_OR_LATER || !SystemUtils.IS_LAF_WINDOWS_XP_ENABLED) { uiDefaults = append(uiDefaults, "MenuItemUI", windowsPrefix + "MenuItemUI"); uiDefaults = append(uiDefaults, "CheckBoxMenuItemUI", commonPrefix + "CheckBoxMenuItemUI"); uiDefaults = append(uiDefaults, "RadioButtonMenuItemUI", commonPrefix + "RadioButtonMenuItemUI"); // Has padding above and below the separator lines uiDefaults = append(uiDefaults, "PopupMenuSeparatorUI", commonPrefix + "PopupMenuSeparatorUI"); } if (SystemUtils.IS_LAF_WINDOWS_XP_ENABLED) { // Aligned menu items if (!SystemUtils.IS_OS_WINDOWS_6_OR_LATER) { uiDefaults = append(uiDefaults, "MenuUI", windowsPrefix + "XPMenuUI"); } // Optional style and optional special borders; // rollover borders for compound buttons uiDefaults = append(uiDefaults, "ToolBarUI", windowsPrefix + "XPToolBarUI"); // Honors XP table header style for custom user renderers. uiDefaults = append(uiDefaults, "TableHeaderUI", windowsPrefix + "XPTableHeaderUI"); } else { // Aligned menu items uiDefaults = append(uiDefaults, "MenuUI", commonPrefix + "MenuUI"); // Optional style and optional special borders; // rollover borders corrected uiDefaults = append(uiDefaults, "ToolBarUI", windowsPrefix + "ToolBarUI"); // Black arrows uiDefaults = append(uiDefaults, "ScrollBarUI", windowsPrefix + "ScrollBarUI"); } table.putDefaults(uiDefaults); } /** * Initializes the component defaults. */ @Override protected void initComponentDefaults(UIDefaults table) { super.initComponentDefaults(table); final boolean isXP = SystemUtils.IS_LAF_WINDOWS_XP_ENABLED; final boolean isClassic = !isXP; final boolean isVista = SystemUtils.IS_OS_WINDOWS_6_OR_LATER; initFontDefaults(table); if (isClassic) { initComponentDefaultsClassic(table); } MicroLayout microLayout = getMicroLayoutPolicy().getMicroLayout("Windows", table); if (!isVista || !SystemUtils.IS_LAF_WINDOWS_XP_ENABLED) { initMenuItemDefaults(table, microLayout); } Object marginBorder = new BasicBorders.MarginBorder(); Object checkBoxMargin = microLayout.getCheckBoxMargin(); Object etchedBorder = new UIDefaults.ProxyLazyValue("javax.swing.plaf.BorderUIResource", "getEtchedBorderUIResource"); Object buttonBorder = new SimpleProxyLazyValue("com.jgoodies.looks.windows.WindowsLookAndFeel", "getButtonBorder"); Object menuBorder = isXP ? WindowsBorders.getXPMenuBorder() : WindowsBorders.getMenuBorder(); Object menuBarEmptyBorder = marginBorder; Object menuBarSeparatorBorder = WindowsBorders.getSeparatorBorder(); Object menuBarEtchedBorder = WindowsBorders.getEtchedBorder(); Object menuBarHeaderBorder = WindowsBorders.getMenuBarHeaderBorder(); Object toolBarEmptyBorder = marginBorder; Object toolBarSeparatorBorder = WindowsBorders.getSeparatorBorder(); Object toolBarEtchedBorder = WindowsBorders.getEtchedBorder(); Object toolBarHeaderBorder = WindowsBorders.getToolBarHeaderBorder(); Object buttonMargin = microLayout.getButtonMargin(); Object toolBarSeparatorSize = null; Object textInsets = microLayout.getTextInsets(); Object wrappedTextInsets = microLayout.getWrappedTextInsets(); Insets comboEditorInsets = microLayout.getComboBoxEditorInsets(); int comboBorderSize = microLayout.getComboBorderSize(); int comboPopupBorderSize = microLayout.getComboPopupBorderSize(); int comboRendererGap = comboEditorInsets.left + comboBorderSize - comboPopupBorderSize; Object comboRendererBorder = new EmptyBorder(1, comboRendererGap, 1, comboRendererGap); Object comboTableEditorInsets = new Insets(0, 0, 0, 0); Object popupMenuSeparatorMargin = microLayout.getPopupMenuSeparatorMargin(); // Should be active. int treeFontSize = table.getFont("Tree.font").getSize(); Integer rowHeight = new Integer(treeFontSize + 6); Color controlColor = table.getColor("control"); Object disabledTextBackground = table.getColor("TextField.disabledBackground"); Object inactiveTextBackground = table.getColor("TextField.inactiveBackground"); Object comboBoxDisabledBackground = isVista && isXP ? table.getColor("ComboBox.background") : disabledTextBackground; Object menuBarBackground = isXP ? table.get("control") : table.get("menu"); Object menuSelectionBackground = isXP ? table.get("MenuItem.selectionBackground") : table.get("Menu.background"); Object menuSelectionForeground = isXP ? table.get("MenuItem.selectionForeground") : table.get("Menu.foreground"); Character passwordEchoChar = new Character(isXP ? '\u25CF' : '*'); Object[] defaults = { "Button.border", buttonBorder, "Button.margin", buttonMargin, // Sun's 14px margin is too wide // 1.4.2 uses a 2 pixel non-standard border that leads to bad // alignment in the typical case that the border is not painted "CheckBox.border", marginBorder, "CheckBox.margin", checkBoxMargin, "ComboBox.disabledBackground", comboBoxDisabledBackground, "ComboBox.editorBorder", marginBorder, "ComboBox.editorColumns", new Integer(5), "ComboBox.editorInsets", comboEditorInsets, // Added by JGoodies "ComboBox.tableEditorInsets", comboTableEditorInsets, "ComboBox.rendererBorder", comboRendererBorder, // Added by JGoodies "EditorPane.margin", wrappedTextInsets, // Begin 1.3 und 1.4.0 "Menu.border", menuBorder, // Fixed in 1.4.1 "Menu.borderPainted", Boolean.TRUE, "Menu.background", menuBarBackground, "Menu.selectionForeground", menuSelectionForeground, "Menu.selectionBackground", menuSelectionBackground, // End 1.3 und 1.4.0 "MenuBar.background", menuBarBackground, "MenuBar.border", menuBarSeparatorBorder, // 1.4.1 Separator wrong "MenuBar.emptyBorder", menuBarEmptyBorder, // Added by JGoodies "MenuBar.separatorBorder", menuBarSeparatorBorder, // Added by JGoodies "MenuBar.etchedBorder", menuBarEtchedBorder, // Added by JGoodies "MenuBar.headerBorder", menuBarHeaderBorder, // Added by JGoodies "FormattedTextField.disabledBackground", disabledTextBackground, // for readonly "FormattedTextField.inactiveBackground", inactiveTextBackground, // for readonly "FormattedTextField.margin", textInsets, // Poor in 1.6 "PasswordField.margin", textInsets, // Poor in 1.6 "PasswordField.echoChar", passwordEchoChar, "PopupMenu.border", WindowsBorders.getPopupMenuBorder(), "PopupMenu.noMarginBorder", WindowsBorders.getNoMarginPopupMenuBorder(), "PopupMenuSeparator.margin", popupMenuSeparatorMargin, "ScrollPane.etchedBorder", etchedBorder, // Added by JGoodies "Spinner.defaultEditorInsets", textInsets, // Added by JGoodies // 1.4.1 uses a 2 pixel non-standard border, that leads to bad // alignment in the typical case that the border is not painted "RadioButton.border", marginBorder, "RadioButton.margin", checkBoxMargin, "Spinner.border", table.get("TextField.border"), "Table.gridColor", controlColor, // 1.4.1 Bug; active "TextArea.margin", wrappedTextInsets, // 1.4.1 Bug "TextArea.disabledBackground", disabledTextBackground, "TextArea.inactiveBackground", inactiveTextBackground, "TextField.margin", textInsets, // 1.4.1 Bug "ToggleButton.margin", buttonMargin, // Sun's 14px margin is too wide "ToolBar.emptyBorder", toolBarEmptyBorder, // Added by JGoodies "ToolBar.separatorBorder", toolBarSeparatorBorder, // Added by JGoodies "ToolBar.etchedBorder", toolBarEtchedBorder, // Added by JGoodies "ToolBar.headerBorder", toolBarHeaderBorder, // Added by JGoodies "ToolBar.separatorSize", toolBarSeparatorSize, "ToolBar.margin", new InsetsUIResource(0, 10, 0, 0), "Tree.selectionBorderColor", controlColor, // 1.4.1 Bug; active "Tree.rowHeight", rowHeight, // 1.4.1 Bug }; table.putDefaults(defaults); } /** * Initializes component defaults required in classic mode only. */ private static void initComponentDefaultsClassic(UIDefaults table) { Object checkBoxIcon = new SimpleProxyLazyValue("com.jgoodies.looks.windows.WindowsLookAndFeel", "getCheckBoxIcon"); Object radioButtonIcon = new SimpleProxyLazyValue("com.jgoodies.looks.windows.WindowsLookAndFeel", "getRadioButtonIcon"); Border winInsetBorder = new BasicBorders.FieldBorder(table.getColor("controlShadow"), table.getColor("controlDkShadow"), table.getColor("controlHighlight"), table.getColor("controlLtHighlight")); Object[] defaults = { "CheckBox.checkColor", table.get("controlText"), // kind-of black "CheckBox.icon", checkBoxIcon, "RadioButton.checkColor", table.get("controlText"), // kind-of black "RadioButton.icon", radioButtonIcon, "Table.scrollPaneBorder", winInsetBorder, // 1.4.1 Bug }; table.putDefaults(defaults); } /** * Looks up the correct control font and sets it for all controls. */ private static void initFontDefaults(UIDefaults table) { FontPolicy fontChoicePolicy = getFontPolicy(); FontSet fontSet = fontChoicePolicy.getFontSet("Windows", table); initFontDefaults(table, fontSet); } private static void initMenuItemDefaults(UIDefaults table, MicroLayout microLayout) { Object menuMargin = microLayout.getMenuMargin(); Object menuItemMargin = microLayout.getMenuItemMargin(); Icon menuItemCheckIcon = new MinimumSizedIcon(); Object[] defaults = { "Menu.margin", menuMargin, // 1.4.1 Bug "MenuItem.borderPainted", Boolean.TRUE, "MenuItem.checkIcon", menuItemCheckIcon, // Aligns menu items "MenuItem.margin", menuItemMargin, // 1.4.1 Bug "CheckBoxMenuItem.margin", menuItemMargin, // 1.4.1 Bug "RadioButtonMenuItem.margin", menuItemMargin, // 1.4.1 Bug }; table.putDefaults(defaults); } /** * Sets Fonts in the given FontSet as defaults for all known * component types in the given UIDefaults table. * * @param table the UIDefaults table used to set fonts * @param fontSet describes the set of Fonts to be installed */ private static void initFontDefaults(UIDefaults table, FontSet fontSet) { Font controlFont = fontSet.getControlFont(); Font menuFont = fontSet.getMenuFont(); Font messageFont = fontSet.getMessageFont(); Font toolTipFont = fontSet.getSmallFont(); Font titleFont = fontSet.getTitleFont(); Font windowFont = fontSet.getWindowTitleFont(); Object[] defaults = { "Button.font", controlFont, "CheckBox.font", controlFont, "ColorChooser.font", controlFont, "ComboBox.font", controlFont, "EditorPane.font", controlFont, "FormattedTextField.font", controlFont, "Label.font", controlFont, "List.font", controlFont, "Panel.font", controlFont, "PasswordField.font", controlFont, "ProgressBar.font", controlFont, "RadioButton.font", controlFont, "ScrollPane.font", controlFont, "Spinner.font", controlFont, "TabbedPane.font", controlFont, "Table.font", controlFont, "TableHeader.font", controlFont, "TextArea.font", controlFont, "TextField.font", controlFont, "TextPane.font", controlFont, "ToolBar.font", controlFont, "ToggleButton.font", controlFont, "Tree.font", controlFont, "Viewport.font", controlFont, "InternalFrame.titleFont", windowFont, // controlBold "OptionPane.font", messageFont, "OptionPane.messageFont", messageFont, "OptionPane.buttonFont", messageFont, "TitledBorder.font", titleFont, "ToolTip.font", toolTipFont, "CheckBoxMenuItem.font", menuFont, "CheckBoxMenuItem.acceleratorFont", menuFont, // 1.3 only ? "Menu.font", menuFont, "Menu.acceleratorFont", menuFont, "MenuBar.font", menuFont, "MenuItem.font", menuFont, "MenuItem.acceleratorFont", menuFont, "PopupMenu.font", menuFont, "RadioButtonMenuItem.font", menuFont, "RadioButtonMenuItem.acceleratorFont", menuFont, // 1.3 only ? }; table.putDefaults(defaults); } // Getters for Proxy Access (Referred classes can stay package visible) *** public static Border getButtonBorder() { return WindowsBorders.getButtonBorder(); } public static Icon getCheckBoxIcon() { return WindowsIconFactory.getCheckBoxIcon(); } public static Icon getRadioButtonIcon() { return WindowsIconFactory.getRadioButtonIcon(); } // Helper Code ************************************************************ /** * Appends the key and value to the given source array and returns * a copy that has the two new elements at its end. * * @return an array with the key and value appended */ private static Object[] append(Object[] source, String key, Object value) { int length = source.length; Object[] destination = new Object[length + 2]; System.arraycopy(source, 0, destination, 0, length); destination[length] = key; destination[length + 1] = value; return destination; } // Helper Class *********************************************************** /** * This class provides an implementation of {@code LazyValue} that * can be used to delay loading of the Class for the instance to be created. * It also avoids creation of an anonymous inner class for the * {@code LazyValue} * subclass. Both of these improve performance at the time that a * a Look and Feel is loaded, at the cost of a slight performance * reduction the first time {@code createValue} is called * (since Reflection APIs are used). */ private static class SimpleProxyLazyValue implements UIDefaults.LazyValue { private final String className; private final String methodName; /** * Creates a {@code LazyValue} which will construct an instance * when asked. * * @param c a {@code String} specifying the classname of the class * containing a static method to be called for instance creation * @param m a {@code String} specifying the static * method to be called on class c */ public SimpleProxyLazyValue(String c, String m) { className = c; methodName = m; } /** * Creates the value retrieved from the {@code UIDefaults} table. * The object is created each time it is accessed. * * @param table a {@code UIDefaults} table * @return the created {@code Object} */ @Override public Object createValue(UIDefaults table) { Object instance = null; try { Class c; // We use a separate ClassLoader ClassLoader classLoader = table != null ? (ClassLoader) table.get("ClassLoader") : Thread.currentThread().getContextClassLoader(); if (classLoader == null) { classLoader = getClass().getClassLoader(); } c = Class.forName(className, true, classLoader); Method m = c.getMethod(methodName, (Class[]) null); instance = m.invoke(c, (Object[]) null); } catch (Throwable t) { LookUtils.log("Problem creating " + className + " with method " + methodName + t); } return instance; } } }