All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jdesktop.swingx.BeanInfoSupport Maven / Gradle / Ivy

Go to download

Contains extensions to the Swing GUI toolkit, including new and enhanced components that provide functionality commonly required by rich client applications.

The newest version!
/*
 * $Id: BeanInfoSupport.java 3471 2009-08-27 13:10:39Z kleopatra $
 *
 * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
 * Santa Clara, California 95054, U.S.A. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
package org.jdesktop.swingx;

import java.awt.Image;
import java.beans.BeanDescriptor;
import java.beans.BeanInfo;
import java.beans.EventSetDescriptor;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.beans.SimpleBeanInfo;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.ImageIcon;

/**
 * Useful baseclass for BeanInfos. With this class, normal introspection occurs
 * and then you are given the opportunity to reconfigure portions of the
 * bean info in the initialize method.
 *
 * @author rbair, Jan Stola
 */
public abstract class BeanInfoSupport extends SimpleBeanInfo {
    private static Logger LOG = Logger.getLogger(BeanInfoSupport.class.getName());
    
    /**
     * Indicates whether I am introspecting state for the give class. This
     * helps prevent infinite loops
     */
    private static Map, Boolean> introspectingState = new HashMap, Boolean>();
    /**
     * The class of the bean that this BeanInfoSupport is for
     */
    private Class beanClass;
    
    /**
     * @see BeanInfo
     */
    private int defaultPropertyIndex = -1;
    /**
     * @see BeanInfo
     */
    private int defaultEventIndex = -1;
    /**
     * The 16x16 color icon
     */
    private Image iconColor16 = null;
    /**
     * The 32x32 color icon
     */
    private Image iconColor32 = null;
    /**
     * The 16x16 monochrome icon
     */
    private Image iconMono16 = null;
    /**
     * The 32x32 monochrome icon
     */
    private Image iconMono32 = null;
    /**
     * A reference to the icon. This String must be of a form that
     * ImageIO can use to locate and load the icon image
     */
    private String iconNameC16 = null;
    /**
     * A reference to the icon. This String must be of a form that
     * ImageIO can use to locate and load the icon image
     */
    private String iconNameC32 = null;
    /**
     * A reference to the icon. This String must be of a form that
     * ImageIO can use to locate and load the icon image
     */
    private String iconNameM16 = null;
    /**
     * A reference to the icon. This String must be of a form that
     * ImageIO can use to locate and load the icon image
     */
    private String iconNameM32 = null;
    
    private BeanDescriptor beanDescriptor;
    
    private Map properties = new TreeMap();
    private Map events = new TreeMap();
    private Map methods = new TreeMap();

    /**
     * Creates a new instance of BeanInfoSupport.
     * 
     * @param beanClass class of the bean.
     */
    public BeanInfoSupport(Class beanClass) {
        this.beanClass = beanClass;
        if (!isIntrospecting()) {
            introspectingState.put(beanClass, Boolean.TRUE);
            try {
                Class superClass = beanClass.getSuperclass();
                while (superClass != null) {
                    Introspector.flushFromCaches(superClass);
                    superClass = superClass.getSuperclass();
                }
                BeanInfo info = Introspector.getBeanInfo(beanClass);
                beanDescriptor = info.getBeanDescriptor();
                if (beanDescriptor != null) {
                    Class customizerClass = getCustomizerClass();
                    beanDescriptor = new BeanDescriptor(beanDescriptor.getBeanClass(),
                            customizerClass == null ? beanDescriptor.getCustomizerClass()
                            : customizerClass);
                } else {
                    beanDescriptor = new BeanDescriptor(beanClass, getCustomizerClass());
                }
                for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
                    properties.put(pd.getName(), pd);
                }
                for (EventSetDescriptor esd : info.getEventSetDescriptors()) {
                    events.put(esd.getName(), esd);
                }
                for (MethodDescriptor md : info.getMethodDescriptors()) {
                    methods.put(md.getName(), md);
                }
                
                defaultPropertyIndex = info.getDefaultPropertyIndex();
                defaultEventIndex = info.getDefaultEventIndex();
                                
                iconColor16 = loadStandardImage(info, BeanInfo.ICON_COLOR_16x16);
                iconColor32 = loadStandardImage(info, BeanInfo.ICON_COLOR_32x32);
                iconMono16 = loadStandardImage(info, BeanInfo.ICON_MONO_16x16);
                iconMono32 = loadStandardImage(info, BeanInfo.ICON_MONO_32x32);
            } catch (Exception e) {
                e.printStackTrace();
            }
            introspectingState.put(beanClass, Boolean.FALSE);
            initialize();
        }
    }
    
    private boolean isIntrospecting() {
        Boolean b = introspectingState.get(beanClass);
        return b == null ? false : b.booleanValue();
    }

    /**
     * attempts to load a png icon from the
     * resource directory beneath beaninfo, named like:
     *   JXTaskPaneContainer16.png
     *   JXTaskPaneContainer16-mono.png
     *   JXTaskPaneContainer32.png
     *   JXTaskPaneContainer32-mono.png
     * 
     * if any of the icons is missing, an attempt is made to
     * get an icon via introspection. If that fails, the icon
     * will be set to placeholder16.png or one of the derivitives
     */
    private Image loadStandardImage(BeanInfo info, int size) {
        String s = "";
        switch (size) {
            case BeanInfo.ICON_COLOR_16x16: s = "16"; break;
            case BeanInfo.ICON_COLOR_32x32: s = "32"; break;
            case BeanInfo.ICON_MONO_16x16: s = "16-mono"; break;
            case BeanInfo.ICON_MONO_32x32: s = "32-mono"; break;
        }
        String iconName = beanClass.getSimpleName() + s + ".png";
        
        Image image = null;
        try {
            image = loadImage("resources/" + iconName);
        } catch (Exception e) {
            LOG.info("No icon named " + iconName + " was found");
        }
        
        return image;
    }
    
    @Override
    public Image loadImage(final String resourceName) {
        URL url = getClass().getResource(resourceName);
        return (url == null) ? null : new ImageIcon(url).getImage();
    }

    /**
     * Called by the constructor during the proper time so that subclasses
     * can override the settings/values for the various beaninfo properties.
     * For example, you could call setDisplayName("Foo Name", "foo") to change
     * the foo properties display name
     */
    protected abstract void initialize();

    /**
     * Override this method if you want to return a custom customizer class
     * for the bean
     * 
     * @return null.
     */
    protected Class getCustomizerClass() {
        return null;
    }
    
    //------------------------------------ Methods for mutating the BeanInfo    
    /**
     * Specify the name/url/path to the small 16x16 color icon
     * 
     * @param name name of the icon.
     */
    protected void setSmallColorIconName(String name) {
        iconNameC16 = name;
    }
    
    /**
     * Specify the name/url/path to the 32x32 color icon
     * 
     * @param name name of the icon.
     */
    protected void setColorIconName(String name) {
        iconNameC32 = name;
    }

    /**
     * Specify the name/url/path to the small 16x16 monochrome icon
     * 
     * @param name name of the icon.
     */
    protected void setSmallMonoIconName(String name) {
        iconNameM16 = name;
    }

    /**
     * Specify the name/url/path to the 32x32 monochrome icon
     * 
     * @param name name of the icon.
     */
    protected void setMonoIconName(String name) {
        iconNameM32 = name;
    }
    
    /**
     * Changes the display name of the given named property. Property names
     * are always listed last to allow for varargs
     * 
     * @param displayName display name of the property.
     * @param propertyName name of the property.
     */
    protected void setDisplayName(String displayName, String propertyName) {
        PropertyDescriptor pd = properties.get(propertyName);
        if (pd != null) {
            pd.setDisplayName(displayName);
        } else {
            LOG.log(Level.WARNING, "Failed to set display name for property '" +
                    propertyName + "'. No such property was found");
        }
    }
    
    /**
     * Sets the given named properties to be "hidden".
     * 
     * @param hidden determines whether the properties should be marked as hidden or not.
     * @param propertyNames name of properties.
     * @see PropertyDescriptor
     */
    protected void setHidden(boolean hidden, String... propertyNames) {
        for (String propertyName : propertyNames) {
            PropertyDescriptor pd = properties.get(propertyName);
            if (pd != null) {
                pd.setHidden(hidden);
            } else {
                LOG.log(Level.WARNING, "Failed to set hidden attribute for property '" +
                        propertyName + "'. No such property was found");
            }
        }
    }
    
    protected void setExpert(boolean expert, String... propertyNames) {
        for (String propertyName : propertyNames) {
            PropertyDescriptor pd = properties.get(propertyName);
            if (pd != null) {
                pd.setExpert(expert);
            } else {
                LOG.log(Level.WARNING, "Failed to set expert attribute for property '" +
                        propertyName + "'. No such property was found");
            }
        }
    }
    
    protected void setPreferred(boolean preferred, String... propertyNames) {
        for (String propertyName : propertyNames) {
            PropertyDescriptor pd = properties.get(propertyName);
            if (pd != null) {
                pd.setPreferred(preferred);
            } else {
                LOG.log(Level.WARNING, "Failed to set preferred attribute for property '" +
                        propertyName + "'. No such property was found");
            }
        }
    }
    
    protected void setBound(boolean bound, String... propertyNames) {
        for (String propertyName : propertyNames) {
            PropertyDescriptor pd = properties.get(propertyName);
            if (pd != null) {
                pd.setBound(bound);
            } else {
                LOG.log(Level.WARNING, "Failed to set bound attribute for property '" +
                        propertyName + "'. No such property was found");
            }
        }
    }
    
    protected void setConstrained(boolean constrained, String... propertyNames) {
        for (String propertyName : propertyNames) {
            PropertyDescriptor pd = properties.get(propertyName);
            if (pd != null) {
                pd.setConstrained(constrained);
            } else {
                LOG.log(Level.WARNING, "Failed to set constrained attribute for property '" +
                        propertyName + "'. No such property was found");
            }
        }
    }
    
    protected void setCategory(String categoryName, String... propertyNames) {
        for (String propertyName : propertyNames) {
            PropertyDescriptor pd = properties.get(propertyName);
            if (pd != null) {
                pd.setValue("category", categoryName);
            } else {
                LOG.log(Level.WARNING, "Failed to set category for property '" +
                        propertyName + "'. No such property was found");
            }
        }
    }
    
    protected void setPropertyEditor(Class editorClass, String... propertyNames) {
        for (String propertyName : propertyNames) {
            PropertyDescriptor pd = properties.get(propertyName);
            if (pd != null) {
                pd.setPropertyEditorClass(editorClass);
            } else {
                LOG.log(Level.WARNING, "Failed to set property editor for property '" +
                        propertyName + "'. No such property was found");
            }
        }
    }
    
    protected void setEnumerationValues(EnumerationValue[] values, String... propertyNames) {
        if (values == null) {
            return;
        }
        
        Object[] enumValues = new Object[values.length * 3];
        int index = 0;
        for (EnumerationValue ev : values) {
            enumValues[index++] = ev.getName();
            enumValues[index++] = ev.getValue();
            enumValues[index++] = ev.getJavaInitializationString();
        }
        
        for (String propertyName : propertyNames) {
            PropertyDescriptor pd = properties.get(propertyName);
            if (pd != null) {
                pd.setValue("enumerationValues", enumValues);
            } else {
                LOG.log(Level.WARNING, "Failed to set enumeration values for property '" +
                        propertyName + "'. No such property was found");
            }
        }
    }
    
    //----------------------------------------------------- BeanInfo methods
    /**
     * Gets the bean's BeanDescriptors.
     *
     * @return BeanDescriptor describing the editable
     * properties of this bean.  May return null if the
     * information should be obtained by automatic analysis.
     */
    @Override
    public BeanDescriptor getBeanDescriptor() {
        return isIntrospecting() ? null : beanDescriptor;
    }
    
    /**
     * Gets the bean's PropertyDescriptors.
     *
     * @return An array of PropertyDescriptors describing the editable
     * properties supported by this bean.  May return null if the
     * information should be obtained by automatic analysis.
     * 

* If a property is indexed, then its entry in the result array will * belong to the IndexedPropertyDescriptor subclass of PropertyDescriptor. * A client of getPropertyDescriptors can use "instanceof" to check * if a given PropertyDescriptor is an IndexedPropertyDescriptor. */ @Override public PropertyDescriptor[] getPropertyDescriptors() { return isIntrospecting() ? null : properties.values().toArray(new PropertyDescriptor[0]); } /** * Gets the bean's EventSetDescriptors. * * @return An array of EventSetDescriptors describing the kinds of * events fired by this bean. May return null if the information * should be obtained by automatic analysis. */ @Override public EventSetDescriptor[] getEventSetDescriptors() { return isIntrospecting() ? null : events.values().toArray(new EventSetDescriptor[0]); } /** * Gets the bean's MethodDescriptors. * * @return An array of MethodDescriptors describing the methods * implemented by this bean. May return null if the information * should be obtained by automatic analysis. */ @Override public MethodDescriptor[] getMethodDescriptors() { return isIntrospecting() ? null : methods.values().toArray(new MethodDescriptor[0]); } /** * A bean may have a "default" property that is the property that will * mostly commonly be initially chosen for update by human's who are * customizing the bean. * @return Index of default property in the PropertyDescriptor array * returned by getPropertyDescriptors. *

Returns -1 if there is no default property. */ @Override public int getDefaultPropertyIndex() { return isIntrospecting() ? -1 : defaultPropertyIndex; } /** * A bean may have a "default" event that is the event that will * mostly commonly be used by human's when using the bean. * @return Index of default event in the EventSetDescriptor array * returned by getEventSetDescriptors. *

Returns -1 if there is no default event. */ @Override public int getDefaultEventIndex() { return isIntrospecting() ? -1 : defaultEventIndex; } /** * This method returns an image object that can be used to * represent the bean in toolboxes, toolbars, etc. Icon images * will typically be GIFs, but may in future include other formats. *

* Beans aren't required to provide icons and may return null from * this method. *

* There are four possible flavors of icons (16x16 color, * 32x32 color, 16x16 mono, 32x32 mono). If a bean choses to only * support a single icon we recommend supporting 16x16 color. *

* We recommend that icons have a "transparent" background * so they can be rendered onto an existing background. * * @param iconKind The kind of icon requested. This should be * one of the constant values ICON_COLOR_16x16, ICON_COLOR_32x32, * ICON_MONO_16x16, or ICON_MONO_32x32. * @return An image object representing the requested icon. May * return null if no suitable icon is available. */ @Override public java.awt.Image getIcon(int iconKind) { switch ( iconKind ) { case ICON_COLOR_16x16: return getImage(iconNameC16, iconColor16); case ICON_COLOR_32x32: return getImage(iconNameC32, iconColor32); case ICON_MONO_16x16: return getImage(iconNameM16, iconMono16); case ICON_MONO_32x32: return getImage(iconNameM32, iconMono32); default: return null; } } private java.awt.Image getImage(String name, java.awt.Image img) { if (img == null) { if (name != null) { img = loadImage(name); } } return img; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy