CustomBar.java revision 01b6c755dbcf24e71192dc44757e2eea2a426091
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.layoutlib.bridge.bars;
18
19import com.android.ide.common.rendering.api.RenderResources;
20import com.android.ide.common.rendering.api.ResourceValue;
21import com.android.ide.common.rendering.api.StyleResourceValue;
22import com.android.layoutlib.bridge.Bridge;
23import com.android.layoutlib.bridge.android.BridgeContext;
24import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
25import com.android.layoutlib.bridge.impl.ParserFactory;
26import com.android.layoutlib.bridge.impl.ResourceHelper;
27import com.android.resources.Density;
28import com.android.resources.ResourceType;
29
30import org.xmlpull.v1.XmlPullParser;
31import org.xmlpull.v1.XmlPullParserException;
32
33import android.content.Context;
34import android.content.res.ColorStateList;
35import android.graphics.Bitmap;
36import android.graphics.Bitmap_Delegate;
37import android.graphics.drawable.BitmapDrawable;
38import android.graphics.drawable.Drawable;
39import android.util.TypedValue;
40import android.view.Gravity;
41import android.view.LayoutInflater;
42import android.view.View;
43import android.widget.ImageView;
44import android.widget.LinearLayout;
45import android.widget.TextView;
46
47import java.io.IOException;
48import java.io.InputStream;
49
50/**
51 * Base "bar" class for the window decor around the the edited layout.
52 * This is basically an horizontal layout that loads a given layout on creation (it is read
53 * through {@link Class#getResourceAsStream(String)}).
54 *
55 * The given layout should be a merge layout so that all the children belong to this class directly.
56 *
57 * It also provides a few utility methods to configure the content of the layout.
58 */
59abstract class CustomBar extends LinearLayout {
60
61    protected abstract TextView getStyleableTextView();
62
63    protected CustomBar(Context context, Density density, String layoutPath, String name)
64            throws XmlPullParserException {
65        super(context);
66        setOrientation(LinearLayout.HORIZONTAL);
67        setGravity(Gravity.CENTER_VERTICAL);
68
69        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
70                Context.LAYOUT_INFLATER_SERVICE);
71
72        XmlPullParser parser = ParserFactory.create(getClass().getResourceAsStream(layoutPath),
73                name);
74
75        BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser(
76                parser, (BridgeContext) context, false /*platformFile*/);
77
78        try {
79            inflater.inflate(bridgeParser, this, true);
80        } finally {
81            bridgeParser.ensurePopped();
82        }
83    }
84
85    private InputStream getIcon(String iconName, Density[] densityInOut, String[] pathOut,
86            boolean tryOtherDensities) {
87        // current density
88        Density density = densityInOut[0];
89
90        // bitmap url relative to this class
91        pathOut[0] = "/bars/" + density.getResourceValue() + "/" + iconName;
92
93        InputStream stream = getClass().getResourceAsStream(pathOut[0]);
94        if (stream == null && tryOtherDensities) {
95            for (Density d : Density.values()) {
96                if (d != density) {
97                    densityInOut[0] = d;
98                    stream = getIcon(iconName, densityInOut, pathOut, false /*tryOtherDensities*/);
99                    if (stream != null) {
100                        return stream;
101                    }
102                }
103            }
104        }
105
106        return stream;
107    }
108
109    protected void loadIcon(int index, String iconName, Density density) {
110        View child = getChildAt(index);
111        if (child instanceof ImageView) {
112            ImageView imageView = (ImageView) child;
113
114            String[] pathOut = new String[1];
115            Density[] densityInOut = new Density[] { density };
116            InputStream stream = getIcon(iconName, densityInOut, pathOut,
117                    true /*tryOtherDensities*/);
118            density = densityInOut[0];
119
120            if (stream != null) {
121                // look for a cached bitmap
122                Bitmap bitmap = Bridge.getCachedBitmap(pathOut[0], true /*isFramework*/);
123                if (bitmap == null) {
124                    try {
125                        bitmap = Bitmap_Delegate.createBitmap(stream, false /*isMutable*/, density);
126                        Bridge.setCachedBitmap(pathOut[0], bitmap, true /*isFramework*/);
127                    } catch (IOException e) {
128                        return;
129                    }
130                }
131
132                if (bitmap != null) {
133                    BitmapDrawable drawable = new BitmapDrawable(getContext().getResources(),
134                            bitmap);
135                    imageView.setImageDrawable(drawable);
136                }
137            }
138        }
139    }
140
141    protected void loadIcon(int index, String iconReference) {
142        ResourceValue value = getResourceValue(iconReference);
143        if (value != null) {
144            loadIcon(index, value);
145        }
146    }
147
148    protected void loadIconById(int id, String iconReference) {
149        ResourceValue value = getResourceValue(iconReference);
150        if (value != null) {
151            loadIconById(id, value);
152        }
153    }
154
155
156    protected Drawable loadIcon(int index, ResourceType type, String name) {
157        BridgeContext bridgeContext = (BridgeContext) mContext;
158        RenderResources res = bridgeContext.getRenderResources();
159
160        // find the resource
161        ResourceValue value = res.getFrameworkResource(type, name);
162
163        // resolve it if needed
164        value = res.resolveResValue(value);
165        return loadIcon(index, value);
166    }
167
168    private Drawable loadIcon(int index, ResourceValue value) {
169        View child = getChildAt(index);
170        if (child instanceof ImageView) {
171            ImageView imageView = (ImageView) child;
172
173            return loadIcon(imageView, value);
174        }
175
176        return null;
177    }
178
179    private Drawable loadIconById(int id, ResourceValue value) {
180        View child = findViewById(id);
181        if (child instanceof ImageView) {
182            ImageView imageView = (ImageView) child;
183
184            return loadIcon(imageView, value);
185        }
186
187        return null;
188    }
189
190
191    private Drawable loadIcon(ImageView imageView, ResourceValue value) {
192        Drawable drawable = ResourceHelper.getDrawable(value, (BridgeContext) mContext);
193        if (drawable != null) {
194            imageView.setImageDrawable(drawable);
195        }
196
197        return drawable;
198    }
199
200    protected TextView setText(int index, String stringReference) {
201        View child = getChildAt(index);
202        if (child instanceof TextView) {
203            TextView textView = (TextView) child;
204            setText(textView, stringReference);
205            return textView;
206        }
207
208        return null;
209    }
210
211    protected TextView setTextById(int id, String stringReference) {
212        View child = findViewById(id);
213        if (child instanceof TextView) {
214            TextView textView = (TextView) child;
215            setText(textView, stringReference);
216            return textView;
217        }
218
219        return null;
220    }
221
222    private void setText(TextView textView, String stringReference) {
223        ResourceValue value = getResourceValue(stringReference);
224        if (value != null) {
225            textView.setText(value.getValue());
226        } else {
227            textView.setText(stringReference);
228        }
229    }
230
231    protected void setStyle(String themeEntryName) {
232
233        BridgeContext bridgeContext = (BridgeContext) mContext;
234        RenderResources res = bridgeContext.getRenderResources();
235
236        ResourceValue value = res.findItemInTheme(themeEntryName, true /*isFrameworkAttr*/);
237        value = res.resolveResValue(value);
238
239        if (value instanceof StyleResourceValue == false) {
240            return;
241        }
242
243        StyleResourceValue style = (StyleResourceValue) value;
244
245        // get the background
246        ResourceValue backgroundValue = res.findItemInStyle(style, "background",
247                true /*isFrameworkAttr*/);
248        backgroundValue = res.resolveResValue(backgroundValue);
249        if (backgroundValue != null) {
250            Drawable d = ResourceHelper.getDrawable(backgroundValue, bridgeContext);
251            if (d != null) {
252                setBackground(d);
253            }
254        }
255
256        TextView textView = getStyleableTextView();
257        if (textView != null) {
258            // get the text style
259            ResourceValue textStyleValue = res.findItemInStyle(style, "titleTextStyle",
260                    true /*isFrameworkAttr*/);
261            textStyleValue = res.resolveResValue(textStyleValue);
262            if (textStyleValue instanceof StyleResourceValue) {
263                StyleResourceValue textStyle = (StyleResourceValue) textStyleValue;
264
265                ResourceValue textSize = res.findItemInStyle(textStyle, "textSize",
266                        true /*isFrameworkAttr*/);
267                textSize = res.resolveResValue(textSize);
268
269                if (textSize != null) {
270                    TypedValue out = new TypedValue();
271                    if (ResourceHelper.parseFloatAttribute("textSize", textSize.getValue(), out,
272                            true /*requireUnit*/)) {
273                        textView.setTextSize(
274                                out.getDimension(bridgeContext.getResources().getDisplayMetrics()));
275                    }
276                }
277
278
279                ResourceValue textColor = res.findItemInStyle(textStyle, "textColor",
280                        true /*isFrameworkAttr*/);
281                textColor = res.resolveResValue(textColor);
282                if (textColor != null) {
283                    ColorStateList stateList = ResourceHelper.getColorStateList(
284                            textColor, bridgeContext);
285                    if (stateList != null) {
286                        textView.setTextColor(stateList);
287                    }
288                }
289            }
290        }
291    }
292
293    private ResourceValue getResourceValue(String reference) {
294        BridgeContext bridgeContext = (BridgeContext) mContext;
295        RenderResources res = bridgeContext.getRenderResources();
296
297        // find the resource
298        ResourceValue value = res.findResValue(reference, false /*isFramework*/);
299
300        // resolve it if needed
301        return res.resolveResValue(value);
302    }
303}
304