Package com.palantir.ptoss.cinch.swing

Source Code of com.palantir.ptoss.cinch.swing.Wiring

//   Copyright 2011 Palantir Technologies
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
package com.palantir.ptoss.cinch.swing;

import java.beans.IntrospectionException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.apache.log4j.Logger;

import com.google.common.collect.Lists;
import com.palantir.ptoss.cinch.core.BindableModel;
import com.palantir.ptoss.cinch.core.Binding;
import com.palantir.ptoss.cinch.core.BindingContext;
import com.palantir.ptoss.cinch.core.BindingException;
import com.palantir.ptoss.cinch.core.BindingWiring;
import com.palantir.ptoss.cinch.core.ModelUpdate;
import com.palantir.ptoss.cinch.core.ObjectFieldMethod;

/**
* A binding that will set the Visible state of the annotated component to the state of a model
* boolean. The component must have a "setVisible" method that takes a boolean.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface VisibleIf {
    /**
     * Enum to specify if normal or inverted comparisons should be used.
     */
    public enum Type { NORMAL, INVERTED };
    /**
     * The model boolean property to bind to.
     */
    String to();

    /**
     * Whether or not to invert the boolean.
     */
    Type type() default Type.NORMAL;

    /**
     * Inner utility class that performs the runtime wiring of all {@link VisibleIf} bindings.
     */
    public static class Wiring implements BindingWiring {
        private static final Logger logger = Logger.getLogger(VisibleIf.class);

        public Collection<Binding> wire(final BindingContext context) {
            final List<Field> actions = context.getAnnotatedFields(VisibleIf.class);
            final List<Binding> bindings = Lists.newArrayList();
            for (final Field field : actions) {
                final VisibleIf action = field.getAnnotation(VisibleIf.class);
                final String to = action.to();
                final boolean invert = (action.type() == Type.INVERTED);
                try {
                    bindings.addAll(wire(to, field, context, invert));
                } catch (final Exception e) {
                    throw new BindingException("could not wire up @VisibleIf on " + field.getName(), e);
                }
            }
            return bindings;
        }

        private static Collection<Binding> wire(final String to, final Field field, final BindingContext context, final boolean invert)
            throws SecurityException, NoSuchMethodException, IllegalArgumentException, IntrospectionException {
            final Method setVisibleMethod = field.getType().getMethod("setVisible", boolean.class);
            if (setVisibleMethod == null) {
                throw new BindingException("no setVisible call on VisibleIf field: " + field);
            }
            final Object setVisibleObject = context.getFieldObject(field, Object.class);
            final ObjectFieldMethod getter = context.findGetter(to);
            if (getter == null) {
                throw new BindingException("could not find bindable property: " + to);
            }
            if (getter.getMethod().getReturnType() != boolean.class) {
                throw new BindingException("VisibleIf binding must return boolean: " + to);
            }
            final Binding binding = new Binding() {
                public <T extends Enum<?> & ModelUpdate> void update(final T... changed) {
                    try {
                        getter.getMethod().setAccessible(true);
                        boolean visible = (Boolean)getter.getMethod().invoke(getter.getObject());
                        if (invert) {
                            visible = !visible;
                        }
                        setVisibleMethod.invoke(setVisibleObject, visible);
                    } catch (final Exception e) {
                        Wiring.logger.error("exception during VisibleIf binding", e);
                    }
                }
            };
            ((BindableModel)getter.getObject()).bind(binding);
            return Collections.singleton(binding);
        }
    }
}
TOP

Related Classes of com.palantir.ptoss.cinch.swing.Wiring

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.