Loading tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java +108 −201 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; return getString(index); } /** Loading @@ -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); } /** Loading @@ -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; } /** Loading @@ -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 { if (s != null) { 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 (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 { } catch (NumberFormatException e) { 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; String.format("\"%s\" in attribute \"%2$s\" is not a valid integer", s, mNames[index]), null); return defValue; } return defValue; } Loading @@ -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) { 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); // we'll return the default value below. } String.format("\"%s\" in attribute \"%2$s\" cannot be converted to float.", s, mNames[index]), null); } return defValue; } Loading Loading @@ -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; } Loading Loading @@ -443,27 +350,25 @@ public final class BridgeTypedArray extends TypedArray { */ @Override public float getDimension(int index, float defValue) { if (index < 0 || index >= mResourceData.length) { String s = getString(index); if (s == null) { return defValue; } if (mResourceData[index] == 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; } String s = mResourceData[index].getValue(); if (s == null) { return defValue; } 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; } /** Loading Loading @@ -511,17 +416,14 @@ public final class BridgeTypedArray extends TypedArray { try { return getDimension(index); } catch (RuntimeException e) { if (mResourceData[index] != null) { String s = mResourceData[index].getValue(); 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.", String.format("\"%1$s\" in attribute \"%2$s\" is not a valid format.", s, mNames[index]), null); } } return defValue; } Loading Loading @@ -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()); Loading Loading @@ -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; } Loading Loading @@ -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); } Loading @@ -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 }; } Loading Loading @@ -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); } /** Loading @@ -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; } /** Loading Loading @@ -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; Loading tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java +2 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading
tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java +108 −201 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; return getString(index); } /** Loading @@ -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); } /** Loading @@ -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; } /** Loading @@ -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 { if (s != null) { 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 (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 { } catch (NumberFormatException e) { 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; String.format("\"%s\" in attribute \"%2$s\" is not a valid integer", s, mNames[index]), null); return defValue; } return defValue; } Loading @@ -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) { 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); // we'll return the default value below. } String.format("\"%s\" in attribute \"%2$s\" cannot be converted to float.", s, mNames[index]), null); } return defValue; } Loading Loading @@ -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; } Loading Loading @@ -443,27 +350,25 @@ public final class BridgeTypedArray extends TypedArray { */ @Override public float getDimension(int index, float defValue) { if (index < 0 || index >= mResourceData.length) { String s = getString(index); if (s == null) { return defValue; } if (mResourceData[index] == 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; } String s = mResourceData[index].getValue(); if (s == null) { return defValue; } 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; } /** Loading Loading @@ -511,17 +416,14 @@ public final class BridgeTypedArray extends TypedArray { try { return getDimension(index); } catch (RuntimeException e) { if (mResourceData[index] != null) { String s = mResourceData[index].getValue(); 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.", String.format("\"%1$s\" in attribute \"%2$s\" is not a valid format.", s, mNames[index]), null); } } return defValue; } Loading Loading @@ -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()); Loading Loading @@ -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; } Loading Loading @@ -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); } Loading @@ -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 }; } Loading Loading @@ -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); } /** Loading @@ -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; } /** Loading Loading @@ -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; Loading
tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java +2 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading