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/08/27 17:02:11 UTC
svn commit: r990170 - in /pivot/trunk: core/src/org/apache/pivot/beans/
tutorials/src/org/apache/pivot/tutorials/databinding/
Author: gbrown
Date: Fri Aug 27 15:02:11 2010
New Revision: 990170
URL: http://svn.apache.org/viewvc?rev=990170&view=rev
Log:
Add bind mapping support to NamespaceBinding and BXMLSerializer; automatically generate an ID for bind target if none specified.
Modified:
pivot/trunk/core/src/org/apache/pivot/beans/BXMLSerializer.java
pivot/trunk/core/src/org/apache/pivot/beans/NamespaceBinding.java
pivot/trunk/tutorials/src/org/apache/pivot/tutorials/databinding/PropertyBinding.java
pivot/trunk/tutorials/src/org/apache/pivot/tutorials/databinding/property_binding.bxml
Modified: pivot/trunk/core/src/org/apache/pivot/beans/BXMLSerializer.java
URL: http://svn.apache.org/viewvc/pivot/trunk/core/src/org/apache/pivot/beans/BXMLSerializer.java?rev=990170&r1=990169&r2=990170&view=diff
==============================================================================
--- pivot/trunk/core/src/org/apache/pivot/beans/BXMLSerializer.java (original)
+++ pivot/trunk/core/src/org/apache/pivot/beans/BXMLSerializer.java Fri Aug 27 15:02:11 2010
@@ -193,6 +193,40 @@ public class BXMLSerializer implements S
}
}
+ private static class ScriptBindMapping implements NamespaceBinding.BindMapping {
+ private ScriptEngine scriptEngine;
+ private String functionName;
+
+ public ScriptBindMapping(ScriptEngine scriptEngine, String functionName) {
+ this.scriptEngine = scriptEngine;
+ this.functionName = functionName;
+ }
+
+ public Object evaluate(Object value) {
+ Bindings bindings = scriptEngine.getBindings(ScriptContext.GLOBAL_SCOPE);
+ if (bindings.containsKey(functionName)) {
+ Invocable invocable;
+ try {
+ invocable = (Invocable)scriptEngine;
+ } catch (ClassCastException exception) {
+ throw new RuntimeException(exception);
+ }
+
+ try {
+ value = invocable.invokeFunction(functionName, value);
+ } catch (NoSuchMethodException exception) {
+ throw new RuntimeException(exception);
+ } catch (ScriptException exception) {
+ throw new RuntimeException(exception);
+ }
+ } else {
+ throw new RuntimeException("Mapping function \"" + functionName + "\" is not defined.");
+ }
+
+ return value;
+ }
+ };
+
private XMLInputFactory xmlInputFactory;
private ScriptEngineManager scriptEngineManager;
@@ -205,6 +239,7 @@ public class BXMLSerializer implements S
private Object root = null;
private String language = null;
+ private int nextID = 0;
private LinkedList<Attribute> namespaceBindingAttributes = new LinkedList<Attribute>();
@@ -218,6 +253,8 @@ public class BXMLSerializer implements S
public static final String NAMESPACE_BINDING_PREFIX = OBJECT_REFERENCE_PREFIX + "{";
public static final String NAMESPACE_BINDING_SUFFIX = "}";
+ public static final String BIND_MAPPING_DELIMITER = ":";
+ public static final String INTERNAL_ID_PREFIX = "$";
public static final String LANGUAGE_PROCESSING_INSTRUCTION = "language";
@@ -422,16 +459,28 @@ public class BXMLSerializer implements S
Element element = attribute.element;
String sourcePath = (String)attribute.value;
+ NamespaceBinding.BindMapping bindMapping;
+ int i = sourcePath.indexOf(BIND_MAPPING_DELIMITER);
+ if (i == -1) {
+ bindMapping = null;
+ } else {
+ String bindFunction = sourcePath.substring(0, i);
+ sourcePath = sourcePath.substring(i + 1);
+ bindMapping = new ScriptBindMapping(scriptEngineManager.getEngineByName(language), bindFunction);
+ }
+
switch (element.type) {
case INSTANCE:
case INCLUDE: {
// Bind to <element ID>.<attribute name>
if (element.id == null) {
- throw new SerializationException("Bind target does not have an ID.");
+ element.id = INTERNAL_ID_PREFIX + Integer.toString(nextID++);
+ namespace.put(element.id, element.value);
}
String targetPath = element.id + "." + attribute.name;
- NamespaceBinding namespaceBinding = new NamespaceBinding(namespace, sourcePath, targetPath);
+ NamespaceBinding namespaceBinding = new NamespaceBinding(namespace, sourcePath, targetPath,
+ bindMapping);
namespaceBinding.bind();
break;
@@ -440,11 +489,13 @@ public class BXMLSerializer implements S
case READ_ONLY_PROPERTY: {
// Bind to <parent element ID>.<element name>.<attribute name>
if (element.parent.id == null) {
- throw new SerializationException("Bind target does not have an ID.");
+ element.parent.id = INTERNAL_ID_PREFIX + Integer.toString(nextID++);
+ namespace.put(element.parent.id, element.parent.value);
}
String targetPath = element.parent.id + "." + element.name + "." + attribute.name;
- NamespaceBinding namespaceBinding = new NamespaceBinding(namespace, sourcePath, targetPath);
+ NamespaceBinding namespaceBinding = new NamespaceBinding(namespace, sourcePath, targetPath,
+ bindMapping);
namespaceBinding.bind();
break;
@@ -1472,7 +1523,7 @@ public class BXMLSerializer implements S
}
/**
- * Gets a read-only version of the xml stream reader that's being used by
+ * Gets a read-only version of the XML stream reader that's being used by
* this serializer. Subclasses can use this to access information about the
* current event.
*/
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=990170&r1=990169&r2=990170&view=diff
==============================================================================
--- pivot/trunk/core/src/org/apache/pivot/beans/NamespaceBinding.java (original)
+++ pivot/trunk/core/src/org/apache/pivot/beans/NamespaceBinding.java Fri Aug 27 15:02:11 2010
@@ -27,6 +27,18 @@ import org.apache.pivot.json.JSON;
* property within a namespace.
*/
public class NamespaceBinding {
+ /**
+ * Namespace bind mapping interface.
+ */
+ public interface BindMapping {
+ /**
+ * Transforms a source value during a bind operation.
+ *
+ * @param value
+ */
+ public Object evaluate(Object value);
+ }
+
private Map<String, Object> namespace;
private String sourcePath;
@@ -40,6 +52,8 @@ public class NamespaceBinding {
private Dictionary<String, Object> targetDictionary;
private String targetKey;
+ private BindMapping bindMapping;
+
private boolean updating = false;
private MapListener<String, Object> sourceMapListener = new MapListener.Adapter<String, Object>() {
@@ -48,7 +62,7 @@ public class NamespaceBinding {
if (key.equals(sourceKey)
&& !updating) {
updating = true;
- targetDictionary.put(targetKey, sourceMap.get(sourceKey));
+ targetDictionary.put(targetKey, getMappedSourceValue());
updating = false;
}
}
@@ -60,14 +74,19 @@ public class NamespaceBinding {
if (propertyName.equals(sourceKey)
&& !updating) {
updating = true;
- targetDictionary.put(targetKey, sourceMap.get(sourceKey));
+ targetDictionary.put(targetKey, getMappedSourceValue());
updating = false;
}
}
};
- @SuppressWarnings("unchecked")
public NamespaceBinding(Map<String, Object> namespace, String sourcePath, String targetPath) {
+ this(namespace, sourcePath, targetPath, null);
+ }
+
+ @SuppressWarnings("unchecked")
+ public NamespaceBinding(Map<String, Object> namespace, String sourcePath, String targetPath,
+ BindMapping bindMapping) {
if (namespace == null) {
throw new IllegalArgumentException();
}
@@ -126,8 +145,11 @@ public class NamespaceBinding {
+ "\" does not exist.");
}
+ // Set the bind mapping
+ this.bindMapping = bindMapping;
+
// Perform the initial set from source to target
- targetDictionary.put(targetKey, sourceMap.get(sourceKey));
+ targetDictionary.put(targetKey, getMappedSourceValue());
}
/**
@@ -180,6 +202,25 @@ public class NamespaceBinding {
}
/**
+ * Returns the bind mapping.
+ *
+ * @return
+ * The bind mapping to use during binding, or <tt>null</tt> if no bind
+ * mapping is specified.
+ */
+ public BindMapping getBindMapping() {
+ return bindMapping;
+ }
+
+ /**
+ * Returns the current source value with any bind mapping applied.
+ */
+ public Object getMappedSourceValue() {
+ Object sourceValue = sourceMap.get(sourceKey);
+ return (bindMapping == null) ? sourceValue : bindMapping.evaluate(sourceValue);
+ }
+
+ /**
* Binds the source property to the target property.
*/
public void bind() {
Modified: pivot/trunk/tutorials/src/org/apache/pivot/tutorials/databinding/PropertyBinding.java
URL: http://svn.apache.org/viewvc/pivot/trunk/tutorials/src/org/apache/pivot/tutorials/databinding/PropertyBinding.java?rev=990170&r1=990169&r2=990170&view=diff
==============================================================================
--- pivot/trunk/tutorials/src/org/apache/pivot/tutorials/databinding/PropertyBinding.java (original)
+++ pivot/trunk/tutorials/src/org/apache/pivot/tutorials/databinding/PropertyBinding.java Fri Aug 27 15:02:11 2010
@@ -16,6 +16,7 @@
*/
package org.apache.pivot.tutorials.databinding;
+import java.awt.Color;
import java.net.URL;
import org.apache.pivot.beans.Bindable;
@@ -27,9 +28,25 @@ import org.apache.pivot.wtk.Window;
public class PropertyBinding extends Window implements Bindable {
@Override
public void initialize(Map<String, Object> namespace, URL location, Resources resources) {
- // Manually bind list button selection to label text
- NamespaceBinding namespaceBinding = new NamespaceBinding(namespace,
- "listButton.selectedItem", "listButtonLabel.text");
- namespaceBinding.bind();
+ // Bind list button selection to label text
+ NamespaceBinding namespaceBinding1 = new NamespaceBinding(namespace,
+ "listButton.selectedItem", "listButtonLabel1.text");
+
+ namespaceBinding1.bind();
+
+ // Bind list button selection to label text with bind mapping
+ NamespaceBinding namespaceBinding2 = new NamespaceBinding(namespace,
+ "listButton.selectedItem", "listButtonLabel2.text", new NamespaceBinding.BindMapping() {
+ @Override
+ public Object evaluate(Object value) {
+ return value.toString().toUpperCase();
+ }
+ });
+
+ namespaceBinding2.bind();
+ }
+
+ public static String toHex(Color color) {
+ return String.format("#%02X%02X%02X", color.getRed(), color.getBlue(), color.getGreen());
}
}
Modified: pivot/trunk/tutorials/src/org/apache/pivot/tutorials/databinding/property_binding.bxml
URL: http://svn.apache.org/viewvc/pivot/trunk/tutorials/src/org/apache/pivot/tutorials/databinding/property_binding.bxml?rev=990170&r1=990169&r2=990170&view=diff
==============================================================================
--- pivot/trunk/tutorials/src/org/apache/pivot/tutorials/databinding/property_binding.bxml (original)
+++ pivot/trunk/tutorials/src/org/apache/pivot/tutorials/databinding/property_binding.bxml Fri Aug 27 15:02:11 2010
@@ -20,11 +20,24 @@ limitations under the License.
xmlns:bxml="http://pivot.apache.org/bxml"
xmlns:databinding="org.apache.pivot.tutorials.databinding"
xmlns="org.apache.pivot.wtk">
+ <bxml:script>
+ importClass(org.apache.pivot.tutorials.databinding.PropertyBinding);
+
+ function toUpperCase(value) {
+ return value.toUpperCase();
+ }
+
+ function toHex(color) {
+ return PropertyBinding.toHex(color);
+ }
+ </bxml:script>
+
<Border>
<Form>
<Form.Section heading="One-Way Binding">
<TextInput bxml:id="textInput" Form.label="Text Input"/>
- <Label bxml:id="textInputLabel" Form.label="Text" text="${textInput.text}"/>
+ <Label Form.label="Text" text="${textInput.text}"/>
+ <Label Form.label="Uppercase Text" text="${toUpperCase:textInput.text}"/>
</Form.Section>
<Form.Section heading="Two-Way Binding">
@@ -35,16 +48,19 @@ limitations under the License.
<Form.Section heading="Style Binding">
<ColorChooserButton bxml:id="colorChooserButton" Form.label="Color Chooser Button"
selectedColor="#000000"/>
- <Label bxml:id="colorChooserLabel" Form.label="Selected Color"
- text="${colorChooserButton.selectedColor}">
+ <Label Form.label="Selected Color" text="${colorChooserButton.selectedColor}">
<styles color="${colorChooserButton.selectedColor}"/>
</Label>
+ <Label Form.label="Selected Color (Hex)" text="${toHex:colorChooserButton.selectedColor}">
+ <styles color="${toHex:colorChooserButton.selectedColor}"/>
+ </Label>
</Form.Section>
<Form.Section heading="Manual Binding">
<ListButton bxml:id="listButton" Form.label="List Button"
listData="['Zero', 'One', 'Two', 'Three']" selectedIndex="0"/>
- <Label bxml:id="listButtonLabel" Form.label="Selected Index"/>
+ <Label bxml:id="listButtonLabel1" Form.label="Selected Item"/>
+ <Label bxml:id="listButtonLabel2" Form.label="Uppercase Selected Item"/>
</Form.Section>
</Form>
</Border>