1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Copyright (C) 2008 The Android Open Source Project
3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * you may not use this file except in compliance with the License.
6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * You may obtain a copy of the License at
7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Unless required by applicable law or agreed to in writing, software
11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * See the License for the specific language governing permissions and
14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * limitations under the License.
15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipackage android.content.res;
18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
196649ca371139831369e063b937e25d7d6e97b9e6Deepanshu Guptaimport com.android.ide.common.rendering.api.ArrayResourceValue;
20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.AttrResourceValue;
21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.LayoutLog;
22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.RenderResources;
23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.ResourceValue;
24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.StyleResourceValue;
25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.internal.util.XmlUtils;
26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.layoutlib.bridge.Bridge;
27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.layoutlib.bridge.android.BridgeContext;
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.layoutlib.bridge.impl.ResourceHelper;
29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.resources.ResourceType;
30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
31476e582d2ffdf25102d4c55f8c242baa3d21d37fDeepanshu Guptaimport android.annotation.Nullable;
326649ca371139831369e063b937e25d7d6e97b9e6Deepanshu Guptaimport android.content.res.Resources.NotFoundException;
334a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Guptaimport android.content.res.Resources.Theme;
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.drawable.Drawable;
35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.util.DisplayMetrics;
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.util.TypedValue;
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.view.LayoutInflater_Delegate;
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.view.ViewGroup.LayoutParams;
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
409ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Guptaimport java.util.ArrayList;
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.Arrays;
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.Map;
43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
445779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Guptaimport static android.util.TypedValue.TYPE_ATTRIBUTE;
455779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Guptaimport static android.util.TypedValue.TYPE_DIMENSION;
465779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Guptaimport static android.util.TypedValue.TYPE_FLOAT;
475779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Guptaimport static android.util.TypedValue.TYPE_INT_BOOLEAN;
485779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Guptaimport static android.util.TypedValue.TYPE_INT_COLOR_ARGB4;
495779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Guptaimport static android.util.TypedValue.TYPE_INT_COLOR_ARGB8;
505779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Guptaimport static android.util.TypedValue.TYPE_INT_COLOR_RGB4;
515779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Guptaimport static android.util.TypedValue.TYPE_INT_COLOR_RGB8;
525779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Guptaimport static android.util.TypedValue.TYPE_INT_DEC;
535779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Guptaimport static android.util.TypedValue.TYPE_INT_HEX;
545779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Guptaimport static android.util.TypedValue.TYPE_NULL;
555779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Guptaimport static android.util.TypedValue.TYPE_REFERENCE;
565779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Guptaimport static android.util.TypedValue.TYPE_STRING;
575779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Guptaimport static com.android.SdkConstants.PREFIX_RESOURCE_REF;
585779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Guptaimport static com.android.SdkConstants.PREFIX_THEME_REF;
595779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Guptaimport static com.android.ide.common.rendering.api.RenderResources.REFERENCE_EMPTY;
605779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Guptaimport static com.android.ide.common.rendering.api.RenderResources.REFERENCE_NULL;
615779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Guptaimport static com.android.ide.common.rendering.api.RenderResources.REFERENCE_UNDEFINED;
629ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/**
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Custom implementation of TypedArray to handle non compiled resources.
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic final class BridgeTypedArray extends TypedArray {
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
68e05f1c4684fcc7e3f6a429ff01b210aa19f75304Deepanshu Gupta    private final Resources mBridgeResources;
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final BridgeContext mContext;
70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final boolean mPlatformFile;
71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
72831f3ce9b5b330101b090daf3163a843e0c6317eDeepanshu Gupta    private final ResourceValue[] mResourceData;
73831f3ce9b5b330101b090daf3163a843e0c6317eDeepanshu Gupta    private final String[] mNames;
74831f3ce9b5b330101b090daf3163a843e0c6317eDeepanshu Gupta    private final boolean[] mIsFramework;
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
769ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta    // Contains ids that are @empty. We still store null in mResourceData for that index, since we
779ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta    // want to save on the check against empty, each time a resource value is requested.
789ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta    @Nullable
799ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta    private int[] mEmptyIds;
809ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta
81e05f1c4684fcc7e3f6a429ff01b210aa19f75304Deepanshu Gupta    public BridgeTypedArray(Resources resources, BridgeContext context, int len,
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            boolean platformFile) {
83857ba4af8519479298a671461cd6f5cace35b99bDeepanshu Gupta        super(resources, null, null, 0);
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mBridgeResources = resources;
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mContext = context;
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mPlatformFile = platformFile;
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mResourceData = new ResourceValue[len];
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mNames = new String[len];
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mIsFramework = new boolean[len];
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * A bridge-specific method that sets a value in the type array
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param index the index of the value in the TypedArray
95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param name the name of the attribute
96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param isFramework whether the attribute is in the android namespace.
97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param value the value of the attribute
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void bridgeSetValue(int index, String name, boolean isFramework, ResourceValue value) {
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mResourceData[index] = value;
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mNames[index] = name;
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mIsFramework[index] = isFramework;
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
106831f3ce9b5b330101b090daf3163a843e0c6317eDeepanshu Gupta     * Seals the array after all calls to
107831f3ce9b5b330101b090daf3163a843e0c6317eDeepanshu Gupta     * {@link #bridgeSetValue(int, String, boolean, ResourceValue)} have been done.
108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * <p/>This allows to compute the list of non default values, permitting
109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * {@link #getIndexCount()} to return the proper value.
110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void sealArray() {
112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // fills TypedArray.mIndices which is used to implement getIndexCount/getIndexAt
113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // first count the array size
114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int count = 0;
1159ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta        ArrayList<Integer> emptyIds = null;
116d4cf391c618e5f370f2cfd9f344baa895d5d3242Deepanshu Gupta        for (int i = 0; i < mResourceData.length; i++) {
117d4cf391c618e5f370f2cfd9f344baa895d5d3242Deepanshu Gupta            ResourceValue data = mResourceData[i];
118d4cf391c618e5f370f2cfd9f344baa895d5d3242Deepanshu Gupta            if (data != null) {
1199ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta                String dataValue = data.getValue();
1209ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta                if (REFERENCE_NULL.equals(dataValue) || REFERENCE_UNDEFINED.equals(dataValue)) {
1219ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta                    mResourceData[i] = null;
1229ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta                } else if (REFERENCE_EMPTY.equals(dataValue)) {
123d4cf391c618e5f370f2cfd9f344baa895d5d3242Deepanshu Gupta                    mResourceData[i] = null;
1249ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta                    if (emptyIds == null) {
1259ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta                        emptyIds = new ArrayList<Integer>(4);
1269ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta                    }
1279ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta                    emptyIds.add(i);
128d4cf391c618e5f370f2cfd9f344baa895d5d3242Deepanshu Gupta                } else {
129d4cf391c618e5f370f2cfd9f344baa895d5d3242Deepanshu Gupta                    count++;
130d4cf391c618e5f370f2cfd9f344baa895d5d3242Deepanshu Gupta                }
131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
1349ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta        if (emptyIds != null) {
1359ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta            mEmptyIds = new int[emptyIds.size()];
1369ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta            for (int i = 0; i < emptyIds.size(); i++) {
1379ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta                mEmptyIds[i] = emptyIds.get(i);
1389ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta            }
1399ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta        }
1409ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta
141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // allocate the table with an extra to store the size
142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mIndices = new int[count+1];
143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mIndices[0] = count;
144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // fill the array with the indices.
146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int index = 1;
147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        for (int i = 0 ; i < mResourceData.length ; i++) {
148d4cf391c618e5f370f2cfd9f344baa895d5d3242Deepanshu Gupta            if (mResourceData[i] != null) {
149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mIndices[index++] = i;
150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
1554a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta     * Set the theme to be used for inflating drawables.
1564a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta     */
1574a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta    public void setTheme(Theme theme) {
1584a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta        mTheme = theme;
1594a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta    }
1604a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta
1614a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta    /**
162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Return the number of values in this array.
163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public int length() {
166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mResourceData.length;
167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Return the Resources object this array was loaded from.
171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public Resources getResources() {
174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mBridgeResources;
175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Retrieve the styled string value for the attribute at <var>index</var>.
179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param index Index of attribute to retrieve.
181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return CharSequence holding string data.  May be styled.  Returns
183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *         null if the attribute is not defined.
184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public CharSequence getText(int index) {
187171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        // FIXME: handle styled strings!
188171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        return getString(index);
189282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
190282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
191282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
192282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Retrieve the string value for the attribute at <var>index</var>.
193282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
194282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param index Index of attribute to retrieve.
195282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
196282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return String holding string data.  Any styling information is
197282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * removed.  Returns null if the attribute is not defined.
198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public String getString(int index) {
201171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        if (!hasValue(index)) {
202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return null;
203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
204171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        // As unfortunate as it is, it's possible to use enums with all attribute formats,
2053c8140ab4b39922f92682910ce24de77fd512db4Deepanshu Gupta        // not just integers/enums. So, we need to search the enums always. In case
206171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        // enums are used, the returned value is an integer.
207171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        Integer v = resolveEnumAttribute(index);
208171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        return v == null ? mResourceData[index].getValue() : String.valueOf((int) v);
209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Retrieve the boolean value for the attribute at <var>index</var>.
213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param index Index of attribute to retrieve.
215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param defValue Value to return if the attribute is not defined.
216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return Attribute boolean value, or defValue if not defined.
218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public boolean getBoolean(int index, boolean defValue) {
221171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        String s = getString(index);
222171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        return s == null ? defValue : XmlUtils.convertValueToBoolean(s, defValue);
223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Retrieve the integer value for the attribute at <var>index</var>.
228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param index Index of attribute to retrieve.
230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param defValue Value to return if the attribute is not defined.
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return Attribute int value, or defValue if not defined.
233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public int getInt(int index, int defValue) {
236171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        String s = getString(index);
237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        try {
2380437cac76c24dc6cac7b530e6d80f789565550ecDeepanshu Gupta            return convertValueToInt(s, defValue);
239171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        } catch (NumberFormatException e) {
240171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
2413c8140ab4b39922f92682910ce24de77fd512db4Deepanshu Gupta                    String.format("\"%1$s\" in attribute \"%2$s\" is not a valid integer",
242171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta                            s, mNames[index]),
243171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta                    null);
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return defValue;
246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Retrieve the float value for the attribute at <var>index</var>.
250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param index Index of attribute to retrieve.
252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return Attribute float value, or defValue if not defined..
254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public float getFloat(int index, float defValue) {
257171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        String s = getString(index);
258171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        try {
259171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            if (s != null) {
260171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta                    return Float.parseFloat(s);
261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
262171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        } catch (NumberFormatException e) {
263171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
2643c8140ab4b39922f92682910ce24de77fd512db4Deepanshu Gupta                    String.format("\"%1$s\" in attribute \"%2$s\" cannot be converted to float.",
265171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta                            s, mNames[index]),
266171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta                    null);
267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return defValue;
269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Retrieve the color value for the attribute at <var>index</var>.  If
273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * the attribute references a color resource holding a complex
274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * {@link android.content.res.ColorStateList}, then the default color from
275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * the set is returned.
276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param index Index of attribute to retrieve.
278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param defValue Value to return if the attribute is not defined or
279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *                 not a resource.
280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return Attribute color value, or defValue if not defined.
282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public int getColor(int index, int defValue) {
285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (index < 0 || index >= mResourceData.length) {
286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return defValue;
287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (mResourceData[index] == null) {
290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return defValue;
291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ColorStateList colorStateList = ResourceHelper.getColorStateList(
294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                mResourceData[index], mContext);
295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (colorStateList != null) {
296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return colorStateList.getDefaultColor();
297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return defValue;
300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
3025d1013cf13e59b7f8dc8f16b5811cb29982e0ef3Diego Perez    @Override
303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public ColorStateList getColorStateList(int index) {
304171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        if (!hasValue(index)) {
305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return null;
306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
308566b303365078fac9a454f1595add19e02631db3Diego Perez        return ResourceHelper.getColorStateList(mResourceData[index], mContext);
309566b303365078fac9a454f1595add19e02631db3Diego Perez    }
310b63da06a7ab9ad06184b0359abddd9137742ea4aJerome Gaillard
311566b303365078fac9a454f1595add19e02631db3Diego Perez    @Override
312566b303365078fac9a454f1595add19e02631db3Diego Perez    public ComplexColor getComplexColor(int index) {
313566b303365078fac9a454f1595add19e02631db3Diego Perez        if (!hasValue(index)) {
314b63da06a7ab9ad06184b0359abddd9137742ea4aJerome Gaillard            return null;
315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
317566b303365078fac9a454f1595add19e02631db3Diego Perez        return ResourceHelper.getComplexColor(mResourceData[index], mContext);
318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Retrieve the integer value for the attribute at <var>index</var>.
322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param index Index of attribute to retrieve.
324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param defValue Value to return if the attribute is not defined or
325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *                 not a resource.
326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return Attribute integer value, or defValue if not defined.
328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public int getInteger(int index, int defValue) {
331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return getInt(index, defValue);
332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Retrieve a dimensional unit attribute at <var>index</var>.  Unit
336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * conversions are based on the current {@link DisplayMetrics}
337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * associated with the resources this {@link TypedArray} object
338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * came from.
339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param index Index of attribute to retrieve.
341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param defValue Value to return if the attribute is not defined or
342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *                 not a resource.
343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return Attribute dimension value multiplied by the appropriate
345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * metric, or defValue if not defined.
346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @see #getDimensionPixelOffset
348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @see #getDimensionPixelSize
349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public float getDimension(int index, float defValue) {
352171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        String s = getString(index);
353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (s == null) {
354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return defValue;
355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
356171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        // Check if the value is a magic constant that doesn't require a unit.
357171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        try {
358171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            int i = Integer.parseInt(s);
359171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            if (i == LayoutParams.MATCH_PARENT || i == LayoutParams.WRAP_CONTENT) {
360171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta                return i;
361171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            }
362171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        } catch (NumberFormatException ignored) {
363171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            // pass
364171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        }
365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
366d4cf391c618e5f370f2cfd9f344baa895d5d3242Deepanshu Gupta        if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true)) {
367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return mValue.getDimension(mBridgeResources.getDisplayMetrics());
368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
370171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        return defValue;
371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Retrieve a dimensional unit attribute at <var>index</var> for use
375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * as an offset in raw pixels.  This is the same as
376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * {@link #getDimension}, except the returned value is converted to
377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * integer pixels for you.  An offset conversion involves simply
378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * truncating the base value to an integer.
379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param index Index of attribute to retrieve.
381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param defValue Value to return if the attribute is not defined or
382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *                 not a resource.
383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return Attribute dimension value multiplied by the appropriate
385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * metric and truncated to integer pixels, or defValue if not defined.
386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @see #getDimension
388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @see #getDimensionPixelSize
389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public int getDimensionPixelOffset(int index, int defValue) {
392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return (int) getDimension(index, defValue);
393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Retrieve a dimensional unit attribute at <var>index</var> for use
397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * as a size in raw pixels.  This is the same as
398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * {@link #getDimension}, except the returned value is converted to
399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * integer pixels for use as a size.  A size conversion involves
400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * rounding the base value, and ensuring that a non-zero base value
401282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * is at least one pixel in size.
402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param index Index of attribute to retrieve.
404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param defValue Value to return if the attribute is not defined or
405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *                 not a resource.
406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return Attribute dimension value multiplied by the appropriate
408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * metric and truncated to integer pixels, or defValue if not defined.
409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @see #getDimension
411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @see #getDimensionPixelOffset
412282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
413282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public int getDimensionPixelSize(int index, int defValue) {
415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        try {
41621b564573327b1ed2f7e06146b8a01c47ede3089Deepanshu Gupta            return getDimension(index, null);
417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } catch (RuntimeException e) {
418171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            String s = getString(index);
419171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta
420171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            if (s != null) {
421171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta                // looks like we were unable to resolve the dimension value
422171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta                Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
423171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta                        String.format("\"%1$s\" in attribute \"%2$s\" is not a valid format.",
424d4cf391c618e5f370f2cfd9f344baa895d5d3242Deepanshu Gupta                                s, mNames[index]), null);
425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return defValue;
428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Special version of {@link #getDimensionPixelSize} for retrieving
433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * {@link android.view.ViewGroup}'s layout_width and layout_height
434282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * attributes.  This is only here for performance reasons; applications
435282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * should use {@link #getDimensionPixelSize}.
436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param index Index of the attribute to retrieve.
438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param name Textual name of attribute for error reporting.
439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return Attribute dimension value multiplied by the appropriate
441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * metric and truncated to integer pixels.
442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public int getLayoutDimension(int index, String name) {
445282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        try {
44621b564573327b1ed2f7e06146b8a01c47ede3089Deepanshu Gupta            // this will throw an exception if not found.
44721b564573327b1ed2f7e06146b8a01c47ede3089Deepanshu Gupta            return getDimension(index, name);
448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } catch (RuntimeException e) {
449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (LayoutInflater_Delegate.sIsInInclude) {
45121b564573327b1ed2f7e06146b8a01c47ede3089Deepanshu Gupta                throw new RuntimeException("Layout Dimension '" + name + "' not found.");
452282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "You must supply a " + name + " attribute.", null);
456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return 0;
458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public int getLayoutDimension(int index, int defValue) {
463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return getDimensionPixelSize(index, defValue);
464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
46621b564573327b1ed2f7e06146b8a01c47ede3089Deepanshu Gupta    /** @param name attribute name, used for error reporting. */
46721b564573327b1ed2f7e06146b8a01c47ede3089Deepanshu Gupta    private int getDimension(int index, @Nullable String name) {
468171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        String s = getString(index);
469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (s == null) {
47021b564573327b1ed2f7e06146b8a01c47ede3089Deepanshu Gupta            if (name != null) {
47121b564573327b1ed2f7e06146b8a01c47ede3089Deepanshu Gupta                throw new RuntimeException("Attribute '" + name + "' not found");
47221b564573327b1ed2f7e06146b8a01c47ede3089Deepanshu Gupta            }
473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            throw new RuntimeException();
474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
475171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        // Check if the value is a magic constant that doesn't require a unit.
476171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        try {
477171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            int i = Integer.parseInt(s);
478171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            if (i == LayoutParams.MATCH_PARENT || i == LayoutParams.WRAP_CONTENT) {
479171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta                return i;
480171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            }
481171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        } catch (NumberFormatException ignored) {
482171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            // pass
483171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        }
484d4cf391c618e5f370f2cfd9f344baa895d5d3242Deepanshu Gupta        if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true)) {
485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            float f = mValue.getDimension(mBridgeResources.getDisplayMetrics());
486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            final int res = (int)(f+0.5f);
488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (res != 0) return res;
489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (f == 0) return 0;
490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (f > 0) return 1;
491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        throw new RuntimeException();
494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Retrieve a fractional unit attribute at <var>index</var>.
498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param index Index of attribute to retrieve.
500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param base The base value of this fraction.  In other words, a
501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *             standard fraction is multiplied by this value.
502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param pbase The parent base value of this fraction.  In other
503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *             words, a parent fraction (nn%p) is multiplied by this
504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *             value.
505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param defValue Value to return if the attribute is not defined or
506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *                 not a resource.
507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return Attribute fractional value multiplied by the appropriate
509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * base value, or defValue if not defined.
510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public float getFraction(int index, int base, int pbase, float defValue) {
513171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        String value = getString(index);
514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (value == null) {
515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return defValue;
516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
518d4cf391c618e5f370f2cfd9f344baa895d5d3242Deepanshu Gupta        if (ResourceHelper.parseFloatAttribute(mNames[index], value, mValue, false)) {
519282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return mValue.getFraction(base, pbase);
520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // looks like we were unable to resolve the fraction value
523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String.format(
525d4cf391c618e5f370f2cfd9f344baa895d5d3242Deepanshu Gupta                        "\"%1$s\" in attribute \"%2$s\" cannot be converted to a fraction.",
526d4cf391c618e5f370f2cfd9f344baa895d5d3242Deepanshu Gupta                        value, mNames[index]), null);
527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return defValue;
529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Retrieve the resource identifier for the attribute at
533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * <var>index</var>.  Note that attribute resource as resolved when
534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * the overall {@link TypedArray} object is retrieved.  As a
535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * result, this function will return the resource identifier of the
536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * final resource value that was found, <em>not</em> necessarily the
537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * original resource that was specified by the attribute.
538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param index Index of attribute to retrieve.
540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param defValue Value to return if the attribute is not defined or
541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *                 not a resource.
542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return Attribute resource identifier, or defValue if not defined.
544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public int getResourceId(int index, int defValue) {
547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (index < 0 || index >= mResourceData.length) {
548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return defValue;
549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the Resource for this index
552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ResourceValue resValue = mResourceData[index];
553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // no data, return the default value.
555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (resValue == null) {
556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return defValue;
557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // check if this is a style resource
560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (resValue instanceof StyleResourceValue) {
561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // get the id that will represent this style.
562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return mContext.getDynamicIdByStyle((StyleResourceValue)resValue);
563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // if the attribute was a reference to a resource, and not a declaration of an id (@+id),
566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // then the xml attribute value was "resolved" which leads us to a ResourceValue with a
567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // valid getType() and getName() returning a resource name.
568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // (and getValue() returning null!). We need to handle this!
569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (resValue.getResourceType() != null) {
570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // if this is a framework id
571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (mPlatformFile || resValue.isFramework()) {
572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                // look for idName in the android R classes
573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return mContext.getFrameworkResourceValue(
574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                        resValue.getResourceType(), resValue.getName(), defValue);
575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // look for idName in the project R class.
578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return mContext.getProjectResourceValue(
579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    resValue.getResourceType(), resValue.getName(), defValue);
580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // else, try to get the value, and resolve it somehow.
583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        String value = resValue.getValue();
584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (value == null) {
585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return defValue;
586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // if the value is just an integer, return it.
589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        try {
590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int i = Integer.parseInt(value);
591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            if (Integer.toString(i).equals(value)) {
592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return i;
593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } catch (NumberFormatException e) {
595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // pass
596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // Handle the @id/<name>, @+id/<name> and @android:id/<name>
599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // We need to return the exact value that was compiled (from the various R classes),
600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // as these values can be reused internally with calls to findViewById().
601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // There's a trick with platform layouts that not use "android:" but their IDs are in
602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // fact in the android.R and com.android.internal.R classes.
603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // The field mPlatformFile will indicate that all IDs are to be looked up in the android R
604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // classes exclusively.
605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // if this is a reference to an id, find it.
607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (value.startsWith("@id/") || value.startsWith("@+") ||
608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                value.startsWith("@android:id/")) {
609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int pos = value.indexOf('/');
611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            String idName = value.substring(pos + 1);
612b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta            boolean create = value.startsWith("@+");
613b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta            boolean isFrameworkId =
614b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta                    mPlatformFile || value.startsWith("@android") || value.startsWith("@+android");
615b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta
616b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta            // Look for the idName in project or android R class depending on isPlatform.
617b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta            if (create) {
618b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta                Integer idValue;
619b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta                if (isFrameworkId) {
620b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta                    idValue = Bridge.getResourceId(ResourceType.ID, idName);
621b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta                } else {
62237dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta                    idValue = mContext.getLayoutlibCallback().getResourceId(ResourceType.ID, idName);
623b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta                }
624b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta                return idValue == null ? defValue : idValue;
625b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta            }
626b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta            // This calls the same method as in if(create), but doesn't create a dynamic id, if
627b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta            // one is not found.
628b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta            if (isFrameworkId) {
629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                return mContext.getFrameworkResourceValue(ResourceType.ID, idName, defValue);
630b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta            } else {
631b6864ac6cde109be320e18188209eb8420c585f1Deepanshu Gupta                return mContext.getProjectResourceValue(ResourceType.ID, idName, defValue);
632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // not a direct id valid reference? resolve it
636831f3ce9b5b330101b090daf3163a843e0c6317eDeepanshu Gupta        Integer idValue;
637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (resValue.isFramework()) {
639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            idValue = Bridge.getResourceId(resValue.getResourceType(),
640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    resValue.getName());
641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } else {
64237dbb8b7f3c069196040eed3a03006647db7fa5bDeepanshu Gupta            idValue = mContext.getLayoutlibCallback().getResourceId(
643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    resValue.getResourceType(), resValue.getName());
644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (idValue != null) {
647831f3ce9b5b330101b090daf3163a843e0c6317eDeepanshu Gupta            return idValue;
648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE,
651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                String.format(
652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "Unable to resolve id \"%1$s\" for attribute \"%2$s\"", value, mNames[index]),
653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    resValue);
654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return defValue;
656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
658831f3ce9b5b330101b090daf3163a843e0c6317eDeepanshu Gupta    @Override
659831f3ce9b5b330101b090daf3163a843e0c6317eDeepanshu Gupta    public int getThemeAttributeId(int index, int defValue) {
660831f3ce9b5b330101b090daf3163a843e0c6317eDeepanshu Gupta        // TODO: Get the right Theme Attribute ID to enable caching of the drawables.
661831f3ce9b5b330101b090daf3163a843e0c6317eDeepanshu Gupta        return defValue;
662831f3ce9b5b330101b090daf3163a843e0c6317eDeepanshu Gupta    }
663831f3ce9b5b330101b090daf3163a843e0c6317eDeepanshu Gupta
664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Retrieve the Drawable for the attribute at <var>index</var>.  This
666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * gets the resource ID of the selected attribute, and uses
667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * {@link Resources#getDrawable Resources.getDrawable} of the owning
668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Resources object to retrieve its Drawable.
669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param index Index of attribute to retrieve.
671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return Drawable for the attribute, or null if not defined.
673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public Drawable getDrawable(int index) {
676171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        if (!hasValue(index)) {
677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return null;
678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        ResourceValue value = mResourceData[index];
6814a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta        return ResourceHelper.getDrawable(value, mContext, mTheme);
682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Retrieve the CharSequence[] for the attribute at <var>index</var>.
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * This gets the resource ID of the selected attribute, and uses
688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * {@link Resources#getTextArray Resources.getTextArray} of the owning
689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Resources object to retrieve its String[].
690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param index Index of attribute to retrieve.
692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return CharSequence[] for the attribute, or null if not defined.
694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public CharSequence[] getTextArray(int index) {
6976649ca371139831369e063b937e25d7d6e97b9e6Deepanshu Gupta        if (!hasValue(index)) {
6986649ca371139831369e063b937e25d7d6e97b9e6Deepanshu Gupta            return null;
699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
7006649ca371139831369e063b937e25d7d6e97b9e6Deepanshu Gupta        ResourceValue resVal = mResourceData[index];
7016649ca371139831369e063b937e25d7d6e97b9e6Deepanshu Gupta        if (resVal instanceof ArrayResourceValue) {
7026649ca371139831369e063b937e25d7d6e97b9e6Deepanshu Gupta            ArrayResourceValue array = (ArrayResourceValue) resVal;
7036649ca371139831369e063b937e25d7d6e97b9e6Deepanshu Gupta            int count = array.getElementCount();
704e05f1c4684fcc7e3f6a429ff01b210aa19f75304Deepanshu Gupta            return count >= 0 ? Resources_Delegate.fillValues(mBridgeResources, array, new CharSequence[count]) :
705e05f1c4684fcc7e3f6a429ff01b210aa19f75304Deepanshu Gupta                    null;
7066649ca371139831369e063b937e25d7d6e97b9e6Deepanshu Gupta        }
7076649ca371139831369e063b937e25d7d6e97b9e6Deepanshu Gupta        int id = getResourceId(index, 0);
7086649ca371139831369e063b937e25d7d6e97b9e6Deepanshu Gupta        String resIdMessage = id > 0 ? " (resource id 0x" + Integer.toHexString(id) + ')' : "";
7096649ca371139831369e063b937e25d7d6e97b9e6Deepanshu Gupta        throw new NotFoundException(
7106649ca371139831369e063b937e25d7d6e97b9e6Deepanshu Gupta                String.format("%1$s in %2$s%3$s is not a valid array resource.",
7116649ca371139831369e063b937e25d7d6e97b9e6Deepanshu Gupta                        resVal.getValue(), mNames[index], resIdMessage));
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
714dc62340f18becf51f6f3c94d3994665bcd7dd537Deepanshu Gupta    @Override
715dc62340f18becf51f6f3c94d3994665bcd7dd537Deepanshu Gupta    public int[] extractThemeAttrs() {
71626e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta        // The drawables are always inflated with a Theme and we don't care about caching. So,
71726e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta        // just return.
718dc62340f18becf51f6f3c94d3994665bcd7dd537Deepanshu Gupta        return null;
719dc62340f18becf51f6f3c94d3994665bcd7dd537Deepanshu Gupta    }
720dc62340f18becf51f6f3c94d3994665bcd7dd537Deepanshu Gupta
72126e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta    @Override
72226e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta    public int getChangingConfigurations() {
72326e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta        // We don't care about caching. Any change in configuration is a fresh render. So,
72426e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta        // just return.
72526e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta        return 0;
72626e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta    }
72726e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta
728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Retrieve the raw TypedValue for the attribute at <var>index</var>.
730282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
731282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param index Index of attribute to retrieve.
732282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param outValue TypedValue object in which to place the attribute's
733282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *                 data.
734282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
735282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return Returns true if the value was retrieved, else false.
736282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
737282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
738282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public boolean getValue(int index, TypedValue outValue) {
739171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        String s = getString(index);
740171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        return s != null && ResourceHelper.parseFloatAttribute(mNames[index], s, outValue, false);
741282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
742282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
743d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta    @Override
7445779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta    @SuppressWarnings("ResultOfMethodCallIgnored")
745d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta    public int getType(int index) {
7465779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        String value = getString(index);
7475779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        if (value == null) {
7485779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            return TYPE_NULL;
749d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta        }
7505779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        if (value.startsWith(PREFIX_RESOURCE_REF)) {
7515779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            return TYPE_REFERENCE;
7525779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        }
7535779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        if (value.startsWith(PREFIX_THEME_REF)) {
7545779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            return TYPE_ATTRIBUTE;
7555779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        }
7565779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        try {
7575779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            // Don't care about the value. Only called to check if an exception is thrown.
7585779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            convertValueToInt(value, 0);
7595779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            if (value.startsWith("0x") || value.startsWith("0X")) {
7605779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                return TYPE_INT_HEX;
7615779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            }
7625779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            // is it a color?
7635779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            if (value.startsWith("#")) {
7645779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                int length = value.length() - 1;
7655779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                if (length == 3) {  // rgb
7665779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                    return TYPE_INT_COLOR_RGB4;
7675779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                }
7685779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                if (length == 4) {  // argb
7695779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                    return TYPE_INT_COLOR_ARGB4;
7705779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                }
7715779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                if (length == 6) {  // rrggbb
7725779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                    return TYPE_INT_COLOR_RGB8;
7735779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                }
7745779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                if (length == 8) {  // aarrggbb
7755779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                    return TYPE_INT_COLOR_ARGB8;
7765779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                }
7775779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            }
7785779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) {
7795779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                return TYPE_INT_BOOLEAN;
7805779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            }
7815779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            return TYPE_INT_DEC;
7825779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        } catch (NumberFormatException ignored) {
7835779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            try {
7845779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                Float.parseFloat(value);
7855779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                return TYPE_FLOAT;
7865779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            } catch (NumberFormatException ignore) {
7875779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            }
7885779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            // Might be a dimension.
7895779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            if (ResourceHelper.parseFloatAttribute(null, value, new TypedValue(), false)) {
7905779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                return TYPE_DIMENSION;
7915779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            }
7925779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        }
7935779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        // TODO: handle fractions.
7945779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        return TYPE_STRING;
795d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta    }
796d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta
797282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
798282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Determines whether there is an attribute at <var>index</var>.
799282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
800282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param index Index of attribute to retrieve.
801282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
802282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return True if the attribute has a value, false otherwise.
803282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
804282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
805282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public boolean hasValue(int index) {
806171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        return index >= 0 && index < mResourceData.length && mResourceData[index] != null;
807282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
808282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
8099ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta    @Override
8109ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta    public boolean hasValueOrEmpty(int index) {
8119ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta        return hasValue(index) || index >= 0 && index < mResourceData.length &&
8129ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta                mEmptyIds != null && Arrays.binarySearch(mEmptyIds, index) >= 0;
8139ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta    }
8149ca97747260b9906fc3a159ce3930109022cf2ddDeepanshu Gupta
815282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
816282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Retrieve the raw TypedValue for the attribute at <var>index</var>
817282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * and return a temporary object holding its data.  This object is only
818282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * valid until the next call on to {@link TypedArray}.
819282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
820282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param index Index of attribute to retrieve.
821282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
822282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return Returns a TypedValue object if the attribute is defined,
823282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *         containing its data; otherwise returns null.  (You will not
824282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *         receive a TypedValue whose type is TYPE_NULL.)
825282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
826282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
827282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public TypedValue peekValue(int index) {
828282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (index < 0 || index >= mResourceData.length) {
829282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return null;
830282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
831282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
832282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (getValue(index, mValue)) {
833282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return mValue;
834282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
835282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
836282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return null;
837282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
838282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
839282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
840282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns a message about the parser state suitable for printing error messages.
841282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
842282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
843282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public String getPositionDescription() {
844282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return "<internal -- stub if needed>";
845282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
846282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
847282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
848282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Give back a previously retrieved TypedArray, for later re-use.
849282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
850282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
851282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void recycle() {
852282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // pass
853282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
854282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
855282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @Override
856282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public String toString() {
857282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return Arrays.toString(mResourceData);
858282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
859dc62340f18becf51f6f3c94d3994665bcd7dd537Deepanshu Gupta
860171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta    /**
861171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta     * Searches for the string in the attributes (flag or enums) and returns the integer.
862171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta     * If found, it will return an integer matching the value.
863171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta     *
864171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta     * @param index Index of attribute to retrieve.
865171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta     *
866171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta     * @return Attribute int value, or null if not defined.
867171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta     */
868171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta    private Integer resolveEnumAttribute(int index) {
869171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        // Get the map of attribute-constant -> IntegerValue
870171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        Map<String, Integer> map = null;
871171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        if (mIsFramework[index]) {
872171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            map = Bridge.getEnumValues(mNames[index]);
873171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        } else {
874171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            // get the styleable matching the resolved name
875171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            RenderResources res = mContext.getRenderResources();
876171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            ResourceValue attr = res.getProjectResource(ResourceType.ATTR, mNames[index]);
877171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            if (attr instanceof AttrResourceValue) {
878171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta                map = ((AttrResourceValue) attr).getAttributeValues();
879171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            }
880171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        }
881171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta
882171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        if (map != null) {
883171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            // accumulator to store the value of the 1+ constants.
884171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            int result = 0;
885171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            boolean found = false;
886171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta
887171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            // split the value in case this is a mix of several flags.
888171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            String[] keywords = mResourceData[index].getValue().split("\\|");
889171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            for (String keyword : keywords) {
890171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta                Integer i = map.get(keyword.trim());
891171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta                if (i != null) {
892171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta                    result |= i;
893171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta                    found = true;
894171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta                }
895171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta                // TODO: We should act smartly and log a warning for incorrect keywords. However,
896171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta                // this method is currently called even if the resourceValue is not an enum.
897171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            }
898171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            if (found) {
899171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta                return result;
900171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta            }
901171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        }
902171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta
903171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta        return null;
904171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta    }
905171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta
9065779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta    /**
9075779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta     * Copied from {@link XmlUtils#convertValueToInt(CharSequence, int)}, but adapted to account
9085779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta     * for aapt, and the fact that host Java VM's Integer.parseInt("XXXXXXXX", 16) cannot handle
9095779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta     * "XXXXXXXX" > 80000000.
9105779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta     */
9115779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta    private static int convertValueToInt(@Nullable String charSeq, int defValue) {
9120437cac76c24dc6cac7b530e6d80f789565550ecDeepanshu Gupta        if (null == charSeq || charSeq.isEmpty())
9135779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            return defValue;
9145779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta
9155779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        int sign = 1;
9165779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        int index = 0;
9175779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        int len = charSeq.length();
9185779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        int base = 10;
9195779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta
9205779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        if ('-' == charSeq.charAt(0)) {
9215779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            sign = -1;
9225779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            index++;
9235779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        }
9245779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta
9255779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        if ('0' == charSeq.charAt(index)) {
9265779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            //  Quick check for a zero by itself
9275779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            if (index == (len - 1))
9285779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                return 0;
9295779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta
9305779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            char c = charSeq.charAt(index + 1);
9315779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta
9325779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            if ('x' == c || 'X' == c) {
9335779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                index += 2;
9345779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                base = 16;
9355779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            } else {
9365779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                index++;
9375779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                // Leave the base as 10. aapt removes the preceding zero, and thus when framework
9385779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta                // sees the value, it only gets the decimal value.
9395779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            }
9405779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        } else if ('#' == charSeq.charAt(index)) {
9415779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            return ResourceHelper.getColor(charSeq) * sign;
9425779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        } else if ("true".equals(charSeq) || "TRUE".equals(charSeq)) {
9435779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            return -1;
9445779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        } else if ("false".equals(charSeq) || "FALSE".equals(charSeq)) {
9455779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta            return 0;
9465779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        }
9475779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta
9485779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        // Use Long, since we want to handle hex ints > 80000000.
9495779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta        return ((int)Long.parseLong(charSeq.substring(index), base)) * sign;
9505779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta    }
9515779ad71eabed3aabaefef1e4749693f8320816eDeepanshu Gupta
952dc62340f18becf51f6f3c94d3994665bcd7dd537Deepanshu Gupta    static TypedArray obtain(Resources res, int len) {
953e05f1c4684fcc7e3f6a429ff01b210aa19f75304Deepanshu Gupta        return new BridgeTypedArray(res, null, len, true);
954dc62340f18becf51f6f3c94d3994665bcd7dd537Deepanshu Gupta    }
955dc62340f18becf51f6f3c94d3994665bcd7dd537Deepanshu Gupta}
956