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}}"/>