Could we not put this functionality in BeanDictionary itself?

On Oct 26, 2009, at 9:48 AM, [email protected] wrote:

Author: tvolkert
Date: Mon Oct 26 13:48:09 2009
New Revision: 829797

URL: http://svn.apache.org/viewvc?rev=829797&view=rev
Log:
Added BeanMonitor, changed EventLogger tool to use it, hooked up events to component inspector tool

Added:
incubator/pivot/trunk/core/src/org/apache/pivot/beans/ BeanMonitor.java incubator/pivot/trunk/core/src/org/apache/pivot/beans/ BeanMonitorListener.java
Modified:
incubator/pivot/trunk/tools/src/org/apache/pivot/tools/wtk/ ComponentInspectorSkin.java incubator/pivot/trunk/tools/src/org/apache/pivot/tools/wtk/ EventLogger.java incubator/pivot/trunk/tools/src/org/apache/pivot/tools/wtk/ component_inspector_skin.wtkx

Added: incubator/pivot/trunk/core/src/org/apache/pivot/beans/ BeanMonitor.java
URL: 
http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/org/apache/pivot/beans/BeanMonitor.java?rev=829797&view=auto
= = = = = = = = ====================================================================== --- incubator/pivot/trunk/core/src/org/apache/pivot/beans/ BeanMonitor.java (added) +++ incubator/pivot/trunk/core/src/org/apache/pivot/beans/ BeanMonitor.java Mon Oct 26 13:48:09 2009
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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 org.apache.pivot.beans;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Type;
+import java.util.Comparator;
+
+import org.apache.pivot.collections.ArrayList;
+import org.apache.pivot.collections.HashMap;
+import org.apache.pivot.collections.Sequence;
+import org.apache.pivot.collections.immutable.ImmutableList;
+import org.apache.pivot.util.ListenerList;
+import org.apache.pivot.util.ThreadUtilities;
+import org.apache.pivot.util.Vote;
+
+/**
+ * Notifies listeners of events fired from a source bean.
+ */
+public class BeanMonitor {
+ private static class EventComparator implements Comparator<Method> {
+        @Override
+        public int compare(Method event1, Method event2) {
+            int result = 0;
+
+            Class<?> listenerInterface1 = event1.getDeclaringClass();
+            Class<?> listenerInterface2 = event2.getDeclaringClass();
+
+            if (listenerInterface1 != listenerInterface2) {
+ result = listenerInterface1.getName().compareTo (listenerInterface2.getName());
+            }
+
+            if (result == 0) {
+ result = event1.getName().compareTo(event2.getName ());
+            }
+
+            return result;
+        }
+    }
+
+ private static class PropertyNameComparator implements Comparator<String> {
+        @Override
+ public int compare(String propertyName1, String propertyName2) {
+            return propertyName1.compareTo(propertyName2);
+        }
+    }
+
+ private class MonitorInvocationHandler implements InvocationHandler {
+        @Override
+ public Object invoke(Object proxy, Method event, Object[] arguments) throws Throwable { + beanMonitorListeners.eventFired(BeanMonitor.this, event, arguments);
+
+            String eventName = event.getName();
+            if (eventName.endsWith(PROPERTY_CHANGE_SUFFIX)) {
+ String propertyName = eventName.substring(0, eventName.length()
+                    - PROPERTY_CHANGE_SUFFIX.length());
+
+                if (notifyingProperties.indexOf(propertyName) >= 0) {
+ beanMonitorListeners.propertyChanged (BeanMonitor.this, propertyName);
+                }
+            }
+
+            Object result = null;
+            Class<?> returnType = event.getReturnType();
+            if (returnType == Vote.class) {
+                result = Vote.APPROVE;
+            } else if (returnType == Boolean.TYPE) {
+                result = false;
+            }
+
+            return result;
+        }
+    }
+
+ private static class BeanMonitorListenerList extends ListenerList<BeanMonitorListener>
+        implements BeanMonitorListener {
+        @Override
+ public void sourceChanged(BeanMonitor beanMonitor, Object previousSource) {
+            for (BeanMonitorListener listener : this) {
+                listener.sourceChanged(beanMonitor, previousSource);
+            }
+        }
+
+        @Override
+ public void eventFired(BeanMonitor beanMonitor, Method event, Object[] arguments) {
+            for (BeanMonitorListener listener : this) {
+                listener.eventFired(beanMonitor, event, arguments);
+            }
+        }
+
+        @Override
+ public void propertyChanged(BeanMonitor beanMonitor, String propertyName) {
+            for (BeanMonitorListener listener : this) {
+                listener.propertyChanged(beanMonitor, propertyName);
+            }
+        }
+    }
+
+    private Object source = null;
+
+ private HashMap<Class<?>, Object> eventListenerProxies = new HashMap<Class<?>, Object>(); + private MonitorInvocationHandler monitorInvocationHandler = new MonitorInvocationHandler();
+
+ private ArrayList<Method> declaredEvents = new ArrayList<Method> (eventComparator); + private ArrayList<String> notifyingProperties = new ArrayList<String>(propertyNameComparator);
+
+ private BeanMonitorListenerList beanMonitorListeners = new BeanMonitorListenerList();
+
+ private static EventComparator eventComparator = new EventComparator(); + private static PropertyNameComparator propertyNameComparator = new PropertyNameComparator();
+
+    private static final String PROPERTY_CHANGE_SUFFIX = "Changed";
+
+    /**
+ * Creates a new bean monitor that is initially associated with no source
+     * object.
+     */
+    public BeanMonitor() {
+        this(null);
+    }
+
+    /**
+ * Creates a new bean monitor that will monitor the specified source
+     * object.
+     * <p>
+ * <b>NOTE</b>: failing to clear the source of a bean monitor may result in + * memory leaks, as the source object will maintain references to the bean
+     * monitor as long as the source is set.
+     */
+    public BeanMonitor(Object source) {
+        setSource(source);
+    }
+
+    /**
+     * Gets the source of the bean monitor.
+     *
+     * @return
+     * The source object, or <tt>null</tt> if no source has been set.
+     */
+    public Object getSource() {
+        return source;
+    }
+
+    /**
+     * Sets the source of the bean monitor.
+     * <p>
+ * <b>NOTE</b>: failing to clear the source of a bean monitor may result in + * memory leaks, as the source object will maintain references to the bean
+     * monitor as long as the source is set.
+     *
+     * @param source
+     * The source object, or <tt>null</tt> to clear the source.
+     */
+    public void setSource(Object source) {
+        Object previousSource = this.source;
+
+        if (source != previousSource) {
+            this.source = source;
+
+            if (previousSource != null) {
+                unregisterEventListeners(previousSource);
+            }
+
+            declaredEvents.clear();
+            notifyingProperties.clear();
+
+            if (source != null) {
+                registerEventListeners(source);
+            }
+
+            beanMonitorListeners.sourceChanged(this, previousSource);
+        }
+    }
+
+    /**
+     * Gets the list of events that the source bean may fire.
+     *
+     * @return
+     * The event listener methods that the source bean may invoke.
+     */
+    public Sequence<Method> getDeclaredEvents() {
+        return new ImmutableList<Method>(declaredEvents);
+    }
+
+    /**
+ * Gets the list of source bean property names for which property change
+     * events will be fired.
+     *
+     * @return
+     * The property names that fire change events.
+     */
+    public Sequence<String> getNotifyingProperties() {
+        return new ImmutableList<String>(notifyingProperties);
+    }
+
+    /**
+ * Tells whether or not the specified property fires change events.
+     *
+     * @return
+ * <tt>true</tt> if the property fires change events; <tt>false</tt>
+     * otherwise.
+     */
+    public boolean isNotifyingProperty(String propertyName) {
+        return (notifyingProperties.indexOf(propertyName) >= 0);
+    }
+
+    /**
+     * Registers event listeners on a bean.
+     */
+    private void registerEventListeners(Object bean) {
+        BeanDictionary beanDictionary = new BeanDictionary(bean);
+        Method[] methods = bean.getClass().getMethods();
+
+        for (int i = 0; i < methods.length; i++) {
+            Method method = methods[i];
+
+ if (ListenerList.class.isAssignableFrom (method.getReturnType())
+                && (method.getModifiers() & Modifier.STATIC) == 0) {
+ ParameterizedType genericType = (ParameterizedType) method.getGenericReturnType(); + Type[] typeArguments = genericType.getActualTypeArguments();
+
+                if (typeArguments.length == 1) {
+ Class<?> listenerInterface = (Class<?>) typeArguments[0];
+
+                    if (!listenerInterface.isInterface()) {
+ throw new RuntimeException (listenerInterface.getName()
+                            + " is not an interface.");
+                    }
+
+ Method[] interfaceMethods = listenerInterface.getMethods(); + for (int j = 0; j < interfaceMethods.length; j+ +) {
+                        Method interfaceMethod = interfaceMethods[j];
+ String interfaceMethodName = interfaceMethod.getName();
+
+                        declaredEvents.add(interfaceMethod);
+
+ if (interfaceMethodName.endsWith (PROPERTY_CHANGE_SUFFIX)) { + String propertyName = interfaceMethodName.substring(0, + interfaceMethodName.length() - PROPERTY_CHANGE_SUFFIX.length());
+
+ if (beanDictionary.containsKey (propertyName)) { + notifyingProperties.add (propertyName);
+                            }
+                        }
+                    }
+
+                    // Get the listener list
+                    Object listenerList;
+                    try {
+                        listenerList = method.invoke(bean);
+                    } catch (InvocationTargetException exception) {
+                        throw new RuntimeException(exception);
+                    } catch (IllegalAccessException exception) {
+                        throw new RuntimeException(exception);
+                    }
+
+                    // Get the listener for this interface
+ Object listener = eventListenerProxies.get (listenerInterface);
+                    if (listener == null) {
+ listener = Proxy.newProxyInstance (ThreadUtilities.getClassLoader(), + new Class[]{listenerInterface}, monitorInvocationHandler); + eventListenerProxies.put(listenerInterface, listener);
+                    }
+
+                    // Add the listener
+ Class<?> listenerListClass = listenerList.getClass();
+                    Method addMethod;
+                    try {
+ addMethod = listenerListClass.getMethod ("add",
+                            new Class<?>[] {Object.class});
+                    } catch (NoSuchMethodException exception) {
+                        throw new RuntimeException(exception);
+                    }
+
+                    try {
+ addMethod.invoke(listenerList, new Object[] {listener});
+                    } catch (IllegalAccessException exception) {
+                        throw new RuntimeException(exception);
+                    } catch (InvocationTargetException exception) {
+                        throw new RuntimeException(exception);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Un-registers event listeners on a bean.
+     */
+    private void unregisterEventListeners(Object bean) {
+        Method[] methods = bean.getClass().getMethods();
+
+        for (int i = 0; i < methods.length; i++) {
+            Method method = methods[i];
+
+ if (ListenerList.class.isAssignableFrom (method.getReturnType())
+                && (method.getModifiers() & Modifier.STATIC) == 0) {
+ ParameterizedType genericType = (ParameterizedType) method.getGenericReturnType(); + Type[] typeArguments = genericType.getActualTypeArguments();
+
+                if (typeArguments.length == 1) {
+ Class<?> listenerInterface = (Class<?>) typeArguments[0];
+
+                    // Get the listener list
+                    Object listenerList;
+                    try {
+                        listenerList = method.invoke(bean);
+                    } catch (InvocationTargetException exception) {
+                        throw new RuntimeException(exception);
+                    } catch (IllegalAccessException exception) {
+                        throw new RuntimeException(exception);
+                    }
+
+                    // Get the listener for this interface
+ Object listener = eventListenerProxies.get (listenerInterface);
+                    if (listener == null) {
+ throw new IllegalStateException("Listener proxy is null.");
+                    }
+
+                    // Remove the listener
+ Class<?> listenerListClass = listenerList.getClass();
+                    Method removeMethod;
+                    try {
+ removeMethod = listenerListClass.getMethod ("remove",
+                            new Class<?>[] {Object.class});
+                    } catch (NoSuchMethodException exception) {
+                        throw new RuntimeException(exception);
+                    }
+
+                    try {
+ removeMethod.invoke(listenerList, new Object [] {listener});
+                    } catch (IllegalAccessException exception) {
+                        throw new RuntimeException(exception);
+                    } catch (InvocationTargetException exception) {
+                        throw new RuntimeException(exception);
+                    }
+                }
+            }
+        }
+    }
+
+ public ListenerList<BeanMonitorListener> getBeanMonitorListeners () {
+        return beanMonitorListeners;
+    }
+}

Added: incubator/pivot/trunk/core/src/org/apache/pivot/beans/ BeanMonitorListener.java
URL: 
http://svn.apache.org/viewvc/incubator/pivot/trunk/core/src/org/apache/pivot/beans/BeanMonitorListener.java?rev=829797&view=auto
= = = = = = = = ====================================================================== --- incubator/pivot/trunk/core/src/org/apache/pivot/beans/ BeanMonitorListener.java (added) +++ incubator/pivot/trunk/core/src/org/apache/pivot/beans/ BeanMonitorListener.java Mon Oct 26 13:48:09 2009
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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 org.apache.pivot.beans;
+
+import java.lang.reflect.Method;
+
+/**
+ * Bean monitor listener interface.
+ */
+public interface BeanMonitorListener {
+    /**
+     * Bean monitor listener adapter.
+     */
+    public static class Adapter implements BeanMonitorListener {
+        @Override
+ public void sourceChanged(BeanMonitor beanMonitor, Object previousSource) {
+        }
+
+        @Override
+ public void eventFired(BeanMonitor beanMonitor, Method event, Object[] arguments) {
+        }
+
+        @Override
+ public void propertyChanged(BeanMonitor beanMonitor, String propertyName) {
+        }
+    }
+
+    /**
+     * Called when a bean monitor's source has changed.
+     *
+     * @param beanMonitor
+     * @param previousSource
+     */
+ public void sourceChanged(BeanMonitor beanMonitor, Object previousSource);
+
+    /**
+ * Called when an event has been fired by the bean monitor's source.
+     *
+     * @param beanMonitor
+     * @param event
+     * @param arguments
+     */
+ public void eventFired(BeanMonitor beanMonitor, Method event, Object[] arguments);
+
+    /**
+ * Called when a property of the bean monitor's source has changed.
+     *
+     * @param beanMonitor
+     * @param propertyName
+     */
+ public void propertyChanged(BeanMonitor beanMonitor, String propertyName);
+}

Modified: incubator/pivot/trunk/tools/src/org/apache/pivot/tools/wtk/ ComponentInspectorSkin.java
URL: 
http://svn.apache.org/viewvc/incubator/pivot/trunk/tools/src/org/apache/pivot/tools/wtk/ComponentInspectorSkin.java?rev=829797&r1=829796&r2=829797&view=diff
= = = = = = = = ====================================================================== --- incubator/pivot/trunk/tools/src/org/apache/pivot/tools/wtk/ ComponentInspectorSkin.java (original) +++ incubator/pivot/trunk/tools/src/org/apache/pivot/tools/wtk/ ComponentInspectorSkin.java Mon Oct 26 13:48:09 2009
@@ -21,11 +21,12 @@
import java.util.Comparator;

import org.apache.pivot.beans.BeanDictionary;
+import org.apache.pivot.beans.BeanMonitor;
+import org.apache.pivot.beans.BeanMonitorListener;
import org.apache.pivot.collections.ArrayList;
import org.apache.pivot.collections.EnumList;
import org.apache.pivot.collections.HashMap;
import org.apache.pivot.collections.List;
-import org.apache.pivot.collections.Map;
import org.apache.pivot.serialization.SerializationException;
import org.apache.pivot.util.Resources;
import org.apache.pivot.wtk.BoxPane;
@@ -33,6 +34,7 @@
import org.apache.pivot.wtk.ButtonStateListener;
import org.apache.pivot.wtk.Checkbox;
import org.apache.pivot.wtk.Component;
+import org.apache.pivot.wtk.ComponentStateListener;
import org.apache.pivot.wtk.Dimensions;
import org.apache.pivot.wtk.FlowPane;
import org.apache.pivot.wtk.Form;
@@ -42,7 +44,6 @@
import org.apache.pivot.wtk.ListButtonSelectionListener;
import org.apache.pivot.wtk.Orientation;
import org.apache.pivot.wtk.Point;
-import org.apache.pivot.wtk.Rollup;
import org.apache.pivot.wtk.TextInput;
import org.apache.pivot.wtk.skin.ContainerSkin;
import org.apache.pivot.wtk.text.validation.IntValidator;
@@ -76,13 +77,41 @@

    private Component content = null;

-    @WTKX private BoxPane propertiesPane = null;
+    @WTKX private Form propertiesForm = null;
    @WTKX private BoxPane stylesPane = null;

+    private BeanDictionary beanDictionary = null;
+    private BeanMonitor beanMonitor = new BeanMonitor();
+
+ private HashMap<String, Component> inspectorComponents = new HashMap<String, Component>();
+
private static PropertyNameComparator propertyNameComparator = new PropertyNameComparator(); private static PropertySourceTypeComparator propertySourceTypeComparator =
        new PropertySourceTypeComparator();

+    public ComponentInspectorSkin() {
+ beanMonitor.getBeanMonitorListeners().add(new BeanMonitorListener.Adapter() {
+            @Override
+ public void propertyChanged(BeanMonitor beanMonitor, String propertyName) { + Class<?> propertyType = beanDictionary.getType (propertyName);
+
+                if (propertyType == Boolean.TYPE) {
+                    updateBooleanControl(propertyName);
+                } else if (propertyType == Integer.TYPE) {
+                    updateIntControl(propertyName);
+                } else if (propertyType.isEnum()) {
+                    updateEnumControl(propertyName);
+                } else if (propertyType == Point.class) {
+                    updatePointControl(propertyName);
+                } else if (propertyType == Dimensions.class) {
+                    updateDimensionsControl(propertyName);
+                } else if (propertyType == Limits.class) {
+                    updateLimitsControl(propertyName);
+                }
+            }
+        });
+    }
+
    @Override
    public void install(Component component) {
        super.install(component);
@@ -139,25 +168,26 @@

    @Override
public void sourceChanged(ComponentInspector componentInspector, Component previousSource) {
-        propertiesPane.remove(0, propertiesPane.getLength());
+ Form.SectionSequence propertiesSections = propertiesForm.getSections();
+        propertiesSections.remove(0, propertiesSections.getLength());
+
        stylesPane.remove(0, stylesPane.getLength());

        Component source = componentInspector.getSource();

+        beanDictionary = null;
+        beanMonitor.setSource(source);
+
        if (source != null) {
-            Class<?> sourceType = source.getClass();
- BeanDictionary beanDictionary = new BeanDictionary (source);
+            beanDictionary = new BeanDictionary(source);

-            Map<Class<?>, List<String>> propertyBuckets =
+            Class<?> sourceType = source.getClass();
+            HashMap<Class<?>, List<String>> propertyBuckets =
new HashMap<Class<?>, List<String>> (propertySourceTypeComparator);

            for (String propertyName : beanDictionary) {
- boolean readOnly = beanDictionary.isReadOnly (propertyName);
-
-                if (!readOnly) {
-                    // TODO?
- // Class<?> propertyType = beanDictionary.getType(propertyName);
-
+                if (beanMonitor.isNotifyingProperty(propertyName)
+                    && !beanDictionary.isReadOnly(propertyName)) {
Method method = BeanDictionary.getGetterMethod (sourceType, propertyName); Class<?> declaringClass = method.getDeclaringClass();

@@ -172,47 +202,42 @@
            }

            for (Class<?> declaringClass : propertyBuckets) {
-                Rollup rollup = new Rollup();
-                propertiesPane.add(rollup);
- Label label = new Label(declaringClass.getSimpleName ());
-                label.getStyles().put("color", 16);
-                label.getStyles().put("font", "{bold:true}");
-                rollup.setHeading(label);
-
-                Form form = new Form();
-                form.getStyles().put("rightAlignLabels", true);
                Form.Section section = new Form.Section();
-                form.getSections().add(section);
-                rollup.setContent(form);
+                section.setHeading(declaringClass.getSimpleName());
+                propertiesSections.add(section);

for (String propertyName : propertyBuckets.get (declaringClass)) { - addPropertyControl(propertyName, section, beanDictionary);
+                    addPropertyControl(propertyName, section);
                }
            }
        }
    }

- private void addPropertyControl(String propertyName, Form.Section section,
-        BeanDictionary beanDictionary) {
+ private void addPropertyControl(String propertyName, Form.Section section) {
        Class<?> propertyType = beanDictionary.getType(propertyName);

+        Component inspectorComponent = null;
+
        if (propertyType == Boolean.TYPE) {
-            addBooleanControl(propertyName, section, beanDictionary);
+ inspectorComponent = addBooleanControl(propertyName, section);
        } else if (propertyType == Integer.TYPE) {
-            addIntControl(propertyName, section, beanDictionary);
+ inspectorComponent = addIntControl(propertyName, section);
        } else if (propertyType.isEnum()) {
-            addEnumControl(propertyName, section, beanDictionary);
+ inspectorComponent = addEnumControl(propertyName, section);
        } else if (propertyType == Point.class) {
-            addPointControl(propertyName, section, beanDictionary);
+ inspectorComponent = addPointControl(propertyName, section);
        } else if (propertyType == Dimensions.class) {
- addDimensionsControl(propertyName, section, beanDictionary); + inspectorComponent = addDimensionsControl(propertyName, section);
        } else if (propertyType == Limits.class) {
-            addLimitsControl(propertyName, section, beanDictionary);
+ inspectorComponent = addLimitsControl(propertyName, section);
+        }
+
+        if (inspectorComponent != null) {
+ inspectorComponents.put(propertyName, inspectorComponent);
        }
    }

- private void addBooleanControl(final String propertyName, Form.Section section,
-        final BeanDictionary beanDictionary) {
+ private Component addBooleanControl(final String propertyName, Form.Section section) { boolean propertyValue = (Boolean)beanDictionary.get (propertyName);

        Checkbox checkbox = new Checkbox();
@@ -226,11 +251,20 @@
                beanDictionary.put(propertyName, button.isSelected());
            }
        });
+
+        return checkbox;
    }

- private void addIntControl(final String propertyName, Form.Section section,
-        final BeanDictionary beanDictionary) {
-        /*
+    private void updateBooleanControl(String propertyName) {
+ Checkbox checkbox = (Checkbox)inspectorComponents.get (propertyName);
+
+        if (checkbox != null) {
+ boolean propertyValue = (Boolean)beanDictionary.get (propertyName);
+            checkbox.setSelected(propertyValue);
+        }
+    }
+
+ private Component addIntControl(final String propertyName, Form.Section section) {
        int propertyValue = (Integer)beanDictionary.get(propertyName);

        TextInput textInput = new TextInput();
@@ -244,21 +278,33 @@
textInput.getComponentStateListeners().add(new ComponentStateListener.Adapter() {
            @Override
public void focusedChanged(Component component, Component obverseComponent) {
-                TextInput textInput = (TextInput)component;
-                try {
- beanDictionary.put(propertyName, Integer.parseInt(textInput.getText()));
-                } catch (Exception exception) {
- Object propertyValue = beanDictionary.get (propertyName);
-                    textInput.setText(String.valueOf(propertyValue));
+                if (!component.isFocused()) {
+                    TextInput textInput = (TextInput)component;
+
+                    try {
+ beanDictionary.put(propertyName, Integer.parseInt(textInput.getText()));
+                    } catch (Exception exception) {
+ Object propertyValue = beanDictionary.get (propertyName); + textInput.setText(String.valueOf (propertyValue));
+                    }
                }
            }
        });
-        */
+
+        return textInput;
+    }
+
+    private void updateIntControl(String propertyName) {
+ TextInput textInput = (TextInput)inspectorComponents.get (propertyName);
+
+        if (textInput != null) {
+ int propertyValue = (Integer)beanDictionary.get (propertyName);
+            textInput.setText(String.valueOf(propertyValue));
+        }
    }

    @SuppressWarnings("unchecked")
- private void addEnumControl(final String propertyName, Form.Section section,
-        final BeanDictionary beanDictionary) {
+ private Component addEnumControl(final String propertyName, Form.Section section) {
        Class<?> propertyType = beanDictionary.getType(propertyName);
Enum<?> propertyValue = (Enum<?>)beanDictionary.get (propertyName);

@@ -274,10 +320,20 @@
beanDictionary.put(propertyName, listButton.getSelectedItem());
            }
        });
+
+        return listButton;
    }

- private void addPointControl(final String propertyName, Form.Section section,
-        final BeanDictionary beanDictionary) {
+    private void updateEnumControl(String propertyName) {
+ ListButton listButton = (ListButton)inspectorComponents.get (propertyName);
+
+        if (listButton != null) {
+ Enum<?> propertyValue = (Enum<?>)beanDictionary.get (propertyName);
+            listButton.setSelectedItem(propertyValue);
+        }
+    }
+
+ private Component addPointControl(final String propertyName, Form.Section section) {
        Point point = (Point)beanDictionary.get(propertyName);

        BoxPane boxPane = new BoxPane(Orientation.VERTICAL);
@@ -296,6 +352,23 @@
        textInput.setText(String.valueOf(point.x));
        flowPane.add(textInput);

+ textInput.getComponentStateListeners().add(new ComponentStateListener.Adapter() {
+            @Override
+ public void focusedChanged(Component component, Component obverseComponent) {
+                if (!component.isFocused()) {
+                    TextInput textInput = (TextInput)component;
+ Point point = (Point)beanDictionary.get (propertyName);
+
+                    try {
+ int x = Integer.parseInt(textInput.getText ()); + beanDictionary.put(propertyName, new Point (x, point.y));
+                    } catch (Exception exception) {
+                        textInput.setText(String.valueOf(point.x));
+                    }
+                }
+            }
+        });
+
        Label label = new Label("x");
        label.getStyles().put("font", "{italic:true}");
        flowPane.add(label);
@@ -312,13 +385,45 @@
        textInput.setText(String.valueOf(point.y));
        flowPane.add(textInput);

+ textInput.getComponentStateListeners().add(new ComponentStateListener.Adapter() {
+            @Override
+ public void focusedChanged(Component component, Component obverseComponent) {
+                if (!component.isFocused()) {
+                    TextInput textInput = (TextInput)component;
+ Point point = (Point)beanDictionary.get (propertyName);
+
+                    try {
+ int y = Integer.parseInt(textInput.getText ()); + beanDictionary.put(propertyName, new Point (point.x, y));
+                    } catch (Exception exception) {
+                        textInput.setText(String.valueOf(point.y));
+                    }
+                }
+            }
+        });
+
        label = new Label("y");
        label.getStyles().put("font", "{italic:true}");
        flowPane.add(label);
+
+        return boxPane;
    }

- private void addDimensionsControl(final String propertyName, Form.Section section,
-        final BeanDictionary beanDictionary) {
+    private void updatePointControl(String propertyName) {
+ BoxPane boxPane = (BoxPane)inspectorComponents.get (propertyName);
+
+        if (boxPane != null) {
+            Point point = (Point)beanDictionary.get(propertyName);
+
+ TextInput xTextInput = (TextInput)((FlowPane)boxPane.get (0)).get(0); + TextInput yTextInput = (TextInput)((FlowPane)boxPane.get (1)).get(0);
+
+            xTextInput.setText(String.valueOf(point.x));
+            yTextInput.setText(String.valueOf(point.y));
+        }
+    }
+
+ private Component addDimensionsControl(final String propertyName, Form.Section section) { Dimensions dimensions = (Dimensions)beanDictionary.get (propertyName);

        BoxPane boxPane = new BoxPane(Orientation.VERTICAL);
@@ -337,6 +442,23 @@
        textInput.setText(String.valueOf(dimensions.width));
        flowPane.add(textInput);

+ textInput.getComponentStateListeners().add(new ComponentStateListener.Adapter() {
+            @Override
+ public void focusedChanged(Component component, Component obverseComponent) {
+                if (!component.isFocused()) {
+                    TextInput textInput = (TextInput)component;
+ Dimensions dimensions = (Dimensions) beanDictionary.get(propertyName);
+
+                    try {
+ int width = Integer.parseInt (textInput.getText()); + beanDictionary.put(propertyName, new Dimensions(width, dimensions.height));
+                    } catch (Exception exception) {
+ textInput.setText(String.valueOf (dimensions.width));
+                    }
+                }
+            }
+        });
+
        Label label = new Label("width");
        label.getStyles().put("font", "{italic:true}");
        flowPane.add(label);
@@ -353,13 +475,45 @@
        textInput.setText(String.valueOf(dimensions.height));
        flowPane.add(textInput);

+ textInput.getComponentStateListeners().add(new ComponentStateListener.Adapter() {
+            @Override
+ public void focusedChanged(Component component, Component obverseComponent) {
+                if (!component.isFocused()) {
+                    TextInput textInput = (TextInput)component;
+ Dimensions dimensions = (Dimensions) beanDictionary.get(propertyName);
+
+                    try {
+ int height = Integer.parseInt (textInput.getText()); + beanDictionary.put(propertyName, new Dimensions(dimensions.width, height));
+                    } catch (Exception exception) {
+ textInput.setText(String.valueOf (dimensions.height));
+                    }
+                }
+            }
+        });
+
        label = new Label("height");
        label.getStyles().put("font", "{italic:true}");
        flowPane.add(label);
+
+        return boxPane;
+    }
+
+    private void updateDimensionsControl(String propertyName) {
+ BoxPane boxPane = (BoxPane)inspectorComponents.get (propertyName);
+
+        if (boxPane != null) {
+ Dimensions dimensions = (Dimensions)beanDictionary.get (propertyName);
+
+ TextInput widthTextInput = (TextInput)((FlowPane) boxPane.get(0)).get(0); + TextInput heightTextInput = (TextInput)((FlowPane) boxPane.get(1)).get(0);
+
+            widthTextInput.setText(String.valueOf(dimensions.width));
+ heightTextInput.setText(String.valueOf (dimensions.height));
+        }
    }

- private void addLimitsControl(final String propertyName, Form.Section section,
-        final BeanDictionary beanDictionary) {
+ private Component addLimitsControl(final String propertyName, Form.Section section) {
        Limits limits = (Limits)beanDictionary.get(propertyName);

        BoxPane boxPane = new BoxPane(Orientation.VERTICAL);
@@ -378,6 +532,23 @@
        textInput.setText(String.valueOf(limits.min));
        flowPane.add(textInput);

+ textInput.getComponentStateListeners().add(new ComponentStateListener.Adapter() {
+            @Override
+ public void focusedChanged(Component component, Component obverseComponent) {
+                if (!component.isFocused()) {
+                    TextInput textInput = (TextInput)component;
+ Limits limits = (Limits)beanDictionary.get (propertyName);
+
+                    try {
+ int min = Integer.parseInt(textInput.getText ()); + beanDictionary.put(propertyName, new Limits (min, limits.max));
+                    } catch (Exception exception) {
+ textInput.setText(String.valueOf (limits.min));
+                    }
+                }
+            }
+        });
+
        Label label = new Label("min");
        label.getStyles().put("font", "{italic:true}");
        flowPane.add(label);
@@ -394,8 +565,41 @@
        textInput.setText(String.valueOf(limits.max));
        flowPane.add(textInput);

+ textInput.getComponentStateListeners().add(new ComponentStateListener.Adapter() {
+            @Override
+ public void focusedChanged(Component component, Component obverseComponent) {
+                if (!component.isFocused()) {
+                    TextInput textInput = (TextInput)component;
+ Limits limits = (Limits)beanDictionary.get (propertyName);
+
+                    try {
+ int max = Integer.parseInt(textInput.getText ()); + beanDictionary.put(propertyName, new Limits (limits.min, max));
+                    } catch (Exception exception) {
+ textInput.setText(String.valueOf (limits.max));
+                    }
+                }
+            }
+        });
+
        label = new Label("max");
        label.getStyles().put("font", "{italic:true}");
        flowPane.add(label);
+
+        return boxPane;
+    }
+
+    private void updateLimitsControl(String propertyName) {
+ BoxPane boxPane = (BoxPane)inspectorComponents.get (propertyName);
+
+        if (boxPane != null) {
+            Limits limits = (Limits)beanDictionary.get(propertyName);
+
+ TextInput minTextInput = (TextInput)((FlowPane) boxPane.get(0)).get(0); + TextInput maxTextInput = (TextInput)((FlowPane) boxPane.get(1)).get(0);
+
+            minTextInput.setText(String.valueOf(limits.min));
+            maxTextInput.setText(String.valueOf(limits.max));
+        }
    }
}

Modified: incubator/pivot/trunk/tools/src/org/apache/pivot/tools/wtk/ EventLogger.java
URL: 
http://svn.apache.org/viewvc/incubator/pivot/trunk/tools/src/org/apache/pivot/tools/wtk/EventLogger.java?rev=829797&r1=829796&r2=829797&view=diff
= = = = = = = = ====================================================================== --- incubator/pivot/trunk/tools/src/org/apache/pivot/tools/wtk/ EventLogger.java (original) +++ incubator/pivot/trunk/tools/src/org/apache/pivot/tools/wtk/ EventLogger.java Mon Oct 26 13:48:09 2009
@@ -16,68 +16,19 @@
 */
package org.apache.pivot.tools.wtk;

-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Proxy;
-import java.lang.reflect.Type;
-import java.util.Comparator;

-import org.apache.pivot.collections.ArrayList;
+import org.apache.pivot.beans.BeanMonitor;
+import org.apache.pivot.beans.BeanMonitorListener;
import org.apache.pivot.collections.Group;
-import org.apache.pivot.collections.HashMap;
import org.apache.pivot.collections.HashSet;
import org.apache.pivot.collections.Sequence;
-import org.apache.pivot.collections.immutable.ImmutableList;
import org.apache.pivot.collections.immutable.ImmutableSet;
import org.apache.pivot.util.ListenerList;
-import org.apache.pivot.util.ThreadUtilities;
-import org.apache.pivot.util.Vote;
import org.apache.pivot.wtk.Component;
import org.apache.pivot.wtk.Container;

public class EventLogger extends Container {
- private static class EventComparator implements Comparator<Method> {
-        @Override
-        public int compare(Method event1, Method event2) {
-            int result = 0;
-
-            Class<?> listenerInterface1 = event1.getDeclaringClass();
-            Class<?> listenerInterface2 = event2.getDeclaringClass();
-
-            if (listenerInterface1 != listenerInterface2) {
- result = listenerInterface1.getName().compareTo (listenerInterface2.getName());
-            }
-
-            if (result == 0) {
- result = event1.getName().compareTo(event2.getName ());
-            }
-
-            return result;
-        }
-    }
-
- private class LoggerInvocationHandler implements InvocationHandler {
-        @Override
- public Object invoke(Object proxy, Method event, Object[] arguments) throws Throwable {
-            if (includeEvents.contains(event)) {
- eventLoggerListeners.eventFired(EventLogger.this, event, arguments);
-            }
-
-            Object result = null;
-            Class<?> returnType = event.getReturnType();
-            if (returnType == Vote.class) {
-                result = Vote.APPROVE;
-            } else if (returnType == Boolean.TYPE) {
-                result = false;
-            }
-
-            return result;
-        }
-    }
-
private static class EventLoggerListenerList extends ListenerList<EventLoggerListener>
        implements EventLoggerListener {
        @Override
@@ -109,12 +60,21 @@
        }
    }

-    private Component source = null;
+ private BeanMonitorListener beanMonitorHandler = new BeanMonitorListener.Adapter() {
+        @Override
+ public void sourceChanged(BeanMonitor meanMonitor, Object previousSource) { + eventLoggerListeners.sourceChanged(EventLogger.this, (Component)previousSource);
+        }

- private HashMap<Class<?>, Object> eventListenerProxies = new HashMap<Class<?>, Object>(); - private LoggerInvocationHandler loggerInvocationHandler = new LoggerInvocationHandler();
+        @Override
+ public void eventFired(BeanMonitor meanMonitor, Method event, Object[] arguments) {
+            if (includeEvents.contains(event)) {
+ eventLoggerListeners.eventFired(EventLogger.this, event, arguments);
+            }
+        }
+    };

- private ArrayList<Method> declaredEvents = new ArrayList<Method> (new EventComparator());
+    private BeanMonitor beanMonitor = new BeanMonitor();

    private HashSet<Method> includeEvents = new HashSet<Method>();

@@ -125,34 +85,21 @@
    }

    public EventLogger(Component source) {
+ beanMonitor.getBeanMonitorListeners().add (beanMonitorHandler);
        setSource(source);
        setSkin(new EventLoggerSkin());
    }

    public Component getSource() {
-        return source;
+        return (Component)beanMonitor.getSource();
    }

    public void setSource(Component source) {
-        Component previousSource = this.source;
-
-        if (source != previousSource) {
-            this.source = source;
-
-            if (previousSource != null) {
-                unregisterEventListeners(previousSource);
-            }
-
-            if (source != null) {
-                registerEventListeners(source);
-            }
-
-            eventLoggerListeners.sourceChanged(this, previousSource);
-        }
+        beanMonitor.setSource(source);
    }

    public Sequence<Method> getDeclaredEvents() {
-        return new ImmutableList<Method>(declaredEvents);
+        return beanMonitor.getDeclaredEvents();
    }

    public Group<Method> getIncludeEvents() {
@@ -177,79 +124,6 @@
        return includeEvents.contains(event);
    }

-    private void registerEventListeners(Component source) {
-        declaredEvents.clear();
-
-        Method[] methods = source.getClass().getMethods();
-
-        for (int i = 0; i < methods.length; i++) {
-            Method method = methods[i];
-
- if (ListenerList.class.isAssignableFrom (method.getReturnType())
-                && (method.getModifiers() & Modifier.STATIC) == 0) {
- ParameterizedType genericType = (ParameterizedType) method.getGenericReturnType(); - Type[] typeArguments = genericType.getActualTypeArguments();
-
-                if (typeArguments.length == 1) {
- Class<?> listenerInterface = (Class<?>) typeArguments[0];
-
-                    if (!listenerInterface.isInterface()) {
- throw new RuntimeException (listenerInterface.getName()
-                            + " is not an interface.");
-                    }
-
- Method[] interfaceMethods = listenerInterface.getMethods(); - for (int j = 0; j < interfaceMethods.length; j+ +) {
-                        Method interfaceMethod = interfaceMethods[j];
-                        declaredEvents.add(interfaceMethod);
-                    }
-
-                    // Get the listener list
-                    Object listenerList;
-                    try {
-                        listenerList = method.invoke(source);
-                    } catch (InvocationTargetException exception) {
-                        throw new RuntimeException(exception);
-                    } catch (IllegalAccessException exception) {
-                        throw new RuntimeException(exception);
-                    }
-
-                    // Get the listener for this interface
- Object listener = eventListenerProxies.get (listenerInterface);
-                    if (listener == null) {
- listener = Proxy.newProxyInstance (ThreadUtilities.getClassLoader(), - new Class[]{listenerInterface}, loggerInvocationHandler); - eventListenerProxies.put(listenerInterface, listener);
-                    }
-
-                    // Add the listener
- Class<?> listenerListClass = listenerList.getClass();
-                    Method addMethod;
-                    try {
- addMethod = listenerListClass.getMethod ("add",
-                            new Class<?>[] {Object.class});
-                    } catch (NoSuchMethodException exception) {
-                        throw new RuntimeException(exception);
-                    }
-
-                    try {
- addMethod.invoke(listenerList, new Object[] {listener});
-                    } catch (IllegalAccessException exception) {
-                        throw new RuntimeException(exception);
-                    } catch (InvocationTargetException exception) {
-                        throw new RuntimeException(exception);
-                    }
-                }
-            }
-        }
-    }
-
-    private void unregisterEventListeners(Component source) {
-        declaredEvents.clear();
-
-        // TODO
-    }
-
public ListenerList<EventLoggerListener> getEventLoggerListeners () {
        return eventLoggerListeners;
    }

Modified: incubator/pivot/trunk/tools/src/org/apache/pivot/tools/wtk/ component_inspector_skin.wtkx
URL: 
http://svn.apache.org/viewvc/incubator/pivot/trunk/tools/src/org/apache/pivot/tools/wtk/component_inspector_skin.wtkx?rev=829797&r1=829796&r2=829797&view=diff
= = = = = = = = ====================================================================== --- incubator/pivot/trunk/tools/src/org/apache/pivot/tools/wtk/ component_inspector_skin.wtkx (original) +++ incubator/pivot/trunk/tools/src/org/apache/pivot/tools/wtk/ component_inspector_skin.wtkx Mon Oct 26 13:48:09 2009
@@ -22,7 +22,10 @@
    <view>
<BoxPane orientation="vertical" styles="{fill:true, horizontalAlignment:'right'}"> <Label text="%properties" styles="{padding:{left:10, top: 5}, font:{bold:true}}"/> - <BoxPane wtkx:id="propertiesPane" orientation="vertical" styles="{padding:{left:10}}"/> + <BoxPane orientation="vertical" styles="{padding:{left: 10}}">
+                <Form wtkx:id="propertiesForm"
+ styles="{rightAlignLabels:true, showFirstSectionHeading:true}"/>
+            </BoxPane>
            <Separator/>
<Label text="%styles" styles="{padding:{left:10}, font: {bold:true}}"/> <BoxPane wtkx:id="stylesPane" orientation="vertical" styles="{padding:{left:10}}"/>



Reply via email to