FileDocCategorySizeDatePackage
BridgeTypedArray.javaAPI DocAndroid 1.5 API26476Wed May 06 22:42:02 BST 2009com.android.layoutlib.bridge

BridgeTypedArray

public final class BridgeTypedArray extends android.content.res.TypedArray
TODO: describe.

Fields Summary
private BridgeResources
mResources
private BridgeContext
mContext
private com.android.layoutlib.api.IResourceValue[]
mData
private String[]
mNames
private final boolean
mPlatformFile
Constructors Summary
public BridgeTypedArray(BridgeResources resources, BridgeContext context, int len, boolean platformFile)

        super(null, null, null, 0);
        mResources = resources;
        mContext = context;
        mPlatformFile = platformFile;
        mData = new IResourceValue[len];
        mNames = new String[len];
    
Methods Summary
public voidbridgeSetValue(int index, java.lang.String name, com.android.layoutlib.api.IResourceValue value)
A bridge-specific method that sets a value in the type array

        mData[index] = value;
        mNames[index] = name;
    
public booleangetBoolean(int index, boolean defValue)
Retrieve the boolean value for the attribute at index.

param
index Index of attribute to retrieve.
param
defValue Value to return if the attribute is not defined.
return
Attribute boolean value, or defValue if not defined.

        if (mData[index] == null) {
            return defValue;
        }

        String s = mData[index].getValue();
        if (s != null) {
            return XmlUtils.convertValueToBoolean(s, defValue);
        }
        
        return defValue;
    
public intgetColor(int index, int defValue)
Retrieve the color value for the attribute at index. If the attribute references a color resource holding a complex {@link android.content.res.ColorStateList}, then the default color from the set is returned.

param
index Index of attribute to retrieve.
param
defValue Value to return if the attribute is not defined or not a resource.
return
Attribute color value, or defValue if not defined.

        if (mData[index] == null) {
            return defValue;
        }
        
        String s = mData[index].getValue();
        try {
            return ResourceHelper.getColor(s);
        } catch (NumberFormatException e) {
            mContext.getLogger().warning(String.format(
                    "Unable to convert \"%s\" into a color in attribute \"%2$s\"",
                    s, mNames[index]));

            // we'll return the default value below.
        }

        return defValue;
    
public android.content.res.ColorStateListgetColorStateList(int index)
Retrieve the ColorStateList for the attribute at index. The value may be either a single solid color or a reference to a color or complex {@link android.content.res.ColorStateList} description.

param
index Index of attribute to retrieve.
return
ColorStateList for the attribute, or null if not defined.

        if (mData[index] == null) {
            return null;
        }

        String value = mData[index].getValue();

        if (value == null) {
            return null;
        }
        
        try {
            int color = ResourceHelper.getColor(value);
            return ColorStateList.valueOf(color);
        } catch (NumberFormatException e) {
            // if it's not a color value, we'll attempt to read the xml based color below.
        }
        
        // let the framework inflate the ColorStateList from the XML file.
        try {
            File f = new File(value);
            if (f.isFile()) {
                KXmlParser parser = new KXmlParser();
                parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
                parser.setInput(new FileReader(f));
                
                ColorStateList colorStateList = ColorStateList.createFromXml(
                        mContext.getResources(),
                        // FIXME: we need to know if this resource is platform or not
                        new BridgeXmlBlockParser(parser, mContext, false));
                return colorStateList;
            }
        } catch (Exception e) {
            // this is an error and not warning since the file existence is checked before
            // attempting to parse it.
            mContext.getLogger().error(e);

            // return null below.
        }
        
        // looks like were unable to resolve the color value.
        mContext.getLogger().warning(String.format(
                "Unable to resolve color value \"%1$s\" in attribute \"%2$s\"",
                value, mNames[index]));
        
        return null;
    
public floatgetDimension(int index, float defValue)
Retrieve a dimensional unit attribute at index. Unit conversions are based on the current {@link DisplayMetrics} associated with the resources this {@link TypedArray} object came from.

param
index Index of attribute to retrieve.
param
defValue Value to return if the attribute is not defined or not a resource.
return
Attribute dimension value multiplied by the appropriate metric, or defValue if not defined.
see
#getDimensionPixelOffset
see
#getDimensionPixelSize

        if (mData[index] == null) {
            return defValue;
        }

        String s = mData[index].getValue();

        if (s == null) {
            return defValue;
        } else if (s.equals(BridgeConstants.FILL_PARENT)) {
            return LayoutParams.FILL_PARENT;
        } else if (s.equals(BridgeConstants.WRAP_CONTENT)) {
            return LayoutParams.WRAP_CONTENT;
        }
        
        if (ResourceHelper.stringToFloat(s, mValue)) {
            return mValue.getDimension(mResources.mMetrics);
        }
        
        // looks like we were unable to resolve the dimension value
        mContext.getLogger().warning(String.format(
                "Unable to resolve dimension value \"%1$s\" in attribute \"%2$s\"",
                s, mNames[index]));

        return defValue;
    
public intgetDimensionPixelOffset(int index, int defValue)
Retrieve a dimensional unit attribute at index for use as an offset in raw pixels. This is the same as {@link #getDimension}, except the returned value is converted to integer pixels for you. An offset conversion involves simply truncating the base value to an integer.

param
index Index of attribute to retrieve.
param
defValue Value to return if the attribute is not defined or not a resource.
return
Attribute dimension value multiplied by the appropriate metric and truncated to integer pixels, or defValue if not defined.
see
#getDimension
see
#getDimensionPixelSize

        return (int) getDimension(index, defValue);
    
public intgetDimensionPixelSize(int index, int defValue)
Retrieve a dimensional unit attribute at index for use as a size in raw pixels. This is the same as {@link #getDimension}, except the returned value is converted to integer pixels for use as a size. A size conversion involves rounding the base value, and ensuring that a non-zero base value is at least one pixel in size.

param
index Index of attribute to retrieve.
param
defValue Value to return if the attribute is not defined or not a resource.
return
Attribute dimension value multiplied by the appropriate metric and truncated to integer pixels, or defValue if not defined.
see
#getDimension
see
#getDimensionPixelOffset

        if (mData[index] == null) {
            return defValue;
        }

        String s = mData[index].getValue();

        if (s == null) {
            return defValue;
        } else if (s.equals(BridgeConstants.FILL_PARENT)) {
            return LayoutParams.FILL_PARENT;
        } else if (s.equals(BridgeConstants.WRAP_CONTENT)) {
            return LayoutParams.WRAP_CONTENT;
        }
        
        // FIXME huh?

        float f = getDimension(index, defValue);
        final int res = (int)(f+0.5f);
        if (res != 0) return res;
        if (f == 0) return 0;
        if (f > 0) return 1;

        throw new UnsupportedOperationException("Can't convert to dimension: " +
                Integer.toString(index));
    
public android.graphics.drawable.DrawablegetDrawable(int index)
Retrieve the Drawable for the attribute at index. This gets the resource ID of the selected attribute, and uses {@link Resources#getDrawable Resources.getDrawable} of the owning Resources object to retrieve its Drawable.

param
index Index of attribute to retrieve.
return
Drawable for the attribute, or null if not defined.

        if (mData[index] == null) {
            return null;
        }

        String value = mData[index].getValue();
        if (value == null || BridgeConstants.REFERENCE_NULL.equals(value)) {
            return null;
        }
        
        Drawable d = ResourceHelper.getDrawable(value, mContext, mData[index].isFramework());
        
        if (d != null) {
            return d;
        }
        
        // looks like we were unable to resolve the drawable
        mContext.getLogger().warning(String.format(
                "Unable to resolve drawable \"%1$s\" in attribute \"%2$s\"", value, mNames[index]));

        return null;
    
public floatgetFloat(int index, float defValue)
Retrieve the float value for the attribute at index.

param
index Index of attribute to retrieve.
return
Attribute float value, or defValue if not defined..

        if (mData[index] == null) {
            return defValue;
        }

        String s = mData[index].getValue();

        if (s != null) {
            try {
                return Float.parseFloat(s);
            } catch (NumberFormatException e) {
                mContext.getLogger().warning(String.format(
                        "Unable to convert \"%s\" into a float in attribute \"%2$s\"",
                        s, mNames[index]));
                
                // we'll return the default value below.
            }
        }
        return defValue;
    
public floatgetFraction(int index, int base, int pbase, float defValue)
Retrieve a fractional unit attribute at index.

param
index Index of attribute to retrieve.
param
base The base value of this fraction. In other words, a standard fraction is multiplied by this value.
param
pbase The parent base value of this fraction. In other words, a parent fraction (nn%p) is multiplied by this value.
param
defValue Value to return if the attribute is not defined or not a resource.
return
Attribute fractional value multiplied by the appropriate base value, or defValue if not defined.

        if (mData[index] == null) {
            return defValue;
        }

        String value = mData[index].getValue();
        if (value == null) {
            return defValue;
        }
        
        if (ResourceHelper.stringToFloat(value, mValue)) {
            return mValue.getFraction(base, pbase);
        }

        // looks like we were unable to resolve the fraction value
        mContext.getLogger().warning(String.format(
                "Unable to resolve fraction value \"%1$s\" in attribute \"%2$s\"",
                value, mNames[index]));
        
        return defValue;
    
public intgetInt(int index, int defValue)
Retrieve the integer value for the attribute at index.

param
index Index of attribute to retrieve.
param
defValue Value to return if the attribute is not defined.
return
Attribute int value, or defValue if not defined.

        if (mData[index] == null) {
            return defValue;
        }

        String s = mData[index].getValue();
        
        try {
            return (s == null) ? defValue : 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.
        // Get the map of attribute-constant -> IntegerValue
        Map<String, Integer> map = Bridge.getEnumValues(mNames[index]);
        
        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 = s.split("\\|");
            for (String keyword : keywords) {
                Integer i = map.get(keyword.trim());
                if (i != null) {
                    result |= i.intValue();
                } else {
                    mContext.getLogger().warning(String.format(
                            "Unknown constant \"%s\" in attribute \"%2$s\"",
                            keyword, mNames[index]));
                }
            }
            return result;
        }

        return defValue;
    
public intgetInteger(int index, int defValue)
Retrieve the integer value for the attribute at index.

param
index Index of attribute to retrieve.
param
defValue Value to return if the attribute is not defined or not a resource.
return
Attribute integer value, or defValue if not defined.

        if (mData[index] == null) {
            return defValue;
        }

        String s = mData[index].getValue();

        if (s != null) {
            try {
                return Integer.parseInt(s);
            } catch (NumberFormatException e) {
                mContext.getLogger().warning(String.format(
                        "Unable to convert \"%s\" into a integer in attribute \"%2$s\"",
                        s, mNames[index]));

                // The default value is returned below.
            }
        }
        
        return defValue;
    
public intgetLayoutDimension(int index, java.lang.String name)
Special version of {@link #getDimensionPixelSize} for retrieving {@link android.view.ViewGroup}'s layout_width and layout_height attributes. This is only here for performance reasons; applications should use {@link #getDimensionPixelSize}.

param
index Index of the attribute to retrieve.
param
name Textual name of attribute for error reporting.
return
Attribute dimension value multiplied by the appropriate metric and truncated to integer pixels.

        return getDimensionPixelSize(index, 0);
    
public java.lang.StringgetPositionDescription()
Returns a message about the parser state suitable for printing error messages.

        return "<internal -- stub if needed>";
    
public intgetResourceId(int index, int defValue)
Retrieve the resource identifier for the attribute at index. Note that attribute resource as resolved when the overall {@link TypedArray} object is retrieved. As a result, this function will return the resource identifier of the final resource value that was found, not necessarily the original resource that was specified by the attribute.

param
index Index of attribute to retrieve.
param
defValue Value to return if the attribute is not defined or not a resource.
return
Attribute resource identifier, or defValue if not defined.

        // get the IResource for this index
        IResourceValue resValue = mData[index];
        
        // no data, return the default value.
        if (resValue == null) {
            return defValue;
        }

        // check if this is a style resource
        if (resValue instanceof IStyleResourceValue) {
            // get the id that will represent this style.
            return mContext.getDynamicIdByStyle((IStyleResourceValue)resValue);
        }
        
        // if the attribute was a reference to an id, and not a declaration of an id (@+id), then
        // the xml attribute value was "resolved" which leads us to a IResourceValue with
        // getType() returning "id" and getName() returning the id name
        // (and getValue() returning null!). We need to handle this!
        if (resValue.getType() != null && resValue.getType().equals(BridgeConstants.RES_ID)) {
            // if this is a framework id
            if (mPlatformFile || resValue.isFramework()) {
                // look for idName in the android R classes
                return mContext.getFrameworkIdValue(resValue.getName(), defValue);
            }

            // look for idName in the project R class.
            return mContext.getProjectIdValue(resValue.getName(), defValue);
        }

        // else, try to get the value, and resolve it somehow.
        String value = resValue.getValue();
        if (value == null) {
            return defValue;
        }
        
        // if the value is just an integer, return it.
        try {
            int i = Integer.parseInt(value);
            if (Integer.toString(i).equals(value)) {
                return i;
            }
        } catch (NumberFormatException e) {
            // pass
        }

        // Handle the @id/<name>, @+id/<name> and @android:id/<name>
        // We need to return the exact value that was compiled (from the various R classes),
        // as these values can be reused internally with calls to findViewById().
        // There's a trick with platform layouts that not use "android:" but their IDs are in
        // fact in the android.R and com.android.internal.R classes.
        // The field mPlatformFile will indicate that all IDs are to be looked up in the android R
        // classes exclusively.
        
        // if this is a reference to an id, find it.
        if (value.startsWith("@id/") || value.startsWith("@+") ||
                value.startsWith("@android:id/")) {
            
            int pos = value.indexOf('/");
            String idName = value.substring(pos + 1);
            
            // if this is a framework id
            if (mPlatformFile || value.startsWith("@android") || value.startsWith("@+android")) {
                // look for idName in the android R classes
                return mContext.getFrameworkIdValue(idName, defValue);
            }

            // look for idName in the project R class.
            return mContext.getProjectIdValue(idName, defValue);
        }

        // not a direct id valid reference? resolve it
        Integer idValue = null;
        
        if (resValue.isFramework()) {
            idValue = Bridge.getResourceValue(resValue.getType(), resValue.getName());
        } else {
            idValue = mContext.getProjectCallback().getResourceValue(
                    resValue.getType(), resValue.getName());
        }

        if (idValue != null) {
            return idValue.intValue();
        }
        
        mContext.getLogger().warning(String.format(
                "Unable to resolve id \"%1$s\" for attribute \"%2$s\"", value, mNames[index]));
        return defValue;
    
public android.content.res.ResourcesgetResources()
Return the Resources object this array was loaded from.

        return mResources;
    
public java.lang.StringgetString(int index)
Retrieve the string value for the attribute at index.

param
index Index of attribute to retrieve.
return
String holding string data. Any styling information is removed. Returns null if the attribute is not defined.

        if (mData[index] != null) {
            return mData[index].getValue();
        }
        
        return null;
    
public java.lang.CharSequencegetText(int index)
Retrieve the styled string value for the attribute at index.

param
index Index of attribute to retrieve.
return
CharSequence holding string data. May be styled. Returns null if the attribute is not defined.

        if (mData[index] != null) {
            // FIXME: handle styled strings!
            return mData[index].getValue();
        }

        return null;
    
public java.lang.CharSequence[]getTextArray(int index)
Retrieve the CharSequence[] for the attribute at index. This gets the resource ID of the selected attribute, and uses {@link Resources#getTextArray Resources.getTextArray} of the owning Resources object to retrieve its String[].

param
index Index of attribute to retrieve.
return
CharSequence[] for the attribute, or null if not defined.

        if (mData[index] == null) {
            return null;
        }

        String value = mData[index].getValue();
        if (value != null) {
            return new CharSequence[] { value };
        }
        
        mContext.getLogger().warning(String.format(
                String.format("Unknown value for getTextArray(%d) => %s", //DEBUG
                index, mData[index].getName())));

        return null;
    
public booleangetValue(int index, android.util.TypedValue outValue)
Retrieve the raw TypedValue for the attribute at index.

param
index Index of attribute to retrieve.
param
outValue TypedValue object in which to place the attribute's data.
return
Returns true if the value was retrieved, else false.

        if (mData[index] == null) {
            return false;
        }
        
        String s = mData[index].getValue();
        
        return ResourceHelper.stringToFloat(s, outValue);
    
public booleangetValueAt(int index, android.util.TypedValue outValue)

        // pass
        return false;
    
public booleanhasValue(int index)
Determines whether there is an attribute at index.

param
index Index of attribute to retrieve.
return
True if the attribute has a value, false otherwise.

        return mData[index] != null;
    
public intlength()
Return the number of values in this array.

        return mData.length;
    
public android.util.TypedValuepeekValue(int index)
Retrieve the raw TypedValue for the attribute at index and return a temporary object holding its data. This object is only valid until the next call on to {@link TypedArray}.

param
index Index of attribute to retrieve.
return
Returns a TypedValue object if the attribute is defined, containing its data; otherwise returns null. (You will not receive a TypedValue whose type is TYPE_NULL.)

        if (getValue(index, mValue)) {
            return mValue;
        }
        
        return null;
    
public voidrecycle()
Give back a previously retrieved StyledAttributes, for later re-use.

        // pass
    
public voidsealArray()
Seals the array after all calls to {@link #bridgeSetValue(int, String, IResourceValue)} have been done.

This allows to compute the list of non default values, permitting {@link #getIndexCount()} to return the proper value.

        // fills TypedArray.mIndices which is used to implement getIndexCount/getIndexAt
        // first count the array size
        int count = 0;
        for (IResourceValue data : mData) {
            if (data != null) {
                count++;
            }
        }
        
        // allocate the table with an extra to store the size
        mIndices = new int[count+1];
        mIndices[0] = count;
        
        // fill the array with the indices.
        int index = 1;
        for (int i = 0 ; i < mData.length ; i++) {
            if (mData[i] != null) {
                mIndices[index++] = i;
            }
        }
    
public java.lang.StringtoString()

        return mData.toString();