OSDN Git Service

Always resolve enum when resolving resources.
authorDeepanshu Gupta <deepanshu@google.com>
Mon, 29 Sep 2014 16:32:42 +0000 (09:32 -0700)
committerDeepanshu Gupta <deepanshu@google.com>
Mon, 29 Sep 2014 19:01:37 +0000 (12:01 -0700)
Enums were resolved only for integers and dimensions. This change
resolves enums for all resource types. Well, almost all. For color and
colorStateList, enums are still not referenced.

Bug: http://b.android.com/76091
Change-Id: Ie43bd1b54fb9877655d31773bdf71d9a6a65c473

tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java

index aaba545..4a6a434 100644 (file)
@@ -23,7 +23,6 @@ import com.android.ide.common.rendering.api.ResourceValue;
 import com.android.ide.common.rendering.api.StyleResourceValue;
 import com.android.internal.util.XmlUtils;
 import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.BridgeConstants;
 import com.android.layoutlib.bridge.android.BridgeContext;
 import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
 import com.android.layoutlib.bridge.impl.ParserFactory;
@@ -142,16 +141,8 @@ public final class BridgeTypedArray extends TypedArray {
      */
     @Override
     public CharSequence getText(int index) {
-        if (index < 0 || index >= mResourceData.length) {
-            return null;
-        }
-
-        if (mResourceData[index] != null) {
-            // FIXME: handle styled strings!
-            return mResourceData[index].getValue();
-        }
-
-        return null;
+        // FIXME: handle styled strings!
+        return getString(index);
     }
 
     /**
@@ -164,15 +155,14 @@ public final class BridgeTypedArray extends TypedArray {
      */
     @Override
     public String getString(int index) {
-        if (index < 0 || index >= mResourceData.length) {
+        if (!hasValue(index)) {
             return null;
         }
-
-        if (mResourceData[index] != null) {
-            return mResourceData[index].getValue();
-        }
-
-        return null;
+        // As unfortunate as it is, it's possible to use enums with all attribute formats,
+        // not just integers/enums. So, we need to search the enums always. In case,
+        // enums are used, the returned value is an integer.
+        Integer v = resolveEnumAttribute(index);
+        return v == null ? mResourceData[index].getValue() : String.valueOf((int) v);
     }
 
     /**
@@ -185,20 +175,9 @@ public final class BridgeTypedArray extends TypedArray {
      */
     @Override
     public boolean getBoolean(int index, boolean defValue) {
-        if (index < 0 || index >= mResourceData.length) {
-            return defValue;
-        }
-
-        if (mResourceData[index] == null) {
-            return defValue;
-        }
+        String s = getString(index);
+        return s == null ? defValue : XmlUtils.convertValueToBoolean(s, defValue);
 
-        String s = mResourceData[index].getValue();
-        if (s != null) {
-            return XmlUtils.convertValueToBoolean(s, defValue);
-        }
-
-        return defValue;
     }
 
     /**
@@ -211,75 +190,18 @@ public final class BridgeTypedArray extends TypedArray {
      */
     @Override
     public int getInt(int index, int defValue) {
-        if (index < 0 || index >= mResourceData.length) {
-            return defValue;
-        }
-
-        if (mResourceData[index] == null) {
-            return defValue;
-        }
-
-        String s = mResourceData[index].getValue();
-
-        if (s == null || s.length() == 0) {
-            return defValue;
-        }
-
+        String s = getString(index);
         try {
-            return XmlUtils.convertValueToInt(s, defValue);
-        } catch (NumberFormatException e) {
-            // pass
-        }
-
-        // Field is not null and is not an integer.
-        // Check for possible constants and try to find them.
-        return (int) resolveEnumAttribute(index, defValue);
-    }
-
-    /**
-     * Searches for the string in the attributes (flag or enums) and returns the integer.
-     * If found, it will return an integer matching the value. However, if the value is not found,
-     * it returns {@code defValue} which may be a float.
-     *
-     * @param index Index of attribute to retrieve.
-     * @param defValue Value to return if the attribute is not found.
-     *
-     * @return Attribute int value, or defValue if not defined.
-     */
-    private float resolveEnumAttribute(int index, float defValue) {
-        // Get the map of attribute-constant -> IntegerValue
-        Map<String, Integer> map = null;
-        if (mIsFramework[index]) {
-            map = Bridge.getEnumValues(mNames[index]);
-        } else {
-            // get the styleable matching the resolved name
-            RenderResources res = mContext.getRenderResources();
-            ResourceValue attr = res.getProjectResource(ResourceType.ATTR, mNames[index]);
-            if (attr instanceof AttrResourceValue) {
-                map = ((AttrResourceValue) attr).getAttributeValues();
+            if (s != null) {
+                return XmlUtils.convertValueToInt(s, defValue);
             }
+        } catch (NumberFormatException e) {
+            Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
+                    String.format("\"%s\" in attribute \"%2$s\" is not a valid integer",
+                            s, mNames[index]),
+                    null);
+            return defValue;
         }
-
-        if (map != null) {
-            // accumulator to store the value of the 1+ constants.
-            int result = 0;
-
-            // split the value in case this is a mix of several flags.
-            String[] keywords = mResourceData[index].getValue().split("\\|");
-            for (String keyword : keywords) {
-                Integer i = map.get(keyword.trim());
-                if (i != null) {
-                    result |= i;
-                } else {
-                    Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
-                            String.format(
-                                "\"%s\" in attribute \"%2$s\" is not a valid value",
-                                keyword, mNames[index]), null);
-                }
-            }
-            return result;
-        }
-
         return defValue;
     }
 
@@ -292,27 +214,16 @@ public final class BridgeTypedArray extends TypedArray {
      */
     @Override
     public float getFloat(int index, float defValue) {
-        if (index < 0 || index >= mResourceData.length) {
-            return defValue;
-        }
-
-        if (mResourceData[index] == null) {
-            return defValue;
-        }
-
-        String s = mResourceData[index].getValue();
-
-        if (s != null) {
-            try {
-                return Float.parseFloat(s);
-            } catch (NumberFormatException e) {
-                Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
-                        String.format(
-                            "\"%s\" in attribute \"%2$s\" cannot be converted to float.",
-                            s, mNames[index]), null);
-
-                // we'll return the default value below.
+        String s = getString(index);
+        try {
+            if (s != null) {
+                    return Float.parseFloat(s);
             }
+        } catch (NumberFormatException e) {
+            Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
+                    String.format("\"%s\" in attribute \"%2$s\" cannot be converted to float.",
+                            s, mNames[index]),
+                    null);
         }
         return defValue;
     }
@@ -359,11 +270,7 @@ public final class BridgeTypedArray extends TypedArray {
      */
     @Override
     public ColorStateList getColorStateList(int index) {
-        if (index < 0 || index >= mResourceData.length) {
-            return null;
-        }
-
-        if (mResourceData[index] == null) {
+        if (!hasValue(index)) {
             return null;
         }
 
@@ -443,27 +350,25 @@ public final class BridgeTypedArray extends TypedArray {
      */
     @Override
     public float getDimension(int index, float defValue) {
-        if (index < 0 || index >= mResourceData.length) {
-            return defValue;
-        }
-
-        if (mResourceData[index] == null) {
-            return defValue;
-        }
-
-        String s = mResourceData[index].getValue();
-
+        String s = getString(index);
         if (s == null) {
             return defValue;
         }
+        // Check if the value is a magic constant that doesn't require a unit.
+        try {
+            int i = Integer.parseInt(s);
+            if (i == LayoutParams.MATCH_PARENT || i == LayoutParams.WRAP_CONTENT) {
+                return i;
+            }
+        } catch (NumberFormatException ignored) {
+            // pass
+        }
 
         if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true)) {
             return mValue.getDimension(mBridgeResources.getDisplayMetrics());
         }
 
-        // looks like we were unable to resolve the dimension value. Check if it is an attribute
-        // constant.
-        return resolveEnumAttribute(index, defValue);
+        return defValue;
     }
 
     /**
@@ -511,16 +416,13 @@ public final class BridgeTypedArray extends TypedArray {
         try {
             return getDimension(index);
         } catch (RuntimeException e) {
-            if (mResourceData[index] != null) {
-                String s = mResourceData[index].getValue();
-
-                if (s != null) {
-                    // looks like we were unable to resolve the dimension value
-                    Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
-                            String.format(
-                                "\"%1$s\" in attribute \"%2$s\" is not a valid format.",
+            String s = getString(index);
+
+            if (s != null) {
+                // looks like we were unable to resolve the dimension value
+                Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
+                        String.format("\"%1$s\" in attribute \"%2$s\" is not a valid format.",
                                 s, mNames[index]), null);
-                }
             }
 
             return defValue;
@@ -563,21 +465,19 @@ public final class BridgeTypedArray extends TypedArray {
     }
 
     private int getDimension(int index) {
-        if (mResourceData[index] == null) {
-            throw new RuntimeException();
-        }
-
-        String s = mResourceData[index].getValue();
-
+        String s = getString(index);
         if (s == null) {
             throw new RuntimeException();
-        } else if (s.equals(BridgeConstants.MATCH_PARENT) ||
-                s.equals(BridgeConstants.FILL_PARENT)) {
-            return LayoutParams.MATCH_PARENT;
-        } else if (s.equals(BridgeConstants.WRAP_CONTENT)) {
-            return LayoutParams.WRAP_CONTENT;
         }
-
+        // Check if the value is a magic constant that doesn't require a unit.
+        try {
+            int i = Integer.parseInt(s);
+            if (i == LayoutParams.MATCH_PARENT || i == LayoutParams.WRAP_CONTENT) {
+                return i;
+            }
+        } catch (NumberFormatException ignored) {
+            // pass
+        }
         if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true)) {
             float f = mValue.getDimension(mBridgeResources.getDisplayMetrics());
 
@@ -607,15 +507,7 @@ public final class BridgeTypedArray extends TypedArray {
      */
     @Override
     public float getFraction(int index, int base, int pbase, float defValue) {
-        if (index < 0 || index >= mResourceData.length) {
-            return defValue;
-        }
-
-        if (mResourceData[index] == null) {
-            return defValue;
-        }
-
-        String value = mResourceData[index].getValue();
+        String value = getString(index);
         if (value == null) {
             return defValue;
         }
@@ -766,20 +658,11 @@ public final class BridgeTypedArray extends TypedArray {
      */
     @Override
     public Drawable getDrawable(int index) {
-        if (index < 0 || index >= mResourceData.length) {
-            return null;
-        }
-
-        if (mResourceData[index] == null) {
+        if (!hasValue(index)) {
             return null;
         }
 
         ResourceValue value = mResourceData[index];
-        String stringValue = value.getValue();
-        if (stringValue == null) {
-            return null;
-        }
-
         return ResourceHelper.getDrawable(value, mContext);
     }
 
@@ -796,15 +679,7 @@ public final class BridgeTypedArray extends TypedArray {
      */
     @Override
     public CharSequence[] getTextArray(int index) {
-        if (index < 0 || index >= mResourceData.length) {
-            return null;
-        }
-
-        if (mResourceData[index] == null) {
-            return null;
-        }
-
-        String value = mResourceData[index].getValue();
+        String value = getString(index);
         if (value != null) {
             return new CharSequence[] { value };
         }
@@ -837,17 +712,8 @@ public final class BridgeTypedArray extends TypedArray {
      */
     @Override
     public boolean getValue(int index, TypedValue outValue) {
-        if (index < 0 || index >= mResourceData.length) {
-            return false;
-        }
-
-        if (mResourceData[index] == null) {
-            return false;
-        }
-
-        String s = mResourceData[index].getValue();
-
-        return ResourceHelper.parseFloatAttribute(mNames[index], s, outValue, false);
+        String s = getString(index);
+        return s != null && ResourceHelper.parseFloatAttribute(mNames[index], s, outValue, false);
     }
 
     /**
@@ -859,12 +725,7 @@ public final class BridgeTypedArray extends TypedArray {
      */
     @Override
     public boolean hasValue(int index) {
-        //noinspection SimplifiableIfStatement
-        if (index < 0 || index >= mResourceData.length) {
-            return false;
-        }
-
-        return mResourceData[index] != null;
+        return index >= 0 && index < mResourceData.length && mResourceData[index] != null;
     }
 
     /**
@@ -912,6 +773,52 @@ public final class BridgeTypedArray extends TypedArray {
         return Arrays.toString(mResourceData);
     }
 
+    /**
+     * Searches for the string in the attributes (flag or enums) and returns the integer.
+     * If found, it will return an integer matching the value.
+     *
+     * @param index Index of attribute to retrieve.
+     *
+     * @return Attribute int value, or null if not defined.
+     */
+    private Integer resolveEnumAttribute(int index) {
+        // Get the map of attribute-constant -> IntegerValue
+        Map<String, Integer> map = null;
+        if (mIsFramework[index]) {
+            map = Bridge.getEnumValues(mNames[index]);
+        } else {
+            // get the styleable matching the resolved name
+            RenderResources res = mContext.getRenderResources();
+            ResourceValue attr = res.getProjectResource(ResourceType.ATTR, mNames[index]);
+            if (attr instanceof AttrResourceValue) {
+                map = ((AttrResourceValue) attr).getAttributeValues();
+            }
+        }
+
+        if (map != null) {
+            // accumulator to store the value of the 1+ constants.
+            int result = 0;
+            boolean found = false;
+
+            // split the value in case this is a mix of several flags.
+            String[] keywords = mResourceData[index].getValue().split("\\|");
+            for (String keyword : keywords) {
+                Integer i = map.get(keyword.trim());
+                if (i != null) {
+                    result |= i;
+                    found = true;
+                }
+                // TODO: We should act smartly and log a warning for incorrect keywords. However,
+                // this method is currently called even if the resourceValue is not an enum.
+            }
+            if (found) {
+                return result;
+            }
+        }
+
+        return null;
+    }
+
     static TypedArray obtain(Resources res, int len) {
         return res instanceof BridgeResources ?
                 new BridgeTypedArray(((BridgeResources) res), null, len, true) : null;
index 99ae7c9..22f8e1c 100644 (file)
@@ -16,6 +16,7 @@
 
 package com.android.layoutlib.bridge.impl;
 
+import com.android.annotations.NonNull;
 import com.android.ide.common.rendering.api.DensityBasedResourceValue;
 import com.android.ide.common.rendering.api.LayoutLog;
 import com.android.ide.common.rendering.api.RenderResources;
@@ -358,7 +359,7 @@ public final class ResourceHelper {
      * @param requireUnit whether the value is expected to contain a unit.
      * @return true if success.
      */
-    public static boolean parseFloatAttribute(String attribute, String value,
+    public static boolean parseFloatAttribute(String attribute, @NonNull String value,
             TypedValue outValue, boolean requireUnit) {
         assert !requireUnit || attribute != null;