Add resource support in binding expression.
Change-Id: Iccb8c3a5856c247d8245fe97a3c37cd60bb7e758
diff --git a/compiler/src/main/java/com/android/databinding/ExpressionVisitor.java b/compiler/src/main/java/com/android/databinding/ExpressionVisitor.java
index ce603e5..dbc6f55 100644
--- a/compiler/src/main/java/com/android/databinding/ExpressionVisitor.java
+++ b/compiler/src/main/java/com/android/databinding/ExpressionVisitor.java
@@ -143,6 +143,11 @@
return mModel.math(ctx.left.accept(this), ctx.op.getText(), ctx.right.accept(this));
}
+ @Override
+ public Expr visitResource(@NotNull BindingExpressionParser.ResourceContext ctx) {
+ return mModel.resourceExpr(ctx.getText());
+ }
+
// @Override
// public Expr visitIdentifier(@NotNull BindingExpressionParser.IdentifierContext ctx) {
// final String identifier = ctx.Identifier().getText();
diff --git a/compiler/src/main/java/com/android/databinding/expr/Expr.java b/compiler/src/main/java/com/android/databinding/expr/Expr.java
index 88eef39..d68124b 100644
--- a/compiler/src/main/java/com/android/databinding/expr/Expr.java
+++ b/compiler/src/main/java/com/android/databinding/expr/Expr.java
@@ -124,7 +124,7 @@
private BitSet resolveInvalidFlags() {
BitSet bitSet = new BitSet();
- if (mCanBeInvalidated) {
+ if (mCanBeInvalidated || getDependants().isEmpty()) {
bitSet.set(getId(), true);
}
for (Dependency dependency : getDependencies()) {
diff --git a/compiler/src/main/java/com/android/databinding/expr/ExprModel.java b/compiler/src/main/java/com/android/databinding/expr/ExprModel.java
index ea7bbc7..bfe04e5 100644
--- a/compiler/src/main/java/com/android/databinding/expr/ExprModel.java
+++ b/compiler/src/main/java/com/android/databinding/expr/ExprModel.java
@@ -142,6 +142,10 @@
return register(new GroupExpr(grouped));
}
+ public Expr resourceExpr(String resourceText) {
+ return register(new ResourceExpr(resourceText));
+ }
+
public List<Expr> getBindingExpressions() {
return mBindingExpressions;
}
diff --git a/compiler/src/main/java/com/android/databinding/expr/ResourceExpr.java b/compiler/src/main/java/com/android/databinding/expr/ResourceExpr.java
new file mode 100644
index 0000000..80cbbf5
--- /dev/null
+++ b/compiler/src/main/java/com/android/databinding/expr/ResourceExpr.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.databinding.expr;
+
+import com.google.common.collect.ImmutableMap;
+
+import com.android.databinding.ClassAnalyzer;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+
+public class ResourceExpr extends Expr {
+
+ private final static Map<String, String> RESOURCE_TYPE_TO_R_OBJECT =
+ ImmutableMap.<String, String>builder()
+ .put("colorStateList", "color ")
+ .put("dimenOffset", "dimen ")
+ .put("dimenSize", "dimen ")
+ .put("intArray", "array ")
+ .put("stateListAnimator", "animator ")
+ .put("stringArray", "array ")
+ .put("typedArray", "array")
+ .build();
+
+ private final String mPackage;
+
+ private final String mResourceType;
+
+ private final String mResourceId;
+
+ public ResourceExpr(String resourceText) {
+ int colonIndex = resourceText.indexOf(':');
+ int slashIndex = resourceText.indexOf('/');
+ mResourceType = resourceText.substring(colonIndex + 1, slashIndex).trim();
+ mResourceId = resourceText.substring(slashIndex + 1).trim();
+ String packageName = "";
+ if (colonIndex > 1) {
+ if ("android".equals(resourceText.substring(1, colonIndex).trim())) {
+ packageName = "android.";
+ } else {
+ packageName = "";
+ }
+ }
+ mPackage = packageName;
+ }
+
+ @Override
+ protected Class resolveType(ClassAnalyzer classAnalyzer) {
+ String type;
+ switch (mResourceType) {
+ case "anim":
+ type = "android.view.animation.Animation";
+ break;
+ case "animator":
+ type = "android.animation.Animator";
+ break;
+ case "bool":
+ return boolean.class;
+ case "color":
+ return int.class;
+ case "colorStateList":
+ type = "android.content.res.ColorStateList";
+ break;
+ case "dimen":
+ return float.class;
+ case "dimenOffset":
+ return int.class;
+ case "dimenSize":
+ return int.class;
+ case "drawable":
+ type = "android.graphics.drawable.Drawable";
+ break;
+ case "fraction":
+ return float.class;
+ case "id":
+ return int.class;
+ case "intArray":
+ return int[].class;
+ case "integer":
+ return int.class;
+ case "interpolator":
+ type = "";
+ break;
+ case "layout":
+ return int.class;
+ case "plurals":
+ return int.class;
+ case "stateListAnimator":
+ type = "android.animation.StateListAnimator";
+ break;
+ case "string":
+ return String.class;
+ case "stringArray":
+ return String[].class;
+ case "transition":
+ type = "android.transition.Transition";
+ break;
+ case "typedArray":
+ type = "android.content.res.TypedArray";
+ break;
+ default:
+ type = mResourceType;
+ break;
+ }
+ return classAnalyzer.findClass(type);
+ }
+
+ @Override
+ protected List<Dependency> constructDependencies() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ protected String computeUniqueKey() {
+ if (mPackage == null) {
+ return "@" + mResourceType + "/" + mResourceId;
+ } else {
+ return "@" + "android:" + mResourceType + "/" + mResourceId;
+ }
+ }
+
+ @Override
+ public boolean isDynamic() {
+ return false;
+ }
+
+ @Override
+ public boolean canBeInvalidated() {
+ return false;
+ }
+
+ public String toJava() {
+ final String context = "mRoot.getContext()";
+ final String resources = context + ".getResources()";
+ final String resourceName = mPackage + "R." + getResourceObject() + "." + mResourceId;
+ switch (mResourceType) {
+ case "anim": return "android.view.animation.AnimationUtils.loadAnimation(" + context + ", " + resourceName + ")";
+ case "animator": return "android.animation.AnimatorInflater.loadAnimator(" + context + ", " + resourceName + ")";
+ case "bool": return resources + ".getBoolean(" + resourceName + ")";
+ case "color": return resources + ".getColor(" + resourceName + ")";
+ case "colorStateList": return resources + ".getColorStateList(" + resourceName + ")";
+ case "dimen": return resources + ".getDimension(" + resourceName + ")";
+ case "dimenOffset": return resources + ".getDimensionPixelOffset(" + resourceName + ")";
+ case "dimenSize": return resources + ".getDimensionPixelSize(" + resourceName + ")";
+ case "drawable": return resources + ".getDrawable(" + resourceName + ")";
+ case "fraction": return resources + ".getFraction(" + resourceName + ", 1, 1)";
+ case "id": return resourceName;
+ case "intArray": return resources + ".getIntArray(" + resourceName + ")";
+ case "integer": return resources + ".getInteger(" + resourceName + ")";
+ case "interpolator": return "android.view.animation.AnimationUtils.loadInterpolator(" + context + ", " + resourceName + ")";
+ case "layout": return resourceName;
+ case "plurals": return resourceName;
+ case "stateListAnimator": return "android.animation.AnimatorInflater.loadStateListAnimator(" + context + ", " + resourceName + ")";
+ case "string": return resources + ".getString(" + resourceName + ")";
+ case "stringArray": return resources + ".getStringArray(" + resourceName + ")";
+ case "transition": return "android.transition.TransitionInflater.from(" + context + ").inflateTransition(" + resourceName + ")";
+ case "typedArray": return resources + ".obtainTypedArray(" + resourceName + ")";
+ }
+ final String property = Character.toUpperCase(mResourceType.charAt(0)) +
+ mResourceType.substring(1);
+ return resources + ".get" + property + "(" + resourceName + ")";
+
+ }
+
+ private String getResourceObject() {
+ String rFileObject = RESOURCE_TYPE_TO_R_OBJECT.get(mResourceType);
+ if (rFileObject == null) {
+ rFileObject = mResourceType;
+ }
+ return rFileObject;
+ }
+}
diff --git a/compiler/src/main/java/com/android/databinding/store/SetterStore.java b/compiler/src/main/java/com/android/databinding/store/SetterStore.java
index 0cab80c..b41e7e1 100644
--- a/compiler/src/main/java/com/android/databinding/store/SetterStore.java
+++ b/compiler/src/main/java/com/android/databinding/store/SetterStore.java
@@ -16,7 +16,6 @@
package com.android.databinding.store;
import com.android.databinding.ClassAnalyzer;
-import com.android.databinding.util.L;
import java.io.File;
import java.io.IOException;
@@ -318,8 +317,6 @@
public String getSetterCall(String attribute, Class<?> viewType, Class<?> valueType,
String viewExpression, String valueExpression) {
- L.d("getting setter call for %s %s %s %s %s", attribute, viewType, valueType,
- viewExpression, valueExpression);
if (!attribute.startsWith("android:")) {
int colon = attribute.indexOf(':');
if (colon >= 0) {
@@ -327,11 +324,9 @@
}
}
ArrayList<AdaptedMethod> adapters = mAdaptedMethods.get(attribute);
- L.d("returned adapter count %d", adapters == null ? -1 : adapters.size());
AdaptedMethod adapter = null;
String setterName = null;
Method bestSetterMethod = getBestSetter(viewType, valueType, attribute);
- L.d("setter method: %s", bestSetterMethod == null ? "null" : bestSetterMethod.getName());
Class<?> bestViewType = null;
Class<?> bestValueType = null;
if (bestSetterMethod != null) {
@@ -342,7 +337,6 @@
if (adapters != null) {
for (AdaptedMethod adaptedMethod : adapters) {
- L.d("checking adapter method %s", adaptedMethod);
if (adaptedMethod.viewType.isAssignableFrom(viewType)) {
boolean isBetterView = bestViewType == null ||
bestValueType.isAssignableFrom(adaptedMethod.valueType);
@@ -351,12 +345,7 @@
bestViewType = adaptedMethod.viewType;
bestValueType = adaptedMethod.valueType;
adapter = adaptedMethod;
- L.d("chosen %s", adaptedMethod);
- } else {
- L.d("not better");
}
- } else {
- L.d("not assignable");
}
}
}
@@ -469,16 +458,12 @@
}
private ConversionMethod getConversionMethod(Class<?> from, Class<?> to) {
- System.out.println("Getting conversion from " + from + " to " + to);
if (from != null && to != null) {
for (ConversionMethod conversion : mConversionMethods) {
- System.out.println("Testing " + conversion.fromType + " to " + conversion.toType);
if (canUseForConversion(from, conversion.fromType) &&
canUseForConversion(conversion.toType, to)) {
- System.out.println("Yes!");
return conversion;
}
- System.out.println("Nope!");
}
}
return null;
diff --git a/compiler/src/main/kotlin/com/android/databinding/writer/LayoutBinderWriter.kt b/compiler/src/main/kotlin/com/android/databinding/writer/LayoutBinderWriter.kt
index e72c2ae..4dfc85f 100644
--- a/compiler/src/main/kotlin/com/android/databinding/writer/LayoutBinderWriter.kt
+++ b/compiler/src/main/kotlin/com/android/databinding/writer/LayoutBinderWriter.kt
@@ -43,6 +43,7 @@
import com.android.databinding.ext.br
import com.android.databinding.ext.toJavaCode
import com.android.databinding.ext.isObservable
+import com.android.databinding.expr.ResourceExpr
fun Expr.isObservable() = com.android.databinding.ClassAnalyzer.getInstance().isObservable(this.getResolvedType())
@@ -190,6 +191,9 @@
app("?", it.getIfTrue().toCode())
app(":", it.getIfFalse().toCode())
}
+ is ResourceExpr -> kcode("") {
+ app("", it.toJava())
+ }
else -> kcode("//NOT IMPLEMENTED YET")
}
diff --git a/grammerBuilder/BindingExpression.g4 b/grammerBuilder/BindingExpression.g4
index e647895..85d7631 100644
--- a/grammerBuilder/BindingExpression.g4
+++ b/grammerBuilder/BindingExpression.g4
@@ -445,25 +445,25 @@
ResourceType
: 'anim'
| 'animator'
- | 'array'
- | 'attr'
| 'bool'
| 'color'
+ | 'colorStateList'
| 'dimen'
+ | 'dimenOffset'
+ | 'dimenSize'
| 'drawable'
| 'fraction'
| 'id'
| 'integer'
+ | 'intArray'
| 'interpolator'
| 'layout'
- | 'menu'
- | 'mipmap'
| 'plurals'
- | 'raw'
+ | 'stateListAnimator'
| 'string'
- | 'style'
+ | 'stringArray'
| 'transition'
- | 'xml'
+ | 'typedArray'
;
ResourceName
diff --git a/library/src/main/java/android/binding/adapters/ViewBindingAdapter.java b/library/src/main/java/android/binding/adapters/ViewBindingAdapter.java
index 01ec43c..7333abe 100644
--- a/library/src/main/java/android/binding/adapters/ViewBindingAdapter.java
+++ b/library/src/main/java/android/binding/adapters/ViewBindingAdapter.java
@@ -39,11 +39,6 @@
})
public class ViewBindingAdapter {
- @BindingAdapter("android:background")
- public static void setBackground(View view, int color) {
- view.setBackgroundColor(color);
- }
-
@BindingAdapter("android:padding")
public static void setPadding(View view, int padding) {
view.setPadding(padding, padding, padding, padding);