1ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski/*
2ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Copyright (C) 2008 The Android Open Source Project
3ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
4ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
5ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * you may not use this file except in compliance with the License.
6ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * You may obtain a copy of the License at
7ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
8ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
9ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
10ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Unless required by applicable law or agreed to in writing, software
11ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
12ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * See the License for the specific language governing permissions and
14ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * limitations under the License.
15ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski */
16ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
17ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskipackage android.content.res;
18ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1937e93696222aed44026f6423dd05ebc7c3c72b71Deepanshu Guptaimport com.android.ide.common.rendering.api.ArrayResourceValue;
20ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.ide.common.rendering.api.AttrResourceValue;
21ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.ide.common.rendering.api.LayoutLog;
22ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.ide.common.rendering.api.RenderResources;
23ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.ide.common.rendering.api.ResourceValue;
24ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.ide.common.rendering.api.StyleResourceValue;
25ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.internal.util.XmlUtils;
26ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.layoutlib.bridge.Bridge;
27ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.layoutlib.bridge.android.BridgeContext;
28ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.layoutlib.bridge.impl.ResourceHelper;
29ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.resources.ResourceType;
30ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
31442aee6bc1abfb143dcfa1ba60d696e576d066c4Deepanshu Guptaimport android.annotation.Nullable;
32ca617d8a82e46474f597fe9a9b13bf0abc89f0baDeepanshu Guptaimport android.content.res.Resources.Theme;
337c22a707de1ed939ebd91079dff9df6cd5ffd401Diego Perezimport android.graphics.Typeface;
34ef221c3b4f85123ac1ba21b46e36545c91508edaDiego Perezimport android.graphics.Typeface_Accessor;
35ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport android.graphics.drawable.Drawable;
36ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport android.util.DisplayMetrics;
37ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport android.util.TypedValue;
38ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport android.view.LayoutInflater_Delegate;
39ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport android.view.ViewGroup.LayoutParams;
40ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
416f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Guptaimport java.util.ArrayList;
42ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.util.Arrays;
43ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.util.Map;
44ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
451756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Guptaimport static android.util.TypedValue.TYPE_ATTRIBUTE;
461756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Guptaimport static android.util.TypedValue.TYPE_DIMENSION;
471756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Guptaimport static android.util.TypedValue.TYPE_FLOAT;
481756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Guptaimport static android.util.TypedValue.TYPE_INT_BOOLEAN;
491756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Guptaimport static android.util.TypedValue.TYPE_INT_COLOR_ARGB4;
501756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Guptaimport static android.util.TypedValue.TYPE_INT_COLOR_ARGB8;
511756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Guptaimport static android.util.TypedValue.TYPE_INT_COLOR_RGB4;
521756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Guptaimport static android.util.TypedValue.TYPE_INT_COLOR_RGB8;
531756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Guptaimport static android.util.TypedValue.TYPE_INT_DEC;
541756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Guptaimport static android.util.TypedValue.TYPE_INT_HEX;
551756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Guptaimport static android.util.TypedValue.TYPE_NULL;
561756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Guptaimport static android.util.TypedValue.TYPE_REFERENCE;
571756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Guptaimport static android.util.TypedValue.TYPE_STRING;
581756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Guptaimport static com.android.SdkConstants.PREFIX_RESOURCE_REF;
591756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Guptaimport static com.android.SdkConstants.PREFIX_THEME_REF;
601756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Guptaimport static com.android.ide.common.rendering.api.RenderResources.REFERENCE_EMPTY;
611756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Guptaimport static com.android.ide.common.rendering.api.RenderResources.REFERENCE_NULL;
621756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Guptaimport static com.android.ide.common.rendering.api.RenderResources.REFERENCE_UNDEFINED;
636f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta
64ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski/**
65ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Custom implementation of TypedArray to handle non compiled resources.
66ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski */
67ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskipublic final class BridgeTypedArray extends TypedArray {
68ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
69896eb1c37f6a44d65d3a459891475e99170b657cDeepanshu Gupta    private final Resources mBridgeResources;
70ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final BridgeContext mContext;
71ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final boolean mPlatformFile;
72ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
73bc876628ee6b96164b91908ff62fcaefe930f403Charlie Tsai    private final int[] mResourceId;
7428948de70d6f77f80b475926c2b88f55e1365ff4Deepanshu Gupta    private final ResourceValue[] mResourceData;
7528948de70d6f77f80b475926c2b88f55e1365ff4Deepanshu Gupta    private final String[] mNames;
7628948de70d6f77f80b475926c2b88f55e1365ff4Deepanshu Gupta    private final boolean[] mIsFramework;
77ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
786f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta    // Contains ids that are @empty. We still store null in mResourceData for that index, since we
796f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta    // want to save on the check against empty, each time a resource value is requested.
806f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta    @Nullable
816f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta    private int[] mEmptyIds;
826f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta
83896eb1c37f6a44d65d3a459891475e99170b657cDeepanshu Gupta    public BridgeTypedArray(Resources resources, BridgeContext context, int len,
84ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            boolean platformFile) {
85a73a0143fefc62be1ef270db0363272cb4e1864dJohn Reck        super(resources);
86ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mBridgeResources = resources;
87ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mContext = context;
88ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mPlatformFile = platformFile;
89bc876628ee6b96164b91908ff62fcaefe930f403Charlie Tsai        mResourceId = new int[len];
90ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mResourceData = new ResourceValue[len];
91ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mNames = new String[len];
92ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mIsFramework = new boolean[len];
93ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
94ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
95ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
96ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * A bridge-specific method that sets a value in the type array
97ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param index the index of the value in the TypedArray
98ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param name the name of the attribute
99ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param isFramework whether the attribute is in the android namespace.
100bc876628ee6b96164b91908ff62fcaefe930f403Charlie Tsai     * @param resourceId the reference id of this resource
101ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param value the value of the attribute
102ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
103bc876628ee6b96164b91908ff62fcaefe930f403Charlie Tsai    public void bridgeSetValue(int index, String name, boolean isFramework, int resourceId,
104bc876628ee6b96164b91908ff62fcaefe930f403Charlie Tsai            ResourceValue value) {
105bc876628ee6b96164b91908ff62fcaefe930f403Charlie Tsai        mResourceId[index] = resourceId;
106ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mResourceData[index] = value;
107ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mNames[index] = name;
108ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mIsFramework[index] = isFramework;
109ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
110ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
111ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
11228948de70d6f77f80b475926c2b88f55e1365ff4Deepanshu Gupta     * Seals the array after all calls to
113bc876628ee6b96164b91908ff62fcaefe930f403Charlie Tsai     * {@link #bridgeSetValue(int, String, boolean, int, ResourceValue)} have been done.
114ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * <p/>This allows to compute the list of non default values, permitting
115ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * {@link #getIndexCount()} to return the proper value.
116ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
117ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void sealArray() {
118ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // fills TypedArray.mIndices which is used to implement getIndexCount/getIndexAt
119ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // first count the array size
120ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int count = 0;
1216f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta        ArrayList<Integer> emptyIds = null;
122d0cf227ef57e88fa9e104ea1dd2f7fa0555adbddDeepanshu Gupta        for (int i = 0; i < mResourceData.length; i++) {
123d0cf227ef57e88fa9e104ea1dd2f7fa0555adbddDeepanshu Gupta            ResourceValue data = mResourceData[i];
124d0cf227ef57e88fa9e104ea1dd2f7fa0555adbddDeepanshu Gupta            if (data != null) {
1256f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta                String dataValue = data.getValue();
1266f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta                if (REFERENCE_NULL.equals(dataValue) || REFERENCE_UNDEFINED.equals(dataValue)) {
1276f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta                    mResourceData[i] = null;
1286f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta                } else if (REFERENCE_EMPTY.equals(dataValue)) {
129d0cf227ef57e88fa9e104ea1dd2f7fa0555adbddDeepanshu Gupta                    mResourceData[i] = null;
1306f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta                    if (emptyIds == null) {
1316f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta                        emptyIds = new ArrayList<Integer>(4);
1326f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta                    }
1336f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta                    emptyIds.add(i);
134d0cf227ef57e88fa9e104ea1dd2f7fa0555adbddDeepanshu Gupta                } else {
135d0cf227ef57e88fa9e104ea1dd2f7fa0555adbddDeepanshu Gupta                    count++;
136d0cf227ef57e88fa9e104ea1dd2f7fa0555adbddDeepanshu Gupta                }
137ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
138ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
139ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
1406f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta        if (emptyIds != null) {
1416f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta            mEmptyIds = new int[emptyIds.size()];
1426f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta            for (int i = 0; i < emptyIds.size(); i++) {
1436f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta                mEmptyIds[i] = emptyIds.get(i);
1446f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta            }
1456f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta        }
1466f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta
147ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // allocate the table with an extra to store the size
148ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mIndices = new int[count+1];
149ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mIndices[0] = count;
150ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
151ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // fill the array with the indices.
152ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int index = 1;
153ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        for (int i = 0 ; i < mResourceData.length ; i++) {
154d0cf227ef57e88fa9e104ea1dd2f7fa0555adbddDeepanshu Gupta            if (mResourceData[i] != null) {
155ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                mIndices[index++] = i;
156ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
157ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
158ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
159ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
160ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
161ca617d8a82e46474f597fe9a9b13bf0abc89f0baDeepanshu Gupta     * Set the theme to be used for inflating drawables.
162ca617d8a82e46474f597fe9a9b13bf0abc89f0baDeepanshu Gupta     */
163ca617d8a82e46474f597fe9a9b13bf0abc89f0baDeepanshu Gupta    public void setTheme(Theme theme) {
164ca617d8a82e46474f597fe9a9b13bf0abc89f0baDeepanshu Gupta        mTheme = theme;
165ca617d8a82e46474f597fe9a9b13bf0abc89f0baDeepanshu Gupta    }
166ca617d8a82e46474f597fe9a9b13bf0abc89f0baDeepanshu Gupta
167ca617d8a82e46474f597fe9a9b13bf0abc89f0baDeepanshu Gupta    /**
168ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Return the number of values in this array.
169ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
170ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
171ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public int length() {
172ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return mResourceData.length;
173ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
174ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
175ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
176ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Return the Resources object this array was loaded from.
177ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
178ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
179ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public Resources getResources() {
180ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return mBridgeResources;
181ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
182ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
183ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
184ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Retrieve the styled string value for the attribute at <var>index</var>.
185ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
186ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param index Index of attribute to retrieve.
187ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
188ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return CharSequence holding string data.  May be styled.  Returns
189ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *         null if the attribute is not defined.
190ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
191ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
192ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public CharSequence getText(int index) {
19332645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        // FIXME: handle styled strings!
19432645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        return getString(index);
195ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
196ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
197ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
198ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Retrieve the string value for the attribute at <var>index</var>.
199ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
200ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param index Index of attribute to retrieve.
201ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
202ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return String holding string data.  Any styling information is
203ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * removed.  Returns null if the attribute is not defined.
204ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
205ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
206ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public String getString(int index) {
20732645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        if (!hasValue(index)) {
208ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return null;
209ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
21032645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        // As unfortunate as it is, it's possible to use enums with all attribute formats,
211e77c203bd64b0d4a846e9d9e2155b6238620009dDeepanshu Gupta        // not just integers/enums. So, we need to search the enums always. In case
21232645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        // enums are used, the returned value is an integer.
21332645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        Integer v = resolveEnumAttribute(index);
21432645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        return v == null ? mResourceData[index].getValue() : String.valueOf((int) v);
215ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
216ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
217ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
218ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Retrieve the boolean value for the attribute at <var>index</var>.
219ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
220ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param index Index of attribute to retrieve.
221ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param defValue Value to return if the attribute is not defined.
222ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
223ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return Attribute boolean value, or defValue if not defined.
224ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
225ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
226ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public boolean getBoolean(int index, boolean defValue) {
22732645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        String s = getString(index);
22832645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        return s == null ? defValue : XmlUtils.convertValueToBoolean(s, defValue);
229ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
230ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
231ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
232ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
233ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Retrieve the integer value for the attribute at <var>index</var>.
234ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
235ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param index Index of attribute to retrieve.
236ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param defValue Value to return if the attribute is not defined.
237ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
238ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return Attribute int value, or defValue if not defined.
239ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
240ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
241ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public int getInt(int index, int defValue) {
24232645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        String s = getString(index);
243ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        try {
244b7a03c66dfbfed6ce8197b1fbc2aec8925bc410cDeepanshu Gupta            return convertValueToInt(s, defValue);
24532645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        } catch (NumberFormatException e) {
24632645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
247e77c203bd64b0d4a846e9d9e2155b6238620009dDeepanshu Gupta                    String.format("\"%1$s\" in attribute \"%2$s\" is not a valid integer",
24832645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta                            s, mNames[index]),
24932645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta                    null);
250ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
251ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return defValue;
252ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
253ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
254ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
255ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Retrieve the float value for the attribute at <var>index</var>.
256ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
257ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param index Index of attribute to retrieve.
258ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
259ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return Attribute float value, or defValue if not defined..
260ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
261ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
262ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public float getFloat(int index, float defValue) {
26332645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        String s = getString(index);
26432645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        try {
26532645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            if (s != null) {
26632645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta                    return Float.parseFloat(s);
267ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
26832645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        } catch (NumberFormatException e) {
26932645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
270e77c203bd64b0d4a846e9d9e2155b6238620009dDeepanshu Gupta                    String.format("\"%1$s\" in attribute \"%2$s\" cannot be converted to float.",
27132645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta                            s, mNames[index]),
27232645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta                    null);
273ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
274ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return defValue;
275ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
276ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
277ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
278ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Retrieve the color value for the attribute at <var>index</var>.  If
279ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * the attribute references a color resource holding a complex
280ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * {@link android.content.res.ColorStateList}, then the default color from
281ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * the set is returned.
282ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
283ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param index Index of attribute to retrieve.
284ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param defValue Value to return if the attribute is not defined or
285ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *                 not a resource.
286ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
287ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return Attribute color value, or defValue if not defined.
288ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
289ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
290ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public int getColor(int index, int defValue) {
291ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (index < 0 || index >= mResourceData.length) {
292ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return defValue;
293ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
294ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
295ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (mResourceData[index] == null) {
296ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return defValue;
297ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
298ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
299ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        ColorStateList colorStateList = ResourceHelper.getColorStateList(
3005fe96f847cc6b35510cd6e97777c8b8b75d94671Diego Perez                mResourceData[index], mContext, mTheme);
301ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (colorStateList != null) {
302ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return colorStateList.getDefaultColor();
303ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
304ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
305ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return defValue;
306ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
307ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
308e4cf18face6980b0c7ac42761512cd93b89927c3Diego Perez    @Override
309ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public ColorStateList getColorStateList(int index) {
31032645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        if (!hasValue(index)) {
311ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return null;
312ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
313ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
3145fe96f847cc6b35510cd6e97777c8b8b75d94671Diego Perez        return ResourceHelper.getColorStateList(mResourceData[index], mContext, mTheme);
315741ef6aac95e239f894f5640b8ff9728655e98b7Diego Perez    }
316129839107b12d1d42ce53a2b7ed0895589b59ff6Jerome Gaillard
317741ef6aac95e239f894f5640b8ff9728655e98b7Diego Perez    @Override
318741ef6aac95e239f894f5640b8ff9728655e98b7Diego Perez    public ComplexColor getComplexColor(int index) {
319741ef6aac95e239f894f5640b8ff9728655e98b7Diego Perez        if (!hasValue(index)) {
320129839107b12d1d42ce53a2b7ed0895589b59ff6Jerome Gaillard            return null;
321ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
322ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
3235fe96f847cc6b35510cd6e97777c8b8b75d94671Diego Perez        return ResourceHelper.getComplexColor(mResourceData[index], mContext, mTheme);
324ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
325ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
326ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
327ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Retrieve the integer value for the attribute at <var>index</var>.
328ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
329ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param index Index of attribute to retrieve.
330ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param defValue Value to return if the attribute is not defined or
331ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *                 not a resource.
332ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
333ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return Attribute integer value, or defValue if not defined.
334ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
335ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
336ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public int getInteger(int index, int defValue) {
337ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return getInt(index, defValue);
338ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
339ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
340ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
341ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Retrieve a dimensional unit attribute at <var>index</var>.  Unit
342ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * conversions are based on the current {@link DisplayMetrics}
343ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * associated with the resources this {@link TypedArray} object
344ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * came from.
345ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
346ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param index Index of attribute to retrieve.
347ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param defValue Value to return if the attribute is not defined or
348ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *                 not a resource.
349ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
350ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return Attribute dimension value multiplied by the appropriate
351ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * metric, or defValue if not defined.
352ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
353ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @see #getDimensionPixelOffset
354ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @see #getDimensionPixelSize
355ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
356ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
357ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public float getDimension(int index, float defValue) {
35832645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        String s = getString(index);
359ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (s == null) {
360ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return defValue;
361ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
36232645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        // Check if the value is a magic constant that doesn't require a unit.
36332645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        try {
36432645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            int i = Integer.parseInt(s);
36532645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            if (i == LayoutParams.MATCH_PARENT || i == LayoutParams.WRAP_CONTENT) {
36632645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta                return i;
36732645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            }
36832645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        } catch (NumberFormatException ignored) {
36932645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            // pass
37032645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        }
371ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
372d0cf227ef57e88fa9e104ea1dd2f7fa0555adbddDeepanshu Gupta        if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true)) {
373ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return mValue.getDimension(mBridgeResources.getDisplayMetrics());
374ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
375ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
37632645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        return defValue;
377ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
378ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
379ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
380ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Retrieve a dimensional unit attribute at <var>index</var> for use
381ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * as an offset in raw pixels.  This is the same as
382ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * {@link #getDimension}, except the returned value is converted to
383ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * integer pixels for you.  An offset conversion involves simply
384ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * truncating the base value to an integer.
385ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
386ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param index Index of attribute to retrieve.
387ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param defValue Value to return if the attribute is not defined or
388ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *                 not a resource.
389ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
390ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return Attribute dimension value multiplied by the appropriate
391ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * metric and truncated to integer pixels, or defValue if not defined.
392ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
393ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @see #getDimension
394ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @see #getDimensionPixelSize
395ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
396ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
397ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public int getDimensionPixelOffset(int index, int defValue) {
398ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return (int) getDimension(index, defValue);
399ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
400ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
401ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
402ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Retrieve a dimensional unit attribute at <var>index</var> for use
403ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * as a size in raw pixels.  This is the same as
404ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * {@link #getDimension}, except the returned value is converted to
405ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * integer pixels for use as a size.  A size conversion involves
406ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * rounding the base value, and ensuring that a non-zero base value
407ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * is at least one pixel in size.
408ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
409ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param index Index of attribute to retrieve.
410ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param defValue Value to return if the attribute is not defined or
411ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *                 not a resource.
412ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
413ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return Attribute dimension value multiplied by the appropriate
414ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * metric and truncated to integer pixels, or defValue if not defined.
415ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
416ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @see #getDimension
417ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @see #getDimensionPixelOffset
418ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
419ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
420ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public int getDimensionPixelSize(int index, int defValue) {
421ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        try {
422a9d1c5b4e2bd54b0e77c817b0813bec6cddc0eacDeepanshu Gupta            return getDimension(index, null);
423ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } catch (RuntimeException e) {
42432645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            String s = getString(index);
42532645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta
42632645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            if (s != null) {
42732645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta                // looks like we were unable to resolve the dimension value
42832645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta                Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
42932645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta                        String.format("\"%1$s\" in attribute \"%2$s\" is not a valid format.",
430d0cf227ef57e88fa9e104ea1dd2f7fa0555adbddDeepanshu Gupta                                s, mNames[index]), null);
431ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
432ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
433ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return defValue;
434ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
435ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
436ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
437ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
438ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Special version of {@link #getDimensionPixelSize} for retrieving
439ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * {@link android.view.ViewGroup}'s layout_width and layout_height
440ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * attributes.  This is only here for performance reasons; applications
441ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * should use {@link #getDimensionPixelSize}.
442ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
443ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param index Index of the attribute to retrieve.
444ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param name Textual name of attribute for error reporting.
445ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
446ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return Attribute dimension value multiplied by the appropriate
447ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * metric and truncated to integer pixels.
448ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
449ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
450ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public int getLayoutDimension(int index, String name) {
451ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        try {
452a9d1c5b4e2bd54b0e77c817b0813bec6cddc0eacDeepanshu Gupta            // this will throw an exception if not found.
453a9d1c5b4e2bd54b0e77c817b0813bec6cddc0eacDeepanshu Gupta            return getDimension(index, name);
454ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } catch (RuntimeException e) {
455ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
456ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (LayoutInflater_Delegate.sIsInInclude) {
457a9d1c5b4e2bd54b0e77c817b0813bec6cddc0eacDeepanshu Gupta                throw new RuntimeException("Layout Dimension '" + name + "' not found.");
458ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
459ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
460ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
461ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    "You must supply a " + name + " attribute.", null);
462ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
463ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return 0;
464ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
465ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
466ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
467ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
468ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public int getLayoutDimension(int index, int defValue) {
469ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return getDimensionPixelSize(index, defValue);
470ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
471ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
472a9d1c5b4e2bd54b0e77c817b0813bec6cddc0eacDeepanshu Gupta    /** @param name attribute name, used for error reporting. */
473a9d1c5b4e2bd54b0e77c817b0813bec6cddc0eacDeepanshu Gupta    private int getDimension(int index, @Nullable String name) {
47432645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        String s = getString(index);
475ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (s == null) {
476a9d1c5b4e2bd54b0e77c817b0813bec6cddc0eacDeepanshu Gupta            if (name != null) {
477a9d1c5b4e2bd54b0e77c817b0813bec6cddc0eacDeepanshu Gupta                throw new RuntimeException("Attribute '" + name + "' not found");
478a9d1c5b4e2bd54b0e77c817b0813bec6cddc0eacDeepanshu Gupta            }
479ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            throw new RuntimeException();
480ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
48132645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        // Check if the value is a magic constant that doesn't require a unit.
48232645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        try {
48332645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            int i = Integer.parseInt(s);
48432645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            if (i == LayoutParams.MATCH_PARENT || i == LayoutParams.WRAP_CONTENT) {
48532645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta                return i;
48632645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            }
48732645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        } catch (NumberFormatException ignored) {
48832645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            // pass
48932645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        }
490d0cf227ef57e88fa9e104ea1dd2f7fa0555adbddDeepanshu Gupta        if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true)) {
491ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            float f = mValue.getDimension(mBridgeResources.getDisplayMetrics());
492ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
493ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            final int res = (int)(f+0.5f);
494ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (res != 0) return res;
495ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (f == 0) return 0;
496ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (f > 0) return 1;
497ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
498ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
499ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        throw new RuntimeException();
500ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
501ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
502ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
503ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Retrieve a fractional unit attribute at <var>index</var>.
504ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
505ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param index Index of attribute to retrieve.
506ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param base The base value of this fraction.  In other words, a
507ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *             standard fraction is multiplied by this value.
508ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param pbase The parent base value of this fraction.  In other
509ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *             words, a parent fraction (nn%p) is multiplied by this
510ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *             value.
511ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param defValue Value to return if the attribute is not defined or
512ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *                 not a resource.
513ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
514ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return Attribute fractional value multiplied by the appropriate
515ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * base value, or defValue if not defined.
516ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
517ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
518ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public float getFraction(int index, int base, int pbase, float defValue) {
51932645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        String value = getString(index);
520ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (value == null) {
521ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return defValue;
522ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
523ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
524d0cf227ef57e88fa9e104ea1dd2f7fa0555adbddDeepanshu Gupta        if (ResourceHelper.parseFloatAttribute(mNames[index], value, mValue, false)) {
525ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return mValue.getFraction(base, pbase);
526ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
527ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
528ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // looks like we were unable to resolve the fraction value
529ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
530ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                String.format(
531d0cf227ef57e88fa9e104ea1dd2f7fa0555adbddDeepanshu Gupta                        "\"%1$s\" in attribute \"%2$s\" cannot be converted to a fraction.",
532d0cf227ef57e88fa9e104ea1dd2f7fa0555adbddDeepanshu Gupta                        value, mNames[index]), null);
533ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
534ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return defValue;
535ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
536ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
537ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
538ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Retrieve the resource identifier for the attribute at
539ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * <var>index</var>.  Note that attribute resource as resolved when
540ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * the overall {@link TypedArray} object is retrieved.  As a
541ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * result, this function will return the resource identifier of the
542ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * final resource value that was found, <em>not</em> necessarily the
543ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * original resource that was specified by the attribute.
544ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
545ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param index Index of attribute to retrieve.
546ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param defValue Value to return if the attribute is not defined or
547ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *                 not a resource.
548ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
549ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return Attribute resource identifier, or defValue if not defined.
550ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
551ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
552ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public int getResourceId(int index, int defValue) {
553ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (index < 0 || index >= mResourceData.length) {
554ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return defValue;
555ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
556ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
557ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the Resource for this index
558ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        ResourceValue resValue = mResourceData[index];
559ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
560ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // no data, return the default value.
561ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (resValue == null) {
562ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return defValue;
563ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
564ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
565ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // check if this is a style resource
566ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (resValue instanceof StyleResourceValue) {
567ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // get the id that will represent this style.
568ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return mContext.getDynamicIdByStyle((StyleResourceValue)resValue);
569ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
570ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
571ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // if the attribute was a reference to a resource, and not a declaration of an id (@+id),
572ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // then the xml attribute value was "resolved" which leads us to a ResourceValue with a
573ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // valid getType() and getName() returning a resource name.
574ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // (and getValue() returning null!). We need to handle this!
575ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (resValue.getResourceType() != null) {
576ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // if this is a framework id
577ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (mPlatformFile || resValue.isFramework()) {
578ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                // look for idName in the android R classes
579ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return mContext.getFrameworkResourceValue(
580ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                        resValue.getResourceType(), resValue.getName(), defValue);
581ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
582ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
583ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // look for idName in the project R class.
584ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return mContext.getProjectResourceValue(
585ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    resValue.getResourceType(), resValue.getName(), defValue);
586ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
587ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
588ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // else, try to get the value, and resolve it somehow.
589ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        String value = resValue.getValue();
590ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (value == null) {
591ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return defValue;
592ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
5939b30e13d8a9896da848fb5db5f91c802fc5249b2Diego Perez        value = value.trim();
594ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
595ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // if the value is just an integer, return it.
596ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        try {
597ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int i = Integer.parseInt(value);
598ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            if (Integer.toString(i).equals(value)) {
599ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return i;
600ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
601ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } catch (NumberFormatException e) {
602ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // pass
603ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
604ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
6059b30e13d8a9896da848fb5db5f91c802fc5249b2Diego Perez        if (value.startsWith("#")) {
6069b30e13d8a9896da848fb5db5f91c802fc5249b2Diego Perez            // this looks like a color, do not try to parse it
6079b30e13d8a9896da848fb5db5f91c802fc5249b2Diego Perez            return defValue;
6089b30e13d8a9896da848fb5db5f91c802fc5249b2Diego Perez        }
6099b30e13d8a9896da848fb5db5f91c802fc5249b2Diego Perez
610ef221c3b4f85123ac1ba21b46e36545c91508edaDiego Perez        if (Typeface_Accessor.isSystemFont(value)) {
611ef221c3b4f85123ac1ba21b46e36545c91508edaDiego Perez            // A system font family value, do not try to parse
612ef221c3b4f85123ac1ba21b46e36545c91508edaDiego Perez            return defValue;
613ef221c3b4f85123ac1ba21b46e36545c91508edaDiego Perez        }
614ef221c3b4f85123ac1ba21b46e36545c91508edaDiego Perez
615ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // Handle the @id/<name>, @+id/<name> and @android:id/<name>
616ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // We need to return the exact value that was compiled (from the various R classes),
617ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // as these values can be reused internally with calls to findViewById().
618ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // There's a trick with platform layouts that not use "android:" but their IDs are in
619ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // fact in the android.R and com.android.internal.R classes.
620ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // The field mPlatformFile will indicate that all IDs are to be looked up in the android R
621ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // classes exclusively.
622ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
623ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // if this is a reference to an id, find it.
624ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (value.startsWith("@id/") || value.startsWith("@+") ||
625ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                value.startsWith("@android:id/")) {
626ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
627ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int pos = value.indexOf('/');
628ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            String idName = value.substring(pos + 1);
629c8a55f3e2e36475d8a86a5967a9f2db629e02d1cDeepanshu Gupta            boolean create = value.startsWith("@+");
630c8a55f3e2e36475d8a86a5967a9f2db629e02d1cDeepanshu Gupta            boolean isFrameworkId =
631c8a55f3e2e36475d8a86a5967a9f2db629e02d1cDeepanshu Gupta                    mPlatformFile || value.startsWith("@android") || value.startsWith("@+android");
632c8a55f3e2e36475d8a86a5967a9f2db629e02d1cDeepanshu Gupta
633c8a55f3e2e36475d8a86a5967a9f2db629e02d1cDeepanshu Gupta            // Look for the idName in project or android R class depending on isPlatform.
634c8a55f3e2e36475d8a86a5967a9f2db629e02d1cDeepanshu Gupta            if (create) {
635c8a55f3e2e36475d8a86a5967a9f2db629e02d1cDeepanshu Gupta                Integer idValue;
636c8a55f3e2e36475d8a86a5967a9f2db629e02d1cDeepanshu Gupta                if (isFrameworkId) {
637c8a55f3e2e36475d8a86a5967a9f2db629e02d1cDeepanshu Gupta                    idValue = Bridge.getResourceId(ResourceType.ID, idName);
638c8a55f3e2e36475d8a86a5967a9f2db629e02d1cDeepanshu Gupta                } else {
639b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta                    idValue = mContext.getLayoutlibCallback().getResourceId(ResourceType.ID, idName);
640c8a55f3e2e36475d8a86a5967a9f2db629e02d1cDeepanshu Gupta                }
641c8a55f3e2e36475d8a86a5967a9f2db629e02d1cDeepanshu Gupta                return idValue == null ? defValue : idValue;
642c8a55f3e2e36475d8a86a5967a9f2db629e02d1cDeepanshu Gupta            }
643c8a55f3e2e36475d8a86a5967a9f2db629e02d1cDeepanshu Gupta            // This calls the same method as in if(create), but doesn't create a dynamic id, if
644c8a55f3e2e36475d8a86a5967a9f2db629e02d1cDeepanshu Gupta            // one is not found.
645c8a55f3e2e36475d8a86a5967a9f2db629e02d1cDeepanshu Gupta            if (isFrameworkId) {
646ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                return mContext.getFrameworkResourceValue(ResourceType.ID, idName, defValue);
647c8a55f3e2e36475d8a86a5967a9f2db629e02d1cDeepanshu Gupta            } else {
648c8a55f3e2e36475d8a86a5967a9f2db629e02d1cDeepanshu Gupta                return mContext.getProjectResourceValue(ResourceType.ID, idName, defValue);
649ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
650ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
651e76383f79ff4e9103857c94a1fc16afb34587540Diego Perez        else if (value.startsWith("@aapt:_aapt")) {
652e76383f79ff4e9103857c94a1fc16afb34587540Diego Perez            return mContext.getLayoutlibCallback().getResourceId(ResourceType.AAPT, value);
653e76383f79ff4e9103857c94a1fc16afb34587540Diego Perez        }
654ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
65521bf7d189aea4c63a03716a4e82f4193f099e7eeDiego Perez        // not a direct id valid reference. First check if it's an enum (this is a corner case
65621bf7d189aea4c63a03716a4e82f4193f099e7eeDiego Perez        // for attributes that have a reference|enum type), then fallback to resolve
65721bf7d189aea4c63a03716a4e82f4193f099e7eeDiego Perez        // as an ID without prefix.
65821bf7d189aea4c63a03716a4e82f4193f099e7eeDiego Perez        Integer enumValue = resolveEnumAttribute(index);
65921bf7d189aea4c63a03716a4e82f4193f099e7eeDiego Perez        if (enumValue != null) {
66021bf7d189aea4c63a03716a4e82f4193f099e7eeDiego Perez            return enumValue;
66121bf7d189aea4c63a03716a4e82f4193f099e7eeDiego Perez        }
66221bf7d189aea4c63a03716a4e82f4193f099e7eeDiego Perez
66321bf7d189aea4c63a03716a4e82f4193f099e7eeDiego Perez        // Ok, not an enum, resolve as an ID
66428948de70d6f77f80b475926c2b88f55e1365ff4Deepanshu Gupta        Integer idValue;
665ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
666ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (resValue.isFramework()) {
667ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            idValue = Bridge.getResourceId(resValue.getResourceType(),
668ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    resValue.getName());
669ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } else {
670b111e84752652ec862efa7e0fcaa224430feb97fDeepanshu Gupta            idValue = mContext.getLayoutlibCallback().getResourceId(
671ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    resValue.getResourceType(), resValue.getName());
672ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
673ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
674ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (idValue != null) {
67528948de70d6f77f80b475926c2b88f55e1365ff4Deepanshu Gupta            return idValue;
676ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
677ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
67871b8fa8301051c0678fbaa79edd7ba884047df4fJerome Gaillard        if ("text".equals(mNames[index])) {
67971b8fa8301051c0678fbaa79edd7ba884047df4fJerome Gaillard            // In a TextView, if the text is set from the attribute android:text, the correct
68071b8fa8301051c0678fbaa79edd7ba884047df4fJerome Gaillard            // behaviour is not to find a resourceId for the text, and to return the default value.
68171b8fa8301051c0678fbaa79edd7ba884047df4fJerome Gaillard            // So in this case, do not log a warning.
68271b8fa8301051c0678fbaa79edd7ba884047df4fJerome Gaillard            return defValue;
68371b8fa8301051c0678fbaa79edd7ba884047df4fJerome Gaillard        }
68471b8fa8301051c0678fbaa79edd7ba884047df4fJerome Gaillard
685ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE,
686ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                String.format(
687ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    "Unable to resolve id \"%1$s\" for attribute \"%2$s\"", value, mNames[index]),
688ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    resValue);
689ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
690ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return defValue;
691ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
692ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
69328948de70d6f77f80b475926c2b88f55e1365ff4Deepanshu Gupta    @Override
69428948de70d6f77f80b475926c2b88f55e1365ff4Deepanshu Gupta    public int getThemeAttributeId(int index, int defValue) {
69528948de70d6f77f80b475926c2b88f55e1365ff4Deepanshu Gupta        // TODO: Get the right Theme Attribute ID to enable caching of the drawables.
69628948de70d6f77f80b475926c2b88f55e1365ff4Deepanshu Gupta        return defValue;
69728948de70d6f77f80b475926c2b88f55e1365ff4Deepanshu Gupta    }
69828948de70d6f77f80b475926c2b88f55e1365ff4Deepanshu Gupta
699ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
700ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Retrieve the Drawable for the attribute at <var>index</var>.  This
701ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * gets the resource ID of the selected attribute, and uses
702ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * {@link Resources#getDrawable Resources.getDrawable} of the owning
703ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Resources object to retrieve its Drawable.
704ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
705ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param index Index of attribute to retrieve.
706ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
707ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return Drawable for the attribute, or null if not defined.
708ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
709ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
710ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public Drawable getDrawable(int index) {
71132645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        if (!hasValue(index)) {
712ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return null;
713ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
714ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
715ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        ResourceValue value = mResourceData[index];
716ca617d8a82e46474f597fe9a9b13bf0abc89f0baDeepanshu Gupta        return ResourceHelper.getDrawable(value, mContext, mTheme);
717ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
718ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
71941599e719d17f7a7fb64e2df043eb3542f4325f5Diego Perez    /**
72041599e719d17f7a7fb64e2df043eb3542f4325f5Diego Perez     * Version of {@link #getDrawable(int)} that accepts an override density.
72141599e719d17f7a7fb64e2df043eb3542f4325f5Diego Perez     * @hide
72241599e719d17f7a7fb64e2df043eb3542f4325f5Diego Perez     */
72341599e719d17f7a7fb64e2df043eb3542f4325f5Diego Perez    @Override
72441599e719d17f7a7fb64e2df043eb3542f4325f5Diego Perez    public Drawable getDrawableForDensity(int index, int density) {
72541599e719d17f7a7fb64e2df043eb3542f4325f5Diego Perez        return getDrawable(index);
72641599e719d17f7a7fb64e2df043eb3542f4325f5Diego Perez    }
727ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
728ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
7297c22a707de1ed939ebd91079dff9df6cd5ffd401Diego Perez     * Retrieve the Typeface for the attribute at <var>index</var>.
7307c22a707de1ed939ebd91079dff9df6cd5ffd401Diego Perez     * @param index Index of attribute to retrieve.
7317c22a707de1ed939ebd91079dff9df6cd5ffd401Diego Perez     *
7327c22a707de1ed939ebd91079dff9df6cd5ffd401Diego Perez     * @return Typeface for the attribute, or null if not defined.
7337c22a707de1ed939ebd91079dff9df6cd5ffd401Diego Perez     */
7347c22a707de1ed939ebd91079dff9df6cd5ffd401Diego Perez    @Override
7357c22a707de1ed939ebd91079dff9df6cd5ffd401Diego Perez    public Typeface getFont(int index) {
7367c22a707de1ed939ebd91079dff9df6cd5ffd401Diego Perez        if (!hasValue(index)) {
7377c22a707de1ed939ebd91079dff9df6cd5ffd401Diego Perez            return null;
7387c22a707de1ed939ebd91079dff9df6cd5ffd401Diego Perez        }
7397c22a707de1ed939ebd91079dff9df6cd5ffd401Diego Perez
7407c22a707de1ed939ebd91079dff9df6cd5ffd401Diego Perez        ResourceValue value = mResourceData[index];
7417c22a707de1ed939ebd91079dff9df6cd5ffd401Diego Perez        return ResourceHelper.getFont(value, mContext, mTheme);
7427c22a707de1ed939ebd91079dff9df6cd5ffd401Diego Perez    }
7437c22a707de1ed939ebd91079dff9df6cd5ffd401Diego Perez
7447c22a707de1ed939ebd91079dff9df6cd5ffd401Diego Perez    /**
745ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Retrieve the CharSequence[] for the attribute at <var>index</var>.
746ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * This gets the resource ID of the selected attribute, and uses
747ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * {@link Resources#getTextArray Resources.getTextArray} of the owning
748ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Resources object to retrieve its String[].
749ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
750ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param index Index of attribute to retrieve.
751ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
752ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return CharSequence[] for the attribute, or null if not defined.
753ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
754ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
755ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public CharSequence[] getTextArray(int index) {
75637e93696222aed44026f6423dd05ebc7c3c72b71Deepanshu Gupta        if (!hasValue(index)) {
75737e93696222aed44026f6423dd05ebc7c3c72b71Deepanshu Gupta            return null;
758ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
75937e93696222aed44026f6423dd05ebc7c3c72b71Deepanshu Gupta        ResourceValue resVal = mResourceData[index];
76037e93696222aed44026f6423dd05ebc7c3c72b71Deepanshu Gupta        if (resVal instanceof ArrayResourceValue) {
76137e93696222aed44026f6423dd05ebc7c3c72b71Deepanshu Gupta            ArrayResourceValue array = (ArrayResourceValue) resVal;
76237e93696222aed44026f6423dd05ebc7c3c72b71Deepanshu Gupta            int count = array.getElementCount();
763896eb1c37f6a44d65d3a459891475e99170b657cDeepanshu Gupta            return count >= 0 ? Resources_Delegate.fillValues(mBridgeResources, array, new CharSequence[count]) :
764896eb1c37f6a44d65d3a459891475e99170b657cDeepanshu Gupta                    null;
76537e93696222aed44026f6423dd05ebc7c3c72b71Deepanshu Gupta        }
76637e93696222aed44026f6423dd05ebc7c3c72b71Deepanshu Gupta        int id = getResourceId(index, 0);
76737e93696222aed44026f6423dd05ebc7c3c72b71Deepanshu Gupta        String resIdMessage = id > 0 ? " (resource id 0x" + Integer.toHexString(id) + ')' : "";
7680609785e6f839bfd27e33fa2630e6a1c12be9a20Diego Perez        assert false :
7690609785e6f839bfd27e33fa2630e6a1c12be9a20Diego Perez                String.format("%1$s in %2$s%3$s is not a valid array resource.", resVal.getValue(),
7700609785e6f839bfd27e33fa2630e6a1c12be9a20Diego Perez                        mNames[index], resIdMessage);
7710609785e6f839bfd27e33fa2630e6a1c12be9a20Diego Perez
7720609785e6f839bfd27e33fa2630e6a1c12be9a20Diego Perez        return new CharSequence[0];
773ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
774ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
775f0a7a1cb5b3ab8e9f46128c57dd8745e39706fbbDeepanshu Gupta    @Override
776f0a7a1cb5b3ab8e9f46128c57dd8745e39706fbbDeepanshu Gupta    public int[] extractThemeAttrs() {
777eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        // The drawables are always inflated with a Theme and we don't care about caching. So,
778eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        // just return.
779f0a7a1cb5b3ab8e9f46128c57dd8745e39706fbbDeepanshu Gupta        return null;
780f0a7a1cb5b3ab8e9f46128c57dd8745e39706fbbDeepanshu Gupta    }
781f0a7a1cb5b3ab8e9f46128c57dd8745e39706fbbDeepanshu Gupta
782eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    @Override
783eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    public int getChangingConfigurations() {
784eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        // We don't care about caching. Any change in configuration is a fresh render. So,
785eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        // just return.
786eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        return 0;
787eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    }
788eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta
789ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
790ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Retrieve the raw TypedValue for the attribute at <var>index</var>.
791ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
792ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param index Index of attribute to retrieve.
793ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param outValue TypedValue object in which to place the attribute's
794ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *                 data.
795ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
796ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return Returns true if the value was retrieved, else false.
797ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
798ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
799ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public boolean getValue(int index, TypedValue outValue) {
8003dd065e62224ca70a8415ebe8764b626f86a9397Charlie Tsai        // TODO: more switch cases for other types.
8013dd065e62224ca70a8415ebe8764b626f86a9397Charlie Tsai        outValue.type = getType(index);
8023dd065e62224ca70a8415ebe8764b626f86a9397Charlie Tsai        switch (outValue.type) {
8033dd065e62224ca70a8415ebe8764b626f86a9397Charlie Tsai            case TYPE_NULL:
8043dd065e62224ca70a8415ebe8764b626f86a9397Charlie Tsai                return false;
8053dd065e62224ca70a8415ebe8764b626f86a9397Charlie Tsai            case TYPE_STRING:
8063dd065e62224ca70a8415ebe8764b626f86a9397Charlie Tsai                outValue.string = getString(index);
8073dd065e62224ca70a8415ebe8764b626f86a9397Charlie Tsai                return true;
808bc876628ee6b96164b91908ff62fcaefe930f403Charlie Tsai            case TYPE_REFERENCE:
809bc876628ee6b96164b91908ff62fcaefe930f403Charlie Tsai                outValue.resourceId = mResourceId[index];
810bc876628ee6b96164b91908ff62fcaefe930f403Charlie Tsai                return true;
8113dd065e62224ca70a8415ebe8764b626f86a9397Charlie Tsai            default:
8123dd065e62224ca70a8415ebe8764b626f86a9397Charlie Tsai                // For back-compatibility, parse as float.
8133dd065e62224ca70a8415ebe8764b626f86a9397Charlie Tsai                String s = getString(index);
8143dd065e62224ca70a8415ebe8764b626f86a9397Charlie Tsai                return s != null &&
8153dd065e62224ca70a8415ebe8764b626f86a9397Charlie Tsai                        ResourceHelper.parseFloatAttribute(mNames[index], s, outValue, false);
8163dd065e62224ca70a8415ebe8764b626f86a9397Charlie Tsai        }
817ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
818ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
8199fe7fca9bcdceade9c654c6a8dcf0c48be16d78dDeepanshu Gupta    @Override
8201756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta    @SuppressWarnings("ResultOfMethodCallIgnored")
8219fe7fca9bcdceade9c654c6a8dcf0c48be16d78dDeepanshu Gupta    public int getType(int index) {
8221756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        String value = getString(index);
8231756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        if (value == null) {
8241756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            return TYPE_NULL;
8259fe7fca9bcdceade9c654c6a8dcf0c48be16d78dDeepanshu Gupta        }
8261756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        if (value.startsWith(PREFIX_RESOURCE_REF)) {
8271756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            return TYPE_REFERENCE;
8281756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        }
8291756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        if (value.startsWith(PREFIX_THEME_REF)) {
8301756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            return TYPE_ATTRIBUTE;
8311756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        }
8321756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        try {
8331756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            // Don't care about the value. Only called to check if an exception is thrown.
8341756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            convertValueToInt(value, 0);
8351756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            if (value.startsWith("0x") || value.startsWith("0X")) {
8361756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                return TYPE_INT_HEX;
8371756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            }
8381756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            // is it a color?
8391756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            if (value.startsWith("#")) {
8401756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                int length = value.length() - 1;
8411756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                if (length == 3) {  // rgb
8421756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                    return TYPE_INT_COLOR_RGB4;
8431756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                }
8441756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                if (length == 4) {  // argb
8451756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                    return TYPE_INT_COLOR_ARGB4;
8461756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                }
8471756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                if (length == 6) {  // rrggbb
8481756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                    return TYPE_INT_COLOR_RGB8;
8491756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                }
8501756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                if (length == 8) {  // aarrggbb
8511756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                    return TYPE_INT_COLOR_ARGB8;
8521756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                }
8531756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            }
8541756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) {
8551756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                return TYPE_INT_BOOLEAN;
8561756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            }
8571756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            return TYPE_INT_DEC;
8581756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        } catch (NumberFormatException ignored) {
8591756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            try {
8601756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                Float.parseFloat(value);
8611756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                return TYPE_FLOAT;
8621756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            } catch (NumberFormatException ignore) {
8631756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            }
8641756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            // Might be a dimension.
8651756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            if (ResourceHelper.parseFloatAttribute(null, value, new TypedValue(), false)) {
8661756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                return TYPE_DIMENSION;
8671756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            }
8681756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        }
8691756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        // TODO: handle fractions.
8701756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        return TYPE_STRING;
8719fe7fca9bcdceade9c654c6a8dcf0c48be16d78dDeepanshu Gupta    }
8729fe7fca9bcdceade9c654c6a8dcf0c48be16d78dDeepanshu Gupta
873ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
874ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Determines whether there is an attribute at <var>index</var>.
875ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
876ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param index Index of attribute to retrieve.
877ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
878ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return True if the attribute has a value, false otherwise.
879ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
880ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
881ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public boolean hasValue(int index) {
88232645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        return index >= 0 && index < mResourceData.length && mResourceData[index] != null;
883ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
884ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
8856f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta    @Override
8866f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta    public boolean hasValueOrEmpty(int index) {
8876f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta        return hasValue(index) || index >= 0 && index < mResourceData.length &&
8886f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta                mEmptyIds != null && Arrays.binarySearch(mEmptyIds, index) >= 0;
8896f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta    }
8906f3ccf0e18239aa6d8d5b352cf7d411f8716e0a7Deepanshu Gupta
891ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
892ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Retrieve the raw TypedValue for the attribute at <var>index</var>
893ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * and return a temporary object holding its data.  This object is only
894ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * valid until the next call on to {@link TypedArray}.
895ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
896ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param index Index of attribute to retrieve.
897ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
898ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return Returns a TypedValue object if the attribute is defined,
899ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *         containing its data; otherwise returns null.  (You will not
900ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *         receive a TypedValue whose type is TYPE_NULL.)
901ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
902ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
903ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public TypedValue peekValue(int index) {
904ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (index < 0 || index >= mResourceData.length) {
905ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return null;
906ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
907ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
908ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (getValue(index, mValue)) {
909ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return mValue;
910ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
911ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
912ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return null;
913ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
914ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
915ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
916ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Returns a message about the parser state suitable for printing error messages.
917ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
918ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
919ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public String getPositionDescription() {
920ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return "<internal -- stub if needed>";
921ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
922ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
923ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
924ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Give back a previously retrieved TypedArray, for later re-use.
925ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
926ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
927ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void recycle() {
928ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // pass
929ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
930ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
931ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @Override
932ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public String toString() {
933ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return Arrays.toString(mResourceData);
934ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
935f0a7a1cb5b3ab8e9f46128c57dd8745e39706fbbDeepanshu Gupta
93632645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta    /**
93732645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta     * Searches for the string in the attributes (flag or enums) and returns the integer.
93832645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta     * If found, it will return an integer matching the value.
93932645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta     *
94032645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta     * @param index Index of attribute to retrieve.
94132645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta     *
94232645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta     * @return Attribute int value, or null if not defined.
94332645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta     */
94432645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta    private Integer resolveEnumAttribute(int index) {
94532645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        // Get the map of attribute-constant -> IntegerValue
94632645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        Map<String, Integer> map = null;
94732645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        if (mIsFramework[index]) {
94832645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            map = Bridge.getEnumValues(mNames[index]);
94932645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        } else {
95032645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            // get the styleable matching the resolved name
95132645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            RenderResources res = mContext.getRenderResources();
95232645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            ResourceValue attr = res.getProjectResource(ResourceType.ATTR, mNames[index]);
95332645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            if (attr instanceof AttrResourceValue) {
95432645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta                map = ((AttrResourceValue) attr).getAttributeValues();
95532645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            }
95632645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        }
95732645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta
95832645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        if (map != null) {
95932645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            // accumulator to store the value of the 1+ constants.
96032645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            int result = 0;
96132645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            boolean found = false;
96232645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta
96332645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            // split the value in case this is a mix of several flags.
96432645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            String[] keywords = mResourceData[index].getValue().split("\\|");
96532645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            for (String keyword : keywords) {
96632645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta                Integer i = map.get(keyword.trim());
96732645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta                if (i != null) {
96832645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta                    result |= i;
96932645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta                    found = true;
97032645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta                }
97132645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta                // TODO: We should act smartly and log a warning for incorrect keywords. However,
97232645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta                // this method is currently called even if the resourceValue is not an enum.
97332645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            }
97432645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            if (found) {
97532645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta                return result;
97632645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta            }
97732645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        }
97832645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta
97932645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta        return null;
98032645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta    }
98132645d9875e40b2b4719ce77a0c8bf753028e854Deepanshu Gupta
9821756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta    /**
9831756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta     * Copied from {@link XmlUtils#convertValueToInt(CharSequence, int)}, but adapted to account
9841756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta     * for aapt, and the fact that host Java VM's Integer.parseInt("XXXXXXXX", 16) cannot handle
9851756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta     * "XXXXXXXX" > 80000000.
9861756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta     */
9871756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta    private static int convertValueToInt(@Nullable String charSeq, int defValue) {
988b7a03c66dfbfed6ce8197b1fbc2aec8925bc410cDeepanshu Gupta        if (null == charSeq || charSeq.isEmpty())
9891756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            return defValue;
9901756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta
9911756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        int sign = 1;
9921756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        int index = 0;
9931756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        int len = charSeq.length();
9941756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        int base = 10;
9951756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta
9961756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        if ('-' == charSeq.charAt(0)) {
9971756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            sign = -1;
9981756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            index++;
9991756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        }
10001756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta
10011756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        if ('0' == charSeq.charAt(index)) {
10021756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            //  Quick check for a zero by itself
10031756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            if (index == (len - 1))
10041756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                return 0;
10051756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta
10061756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            char c = charSeq.charAt(index + 1);
10071756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta
10081756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            if ('x' == c || 'X' == c) {
10091756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                index += 2;
10101756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                base = 16;
10111756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            } else {
10121756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                index++;
10131756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                // Leave the base as 10. aapt removes the preceding zero, and thus when framework
10141756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta                // sees the value, it only gets the decimal value.
10151756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            }
10161756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        } else if ('#' == charSeq.charAt(index)) {
10171756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            return ResourceHelper.getColor(charSeq) * sign;
10181756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        } else if ("true".equals(charSeq) || "TRUE".equals(charSeq)) {
10191756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            return -1;
10201756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        } else if ("false".equals(charSeq) || "FALSE".equals(charSeq)) {
10211756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta            return 0;
10221756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        }
10231756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta
10241756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        // Use Long, since we want to handle hex ints > 80000000.
10251756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta        return ((int)Long.parseLong(charSeq.substring(index), base)) * sign;
10261756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta    }
10271756dd0960657fca929ced5df044cd00e24b64dbDeepanshu Gupta
1028f0a7a1cb5b3ab8e9f46128c57dd8745e39706fbbDeepanshu Gupta    static TypedArray obtain(Resources res, int len) {
1029896eb1c37f6a44d65d3a459891475e99170b657cDeepanshu Gupta        return new BridgeTypedArray(res, null, len, true);
1030f0a7a1cb5b3ab8e9f46128c57dd8745e39706fbbDeepanshu Gupta    }
1031f0a7a1cb5b3ab8e9f46128c57dd8745e39706fbbDeepanshu Gupta}
1032