You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by gb...@apache.org on 2010/07/08 16:36:08 UTC
svn commit: r961785 - in /pivot/trunk: core/src/org/apache/pivot/beans/
core/src/org/apache/pivot/json/ demos/src/org/apache/pivot/demos/binding/
Author: gbrown
Date: Thu Jul 8 14:36:08 2010
New Revision: 961785
URL: http://svn.apache.org/viewvc?rev=961785&view=rev
Log:
Add initial support for BXML namespace binding.
Added:
pivot/trunk/demos/src/org/apache/pivot/demos/binding/
pivot/trunk/demos/src/org/apache/pivot/demos/binding/NamespaceBindingDemo.java
pivot/trunk/demos/src/org/apache/pivot/demos/binding/namespace_binding_demo.bxml
Modified:
pivot/trunk/core/src/org/apache/pivot/beans/NamespaceBinding.java
pivot/trunk/core/src/org/apache/pivot/json/JSON.java
Modified: pivot/trunk/core/src/org/apache/pivot/beans/NamespaceBinding.java
URL: http://svn.apache.org/viewvc/pivot/trunk/core/src/org/apache/pivot/beans/NamespaceBinding.java?rev=961785&r1=961784&r2=961785&view=diff
==============================================================================
--- pivot/trunk/core/src/org/apache/pivot/beans/NamespaceBinding.java (original)
+++ pivot/trunk/core/src/org/apache/pivot/beans/NamespaceBinding.java Thu Jul 8 14:36:08 2010
@@ -16,53 +16,203 @@
*/
package org.apache.pivot.beans;
+import org.apache.pivot.collections.Dictionary;
+import org.apache.pivot.collections.Map;
+import org.apache.pivot.collections.MapListener;
+import org.apache.pivot.collections.Sequence;
+import org.apache.pivot.json.JSON;
+
/**
- * Represents a binding relationship between an object property and a namespace
- * path.
+ * Represents a binding relationship between a source property and a target
+ * property within a namespace.
*/
public class NamespaceBinding {
- private Object object;
- private String key;
- private String path;
+ private Map<String, Object> namespace;
+
+ private String sourcePath;
+ private Object source;
+ private Map<String, Object> sourceMap;
+ private BeanMonitor sourceMonitor;
+ private String sourceKey;
+
+ private String targetPath;
+ private Object target;
+ private Dictionary<String, Object> targetDictionary;
+ private String targetKey;
+
+ private MapListener<String, Object> sourceMapListener = new MapListener.Adapter<String, Object>() {
+ @Override
+ public void valueUpdated(Map<String, Object> map, String key, Object previousValue) {
+ if (key.equals(sourceKey)) {
+ targetDictionary.put(targetKey, sourceMap.get(sourceKey));
+ }
+ }
+ };
+
+ private PropertyChangeListener sourcePropertyChangeListener = new PropertyChangeListener() {
+ @Override
+ public void propertyChanged(Object bean, String propertyName) {
+ if (propertyName.equals(sourceKey)) {
+ targetDictionary.put(targetKey, sourceMap.get(sourceKey));
+ }
+ }
+ };
+
+ @SuppressWarnings("unchecked")
+ public NamespaceBinding(Map<String, Object> namespace, String sourcePath, String targetPath) {
+ if (namespace == null) {
+ throw new IllegalArgumentException();
+ }
+
+ if (sourcePath == null) {
+ throw new IllegalArgumentException();
+ }
+
+ if (targetPath == null) {
+ throw new IllegalArgumentException();
+ }
+
+ // Set the namespace
+ this.namespace = namespace;
+
+ // Set the source properties
+ this.sourcePath = sourcePath;
+
+ Sequence<String> sourceKeys = JSON.parse(sourcePath);
+ int sourceKeyCount = sourceKeys.getLength();
+
+ source = JSON.get(namespace, sourceKeys, sourceKeyCount - 1);
+
+ if (source instanceof Map<?, ?>) {
+ sourceMap = (Map<String, Object>)source;
+ sourceMonitor = null;
+ } else {
+ sourceMap = new BeanAdapter(source);
+ sourceMonitor = new BeanMonitor(source);
+ }
+
+ sourceKey = sourceKeys.get(sourceKeyCount - 1);
+
+ if (!sourceMap.containsKey(sourceKey)) {
+ throw new IllegalArgumentException("Source property \"" + sourcePath
+ + "\" does not exist.");
+ }
+
+ // Set the target properties
+ this.targetPath = targetPath;
+
+ Sequence<String> targetKeys = JSON.parse(targetPath);
+ int targetKeyCount = targetKeys.getLength();
+
+ target = JSON.get(namespace, targetKeys, targetKeyCount - 1);
+
+ if (target instanceof Dictionary<?, ?>) {
+ targetDictionary = (Dictionary<String, Object>)target;
+ } else {
+ targetDictionary = new BeanAdapter(target);
+ }
+
+ targetKey = targetKeys.get(targetKeyCount - 1);
+
+ if (!targetDictionary.containsKey(targetKey)) {
+ throw new IllegalArgumentException("Target property \"" + targetPath
+ + "\" does not exist.");
+ }
- public NamespaceBinding(Object object, String key, String path) {
- this.object = object;
- this.key = key;
- this.path = path;
+ // Perform the initial set from source to target
+ targetDictionary.put(targetKey, sourceMap.get(sourceKey));
}
/**
- * Returns the bound object.
+ * Returns the namespace.
*/
- public Object getObject() {
- return object;
+ public Map<String, Object> getNamespace() {
+ return namespace;
}
/**
- * Returns the bound property.
+ * Returns the path to the source property.
*/
- public String getKey() {
- return key;
+ public String getSourcePath() {
+ return sourcePath;
}
/**
- * Returns the namespace path to which the object property is bound.
+ * Returns the source object.
*/
- public String getPath() {
- return path;
+ public Object getSource() {
+ return source;
}
/**
- * Binds the object property to the namespace path.
+ * Returns the name of the source property.
+ */
+ public String getSourceKey() {
+ return sourceKey;
+ }
+
+ /**
+ * Returns the path to the target property.
+ */
+ public String getTargetPath() {
+ return targetPath;
+ }
+
+ /**
+ * Returns the target object.
+ */
+ public Object getTarget() {
+ return target;
+ }
+
+ /**
+ * Returns the name of the target property.
+ */
+ public String getTargetKey() {
+ return targetKey;
+ }
+
+ /**
+ * Binds the source property to the target property.
*/
public void bind() {
- // TODO
+ if (source instanceof Map<?, ?>) {
+ sourceMap.getMapListeners().add(sourceMapListener);
+ } else {
+ sourceMonitor.getPropertyChangeListeners().add(sourcePropertyChangeListener);
+ }
}
/**
- * Unbinds the object property from the namespace path.
+ * Unbinds the source property from the target property.
*/
public void unbind() {
- // TODO
+ if (source instanceof Map<?, ?>) {
+ sourceMap.getMapListeners().remove(sourceMapListener);
+ } else {
+ sourceMonitor.getPropertyChangeListeners().remove(sourcePropertyChangeListener);
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ boolean equals = false;
+
+ if (o instanceof NamespaceBinding) {
+ NamespaceBinding namespaceBinding = (NamespaceBinding)o;
+
+ equals = (source == namespaceBinding.source
+ && sourceKey.equals(namespaceBinding.sourceKey)
+ && target == namespaceBinding.target
+ && targetKey.equals(namespaceBinding.targetKey));
+ }
+
+ return equals;
+ }
+
+ @Override
+ public int hashCode() {
+ return (source.hashCode() * sourceKey.hashCode()
+ + target.hashCode() * targetKey.hashCode());
}
}
Modified: pivot/trunk/core/src/org/apache/pivot/json/JSON.java
URL: http://svn.apache.org/viewvc/pivot/trunk/core/src/org/apache/pivot/json/JSON.java?rev=961785&r1=961784&r2=961785&view=diff
==============================================================================
--- pivot/trunk/core/src/org/apache/pivot/json/JSON.java (original)
+++ pivot/trunk/core/src/org/apache/pivot/json/JSON.java Thu Jul 8 14:36:08 2010
@@ -57,6 +57,24 @@ public class JSON {
* Returns the value at the given path.
*
* @param root
+ * The root object.
+ *
+ * @param keys
+ * The path to the value.
+ *
+ * @return
+ * The value at the given path.
+ *
+ * @see #get(Object, Sequence, int)
+ */
+ public static Object get(Object root, Sequence<String> keys) {
+ return get(root, keys, keys.getLength());
+ }
+
+ /**
+ * Returns the value at a given depth along a path.
+ *
+ * @param root
* The root object; must be an instance of {@link org.apache.pivot.collections.Map}
* or {@link org.apache.pivot.collections.List} or a Java bean object.
*
@@ -64,13 +82,13 @@ public class JSON {
* The path to the value, as a set of keys.
*
* @return
- * The value at the given path.
+ * The value at the given depth along the given path.
*/
@SuppressWarnings("unchecked")
- public static Object get(Object root, Sequence<String> keys) {
+ public static Object get(Object root, Sequence<String> keys, int depth) {
Object value = root;
- for (int i = 0, n = keys.getLength(); i < n; i++) {
+ for (int i = 0; i < depth; i++) {
String key = keys.get(i);
if (value instanceof Sequence<?>) {
Added: pivot/trunk/demos/src/org/apache/pivot/demos/binding/NamespaceBindingDemo.java
URL: http://svn.apache.org/viewvc/pivot/trunk/demos/src/org/apache/pivot/demos/binding/NamespaceBindingDemo.java?rev=961785&view=auto
==============================================================================
--- pivot/trunk/demos/src/org/apache/pivot/demos/binding/NamespaceBindingDemo.java (added)
+++ pivot/trunk/demos/src/org/apache/pivot/demos/binding/NamespaceBindingDemo.java Thu Jul 8 14:36:08 2010
@@ -0,0 +1,53 @@
+/*
+ * 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.demos.binding;
+
+import java.net.URL;
+
+import org.apache.pivot.beans.Bindable;
+import org.apache.pivot.beans.NamespaceBinding;
+import org.apache.pivot.collections.Map;
+import org.apache.pivot.util.Resources;
+import org.apache.pivot.wtk.Window;
+
+public class NamespaceBindingDemo extends Window implements Bindable {
+ @Override
+ public void initialize(Map<String, Object> namespace, URL location, Resources resources) {
+ // One-way binding
+ NamespaceBinding textInputToLabelBinding = new NamespaceBinding(namespace,
+ "textInput.text", "label.text");
+ textInputToLabelBinding.bind();
+
+ // Two-way binding
+ NamespaceBinding textInput1ToTextInput2Binding = new NamespaceBinding(namespace,
+ "textInput1.text", "textInput2.text");
+ textInput1ToTextInput2Binding.bind();
+
+ NamespaceBinding textInput2ToTextInput1Binding = new NamespaceBinding(namespace,
+ "textInput2.text", "textInput1.text");
+ textInput2ToTextInput1Binding.bind();
+
+ // Style binding
+ NamespaceBinding colorChooserButtonToLabelTextBinding = new NamespaceBinding(namespace,
+ "colorChooserButton.selectedColor", "colorLabel.text");
+ colorChooserButtonToLabelTextBinding.bind();
+
+ NamespaceBinding colorChooserButtonToLabelColorBinding = new NamespaceBinding(namespace,
+ "colorChooserButton.selectedColor", "colorLabel.styles['color']");
+ colorChooserButtonToLabelColorBinding.bind();
+ }
+}
Added: pivot/trunk/demos/src/org/apache/pivot/demos/binding/namespace_binding_demo.bxml
URL: http://svn.apache.org/viewvc/pivot/trunk/demos/src/org/apache/pivot/demos/binding/namespace_binding_demo.bxml?rev=961785&view=auto
==============================================================================
--- pivot/trunk/demos/src/org/apache/pivot/demos/binding/namespace_binding_demo.bxml (added)
+++ pivot/trunk/demos/src/org/apache/pivot/demos/binding/namespace_binding_demo.bxml Thu Jul 8 14:36:08 2010
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+
+<binding:NamespaceBindingDemo title="Namespace Binding Test" maximized="true"
+ xmlns:bxml="http://pivot.apache.org/bxml"
+ xmlns:binding="org.apache.pivot.demos.binding"
+ xmlns="org.apache.pivot.wtk">
+ <Form>
+ <Form.Section heading="One-Way Binding">
+ <TextInput bxml:id="textInput" Form.label="Text Input"/>
+ <Label bxml:id="label" Form.label="Label"/>
+ </Form.Section>
+
+ <Form.Section heading="Two-Way Binding">
+ <TextInput bxml:id="textInput1" Form.label="Text Input 1"/>
+ <TextInput bxml:id="textInput2" Form.label="Text Input 2"/>
+ </Form.Section>
+
+ <Form.Section heading="Style Binding">
+ <ColorChooserButton bxml:id="colorChooserButton" Form.label="Color Chooser Button"
+ selectedColor="#000000"/>
+ <Label bxml:id="colorLabel" Form.label="Color Label"/>
+ </Form.Section>
+ </Form>
+</binding:NamespaceBindingDemo>