de.unentscheidbar.validation.swing.trigger.ChangeTrigger.java Source code

Java tutorial

Introduction

Here is the source code for de.unentscheidbar.validation.swing.trigger.ChangeTrigger.java

Source

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. Portions Copyrighted 2012 Daniel
 * Huss.
 *
 * The contents of this file are subject to the terms of either the GNU General Public License
 * Version 2 only ("GPL") or the Common Development and Distribution License("CDDL") (collectively,
 * the "License"). You may not use this file except in compliance with the License. You can obtain a
 * copy of the License at http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP.
 * See the License for the specific language governing permissions and limitations under the
 * License. When distributing the software, include this License Header Notice in each file and
 * include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this particular file
 * as subject to the "Classpath" exception as provided by Sun in the GPL Version 2 section of the
 * License file that accompanied this code. If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * Contributor(s):
 *
 * The Original Software is NetBeans. The Initial Developer of the Original Software is Sun
 * Microsystems, Inc. Portions Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * If you wish your version of this file to be governed by only the CDDL or only the GPL Version 2,
 * indicate your decision by adding "[Contributor] elects to include this software in this
 * distribution under the [CDDL or GPL Version 2] license." If you do not indicate a single choice
 * of license, a recipient has the option to distribute your version of this file under either the
 * CDDL, the GPL Version 2 or to extend the choice of license to its licensees as provided above.
 * However, if you add GPL Version 2 code and therefore, elected the GPL Version 2 license, then the
 * option applies only if the new code is made subject to such option by the copyright holder.
 */
package de.unentscheidbar.validation.swing.trigger;

import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Arrays;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;

import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JRadioButton;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.JTable;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;

import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.tuple.Pair;

import de.unentscheidbar.validation.internal.Methods;
import de.unentscheidbar.validation.internal.Methods.MethodChain;

final class ChangeTrigger extends AbstractCoalescingTrigger<JComponent> {

    static final class ComponentChangeListener extends ComponentListener<JComponent> implements ChangeListener {

        ComponentChangeListener(AbstractCoalescingTrigger<JComponent> trigger, JComponent component) {

            super(trigger, component);
        }

        @Override
        public void stateChanged(ChangeEvent e) {

            fire();
        }

    }

    static final class ItemChangeListener extends ComponentListener<JComponent> implements ItemListener {

        ItemChangeListener(AbstractCoalescingTrigger<JComponent> trigger, JComponent component) {

            super(trigger, component);
        }

        @Override
        public void itemStateChanged(ItemEvent e) {

            if (e.getStateChange() == ItemEvent.SELECTED) {
                fire();
            }
        }

    }

    static final class TableChangeListener extends ComponentListener<JComponent> implements TableModelListener {

        TableChangeListener(AbstractCoalescingTrigger<JComponent> trigger, JComponent component) {

            super(trigger, component);
        }

        @Override
        public void tableChanged(TableModelEvent e) {

            fire();
        }

    }

    public static final Trigger<JComponent> INSTANCE = new ChangeTrigger();

    private static final Pair<String, Class<?>> ADD_METHOD = Pair.<String, Class<?>>of("addChangeListener",
            ChangeListener.class);

    private static final String[] PROPERTY_HIERARCHY = { "model" };

    private static final Pair<String, Class<?>> REMOVE_METHOD = Pair.<String, Class<?>>of("removeChangeListener",
            ChangeListener.class);

    public static boolean supports(Object classOrInstance) {

        if (classOrInstance instanceof Class<?>) {
            return supportsClass((Class<?>) classOrInstance);
        } else {
            return supportsInstance(classOrInstance);
        }
    }

    private static MethodChain getAddMethod(Class<?> clazz) {

        return Methods.findMethod(clazz, ADD_METHOD, PROPERTY_HIERARCHY);
    }

    private static MethodChain getRemoveMethod(Class<?> clazz) {

        return Methods.findMethod(clazz, REMOVE_METHOD, PROPERTY_HIERARCHY);
    }

    private static boolean supportsClass(Class<?> clazz) {

        List<Class<?>> supportedClasses = Arrays.<Class<?>>asList(JComboBox.class, JRadioButton.class,
                JCheckBox.class, JColorChooser.class, JSlider.class, JSpinner.class, JTable.class);

        for (Class<?> supportedClass : supportedClasses) {
            if (ClassUtils.isAssignable(clazz, supportedClass))
                return true;
        }
        return getAddMethod(clazz) != null && getRemoveMethod(clazz) != null;
    }

    private static boolean supportsInstance(Object o) {

        if (o == null)
            return false;
        else
            return o instanceof JComboBox<?> || o instanceof JRadioButton || o instanceof JCheckBox
                    || o instanceof JColorChooser || o instanceof JSlider || o instanceof JSpinner
                    || o instanceof JTable || supportsClass(o.getClass());
    }

    private final Map<Object, Object> listeners = new IdentityHashMap<>();

    @Override
    public void registerSelf(JComponent component) {

        if (!listeners.containsKey(component)) {
            listeners.put(component, doRegister(component));
        }
    }

    @Override
    public void unregisterSelf(JComponent component) {

        Object listener = listeners.get(component);
        if (listener != null) {
            doUnregister(component, listener);
            listeners.remove(component);
        }
    }

    private Object doRegister(JComponent c) {

        ComponentChangeListener l = new ComponentChangeListener(this, c);
        Object result = l;
        if (c instanceof JComboBox<?>) {
            ItemListener il = new ItemChangeListener(this, c);
            result = il;
            ((JComboBox<?>) c).addItemListener(il);
        } else if (c instanceof JRadioButton) {
            ItemListener il = new ItemChangeListener(this, c);
            result = il;
            ((JRadioButton) c).addItemListener(il);
        } else if (c instanceof JCheckBox) {
            ItemListener il = new ItemChangeListener(this, c);
            result = il;
            ((JCheckBox) c).addItemListener(il);
        } else if (c instanceof JColorChooser) {
            ((JColorChooser) c).getSelectionModel().addChangeListener(l);
        } else if (c instanceof JSlider) {
            ((JSlider) c).addChangeListener(l);
        } else if (c instanceof JSpinner) {
            ((JSpinner) c).addChangeListener(l);
        } else if (c instanceof JTable) {
            TableChangeListener tl = new TableChangeListener(this, c);
            result = tl;
            ((JTable) c).getModel().addTableModelListener(tl);
        } else {
            MethodChain addChangeListenerMethod = getAddMethod(c.getClass());
            if (addChangeListenerMethod == null)
                throw new UnsupportedClassException(c);
            addChangeListenerMethod.invokeQuietly(c, l);
        }
        return result;
    }

    private void doUnregister(JComponent c, Object l) {

        if (c instanceof JComboBox<?>) {
            ((JComboBox<?>) c).removeItemListener((ItemListener) l);
        } else if (c instanceof JColorChooser) {
            ((JColorChooser) c).getSelectionModel().removeChangeListener((ChangeListener) l);
        } else if (c instanceof JSlider) {
            ((JSlider) c).addChangeListener((ChangeListener) l);
        } else if (c instanceof JSpinner) {
            ((JSpinner) c).addChangeListener((ChangeListener) l);
        } else if (c instanceof JTable) {
            ((JTable) c).getModel().addTableModelListener((TableModelListener) l);
        } else {
            MethodChain removeChangeListenerMethod = getRemoveMethod(c.getClass());
            if (removeChangeListenerMethod == null)
                throw new UnsupportedClassException(c);
            removeChangeListenerMethod.invokeQuietly(c, (ChangeListener) l);
        }
    }
}