org.dyno.visual.swing.base.WidgetProperty.java Source code

Java tutorial

Introduction

Here is the source code for org.dyno.visual.swing.base.WidgetProperty.java

Source

/************************************************************************************
 * Copyright (c) 2008 William Chen.                                                 *
 *                                                                                  *
 * All rights reserved. This program and the accompanying materials are made        *
 * available under the terms of the Eclipse Public License v1.0 which accompanies   *
 * this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html *
 *                                                                                  *
 * Use is subject to the terms of Eclipse Public License v1.0.                      *
 *                                                                                  *
 * Contributors:                                                                    * 
 *     William Chen - initial API and implementation.                               *
 ************************************************************************************/

package org.dyno.visual.swing.base;

import java.awt.Component;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;

import javax.swing.JMenu;
import javax.swing.JPopupMenu;
import javax.swing.UIManager;

import org.dyno.visual.swing.VisualSwingPlugin;
import org.dyno.visual.swing.plugin.spi.ICellEditorFactory;
import org.dyno.visual.swing.plugin.spi.ICodeGen;
import org.dyno.visual.swing.plugin.spi.ILabelProviderFactory;
import org.dyno.visual.swing.plugin.spi.ILookAndFeelAdapter;
import org.dyno.visual.swing.plugin.spi.IValueParser;
import org.dyno.visual.swing.plugin.spi.WidgetAdapter;
import org.dyno.visual.swing.undo.SetValueOperation;
import org.eclipse.core.commands.operations.IOperationHistory;
import org.eclipse.core.commands.operations.IUndoableOperation;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.views.properties.IPropertyDescriptor;

/**
 * 
 * WidgetProperty
 * 
 * @version 1.0.0, 2008-7-3
 * @author William Chen
 */
@SuppressWarnings("unchecked")
public class WidgetProperty extends PropertyAdapter {

    protected Object lastValue;

    protected String category;
    protected ICellEditorFactory editorFactory;
    protected ILabelProviderFactory labelFactory;
    protected boolean editable;
    protected PropertyDescriptor propertyDescriptor;
    protected String helpContextId;
    protected String description;
    protected String propertyName;
    protected String displayName;
    protected String[] filters;

    protected Class beanClass;
    protected boolean gencode;
    protected IValueParser parser;
    protected Object default_value;

    public WidgetProperty(String name, Class beanClass, ILabelProviderFactory label, ICellEditorFactory editor,
            Object defaultValue) {
        this.beanClass = beanClass;
        this.propertyName = name;
        try {
            propertyDescriptor = new PropertyDescriptor(propertyName, beanClass);
        } catch (IntrospectionException e) {
            VisualSwingPlugin.getLogger().error(e);
        }
        gencode = true;
        displayName = name + TEXT_TRAILING;
        editable = true;
        labelFactory = label;
        editorFactory = editor;
        this.default_value = defaultValue;
    }

    public WidgetProperty() {

    }

    public PropertyDescriptor getPropertyDescriptor() {
        return propertyDescriptor;
    }

    public WidgetProperty(String name, Class beanClass, Object defaultValue) {
        this.beanClass = beanClass;
        this.propertyName = name;
        try {
            propertyDescriptor = new PropertyDescriptor(propertyName, beanClass);
        } catch (IntrospectionException e) {
            VisualSwingPlugin.getLogger().error(e);
        }
        gencode = true;
        displayName = name + TEXT_TRAILING;
        editable = true;
        Class<?> type = propertyDescriptor.getPropertyType();
        TypeAdapter ta = ExtensionRegistry.getTypeAdapter(type);
        if (ta != null) {
            labelFactory = ta.getRenderer();
            editorFactory = ta.getEditor();
        }
        this.default_value = defaultValue;
    }

    public WidgetProperty(IConfigurationElement config, Class beanClass) {
        init(config, beanClass);
    }

    @Override
    public void init(IConfigurationElement config, Class beanClass) {
        this.beanClass = beanClass;
        propertyName = config.getAttribute("name");
        if (propertyDescriptor == null) {
            try {
                propertyDescriptor = new PropertyDescriptor(propertyName, beanClass);
            } catch (IntrospectionException e) {
                VisualSwingPlugin.getLogger().error(e);
            }
        }
        String sGencode = config.getAttribute("gencode");
        if (sGencode == null || sGencode.trim().length() == 0)
            gencode = true;
        else
            gencode = sGencode.toLowerCase().equals("true");
        displayName = config.getAttribute("displayName");
        if (displayName == null || displayName.trim().length() == 0)
            displayName = propertyName;
        displayName = displayName + TEXT_TRAILING;
        String sEditable = config.getAttribute("editable");
        editable = sEditable == null || sEditable.trim().length() == 0 || sEditable.toLowerCase().equals("true");
        String sLabel = config.getAttribute("renderer");
        Class<?> type = propertyDescriptor.getPropertyType();
        TypeAdapter ta = ExtensionRegistry.getTypeAdapter(type);
        if (sLabel != null && sLabel.trim().length() > 0) {
            createLabelProviderFactory(config);
        } else if (ta != null) {
            labelFactory = ta.getRenderer();
        }
        String sEditor = config.getAttribute("editor");
        if (sEditor != null && sEditor.trim().length() > 0) {
            createEditorProviderFactory(config);
        } else if (ta != null) {
            editorFactory = ta.getEditor();
        }
        String sParser = config.getAttribute("parser");
        if (sParser != null && sParser.trim().length() > 0) {
            try {
                parser = (IValueParser) config.createExecutableExtension("parser");
            } catch (CoreException e) {
                VisualSwingPlugin.getLogger().error(e);
            }
        } else if (ta != null) {
            parser = ta.getParser();
        }
        helpContextId = config.getAttribute("help-context-id");
        if (helpContextId != null && helpContextId.trim().length() == 0)
            helpContextId = null;
        IConfigurationElement[] children = config.getChildren("description");
        if (children != null && children.length > 0) {
            description = children[0].getValue();
        }
        children = config.getChildren("filter");
        if (children != null && children.length > 0) {
            filters = new String[children.length];
            for (int i = 0; i < children.length; i++) {
                filters[i] = children[i].getValue();
            }
        }
    }

    private void createEditorProviderFactory(IConfigurationElement config) {
        try {
            editorFactory = (ICellEditorFactory) config.createExecutableExtension("editor");
        } catch (CoreException e) {
            VisualSwingPlugin.getLogger().error(e);
        }
    }

    private void createLabelProviderFactory(IConfigurationElement config) {
        try {
            labelFactory = (ILabelProviderFactory) config.createExecutableExtension("renderer");
        } catch (CoreException e) {
            VisualSwingPlugin.getLogger().error(e);
        }
    }

    public void setCategory(String category) {
        this.category = category;
    }

    private IStructuredSelection bean;

    public void setBean(IStructuredSelection bean) {
        this.bean = bean;
    }

    @Override
    public Object getPropertyValue(IStructuredSelection bean) {
        assert !bean.isEmpty();
        try {
            Object value = getFieldValue(bean.getFirstElement());
            if (isEditable()) {
                if (editorFactory != null)
                    value = editorFactory.encodeValue(value);
                else {
                    Class type = lastValue.getClass();
                    TypeAdapter ta = ExtensionRegistry.getTypeAdapter(type);
                    value = ta.getEditor().decodeValue(value);
                }
            }
            lastValue = value;
            return value;
        } catch (Exception e) {
            VisualSwingPlugin.getLogger().error(e);
        }
        lastValue = null;
        return null;
    }

    @Override
    public boolean isPropertyResettable(IStructuredSelection bean) {
        return true;
    }

    @Override
    protected Object getDefaultValue(Object b, String lnfClassname) {
        if (b instanceof Component && Component.class.isAssignableFrom(beanClass)) {
            WidgetAdapter wa = WidgetAdapter.getWidgetAdapter((Component) b);
            if (wa.isRoot() && b.getClass().getSuperclass() == beanClass
                    || !wa.isRoot() && b.getClass() == beanClass) {
                ILookAndFeelAdapter adapter = null;
                if (lnfClassname != null)
                    adapter = ExtensionRegistry.getLnfAdapter(lnfClassname);
                else
                    adapter = ExtensionRegistry.getLnfAdapter(UIManager.getCrossPlatformLookAndFeelClassName());
                if (adapter != null)
                    default_value = adapter.getDefaultValue(beanClass, propertyName);
            } else {
                Class compClass;
                if (wa.isRoot() && b.getClass() == beanClass) {
                    compClass = b.getClass();
                } else if (wa.isRoot() && b.getClass().getSuperclass() != beanClass)
                    compClass = b.getClass().getSuperclass();
                else if (!wa.isRoot() && b.getClass() != beanClass && b.getClass().getSuperclass() == beanClass) {
                    if (b.getClass().getSuperclass() == JMenu.class
                            || b.getClass().getSuperclass() == JPopupMenu.class) {
                        compClass = b.getClass().getSuperclass();
                    } else
                        compClass = b.getClass();
                } else if (wa.isRoot() && b.getClass() != beanClass && b.getClass().getSuperclass() != beanClass)
                    compClass = b.getClass().getSuperclass();
                else if (!wa.isRoot() && b.getClass() != beanClass && b.getClass().getSuperclass() != beanClass)
                    compClass = b.getClass();
                else
                    compClass = null;
                if (compClass != null) {
                    Object obj = DEFAULT_OBJECTS.get(compClass);
                    if (obj == null) {
                        try {
                            obj = compClass.newInstance();
                        } catch (Exception e) {
                            VisualSwingPlugin.getLogger().error(e);
                            obj = null;
                        }
                        DEFAULT_OBJECTS.put(compClass, obj);
                    }
                    default_value = getFieldValue(obj);
                }
            }
        }
        return default_value;
    }

    @Override
    public void setPropertyValue(IStructuredSelection bean, Object value) {
        assert !bean.isEmpty();
        if (isEditable()) {
            try {
                if (editorFactory != null)
                    value = editorFactory.decodeValue(value);
                else {
                    Class type = lastValue.getClass();
                    TypeAdapter ta = ExtensionRegistry.getTypeAdapter(type);
                    value = ta.getEditor().decodeValue(value);
                }
                for (Object b : bean.toArray()) {
                    IUndoableOperation operation = new SetValueOperation(b, this, value);
                    IOperationHistory operationHistory = PlatformUI.getWorkbench().getOperationSupport()
                            .getOperationHistory();
                    if (b instanceof Component) {
                        Component jcomp = (Component) b;
                        WidgetAdapter adapter = WidgetAdapter.getWidgetAdapter(jcomp);
                        if (adapter != null) {
                            operation.addContext(adapter.getUndoContext());
                        }
                    }
                    operationHistory.execute(operation, null, null);
                }
            } catch (Exception e) {
                VisualSwingPlugin.getLogger().error(e);
            }
        }
    }

    private boolean isEditable() {
        if (editorFactory == null) {
            if (lastValue == null)
                return false;
            else {
                Class type = lastValue.getClass();
                TypeAdapter ta = ExtensionRegistry.getTypeAdapter(type);
                if (ta != null && ta.getEditor() != null)
                    return true;
                else
                    return false;
            }
        }
        if (editable) {
            Method setMethod = propertyDescriptor.getWriteMethod();
            if (setMethod == null) {
                return false;
            } else {
                return true;
            }
        } else
            return false;
    }

    @Override
    public CellEditor createPropertyEditor(Composite parent) {
        if (isEditable()) {
            if (editorFactory != null)
                return editorFactory.createPropertyEditor(bean, parent);
            else {
                Class type = lastValue.getClass();
                TypeAdapter ta = ExtensionRegistry.getTypeAdapter(type);
                return ta.getEditor().createPropertyEditor(bean, parent);
            }
        } else {
            return null;
        }
    }

    @Override
    public String getCategory() {
        return category;
    }

    @Override
    public String getDescription() {
        return description;
    }

    @Override
    public String getDisplayName() {
        return displayName;
    }

    @Override
    public String[] getFilterFlags() {
        return filters;
    }

    public void setFilterFlags(String[] filters) {
        this.filters = filters;
    }

    @Override
    public Object getHelpContextIds() {
        return helpContextId;
    }

    @Override
    public Object getId() {
        return propertyName;
    }

    @Override
    public ILabelProvider getLabelProvider() {
        return labelFactory == null ? null : labelFactory.getLabelProvider();
    }

    @Override
    public boolean isCompatibleWith(IPropertyDescriptor anotherProperty) {
        return false;
    }

    @Override
    public boolean cloneProperty(Object bean, Component clone) {
        Object value = getFieldValue(bean);
        if (value != null) {
            TypeAdapter adapter = ExtensionRegistry.getTypeAdapter(value.getClass());
            if (adapter != null && adapter.getCloner() != null) {
                value = adapter.getCloner().clone(value);
            }
        }
        setFieldValue(clone, value);
        return true;
    }

    @Override
    public boolean isGencode() {
        return gencode;
    }

    @Override
    public boolean isEdited(WidgetAdapter adapter) {
        Map<String, Boolean> editedMap = adapter.getEditingMap();
        Boolean bool = editedMap.get(propertyName);
        return bool == null ? false : bool.booleanValue();
    }

    @Override
    public IValueParser getValueParser() {
        return parser;
    }

    @Override
    public void setFieldValue(Object bean, Object newValue) {
        try {
            Method writeMethod = propertyDescriptor.getWriteMethod();
            if (writeMethod != null) {
                writeMethod.invoke(bean, newValue);
            } else {
                Class clazz = bean.getClass();
                Field field = clazz.getField(propertyName);
                field.setAccessible(true);
                field.set(bean, newValue);
            }
        } catch (Exception e) {
            VisualSwingPlugin.getLogger().error(e);
        }
    }

    @Override
    public Object getFieldValue(Object bean) {
        try {
            if (propertyDescriptor.getReadMethod() != null) {
                return propertyDescriptor.getReadMethod().invoke(bean);
            } else {
                Class clazz = bean.getClass();
                Field field = clazz.getField(propertyName);
                field.setAccessible(true);
                return field.get(bean);
            }
        } catch (Exception e) {
            VisualSwingPlugin.getLogger().error(e);
            return null;
        }
    }

    @Override
    public Class getPropertyType() {
        return propertyDescriptor.getPropertyType();
    }

    @Override
    protected Class getObjectClass() {
        return getClass();
    }

    public ICodeGen getCodeGenerator() {
        Class typeClass = propertyDescriptor.getPropertyType();
        TypeAdapter typeAdapter = ExtensionRegistry.getTypeAdapter(typeClass);
        if (editorFactory != null && editorFactory instanceof ItemProviderCellEditorFactory) {
            return editorFactory;
        } else if (typeAdapter != null) {
            return typeAdapter.getCodegen();
        } else {
            return editorFactory;
        }
    }

    @Override
    public String getSetName() {
        return propertyDescriptor.getWriteMethod().getName();
    }
}