CustomBar.java revision 8930cb4f37ff0fbde65f7afd4bbe06ab77677f78
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.LayoutDirection;
29import com.android.resources.ResourceType;
30
31import org.xmlpull.v1.XmlPullParser;
32import org.xmlpull.v1.XmlPullParserException;
33
34import android.content.Context;
35import android.content.res.ColorStateList;
36import android.graphics.Bitmap;
37import android.graphics.Bitmap_Delegate;
38import android.graphics.drawable.BitmapDrawable;
39import android.graphics.drawable.Drawable;
40import android.util.TypedValue;
41import android.view.Gravity;
42import android.view.LayoutInflater;
43import android.view.View;
44import android.widget.ImageView;
45import android.widget.LinearLayout;
46import android.widget.TextView;
47
48import java.io.IOException;
49import java.io.InputStream;
50
51/**
52 * Base "bar" class for the window decor around the the edited layout.
53 * This is basically an horizontal layout that loads a given layout on creation (it is read
54 * through {@link Class#getResourceAsStream(String)}).
55 *
56 * The given layout should be a merge layout so that all the children belong to this class directly.
57 *
58 * It also provides a few utility methods to configure the content of the layout.
59 */
60abstract class CustomBar extends LinearLayout {
61
62    protected abstract TextView getStyleableTextView();
63
64    protected CustomBar(Context context, Density density, int orientation, String layoutPath,
65            String name) throws XmlPullParserException {
66        super(context);
67        setOrientation(orientation);
68        if (orientation == LinearLayout.HORIZONTAL) {
69            setGravity(Gravity.CENTER_VERTICAL);
70        } else {
71            setGravity(Gravity.CENTER_HORIZONTAL);
72        }
73
74        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
75                Context.LAYOUT_INFLATER_SERVICE);
76
77        XmlPullParser parser = ParserFactory.create(getClass().getResourceAsStream(layoutPath),
78                name);
79
80        BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser(
81                parser, (BridgeContext) context, false /*platformFile*/);
82
83        try {
84            inflater.inflate(bridgeParser, this, true);
85        } finally {
86            bridgeParser.ensurePopped();
87        }
88    }
89
90    private InputStream getIcon(String iconName, Density[] densityInOut, LayoutDirection direction,
91            String[] pathOut, boolean tryOtherDensities) {
92        // current density
93        Density density = densityInOut[0];
94
95        // bitmap url relative to this class
96        if (direction != null) {
97            pathOut[0] = "/bars/" + direction.getResourceValue() + "-" + density.getResourceValue()
98                    + "/" + iconName;
99        } else {
100            pathOut[0] = "/bars/" + density.getResourceValue() + "/" + iconName;
101        }
102
103        InputStream stream = getClass().getResourceAsStream(pathOut[0]);
104        if (stream == null && tryOtherDensities) {
105            for (Density d : Density.values()) {
106                if (d != density) {
107                    densityInOut[0] = d;
108                    stream = getIcon(iconName, densityInOut, direction, pathOut,
109                            false /*tryOtherDensities*/);
110                    if (stream != null) {
111                        return stream;
112                    }
113                }
114                // couldn't find resource with direction qualifier. try without.
115                if (direction != null) {
116                    return getIcon(iconName, densityInOut, null, pathOut, true);
117                }
118            }
119        }
120
121        return stream;
122    }
123
124    protected void loadIcon(int index, String iconName, Density density) {
125        loadIcon(index, iconName, density, false);
126    }
127
128    protected void loadIcon(int index, String iconName, Density density, boolean isRtl) {
129        View child = getChildAt(index);
130        if (child instanceof ImageView) {
131            ImageView imageView = (ImageView) child;
132
133            String[] pathOut = new String[1];
134            Density[] densityInOut = new Density[] { density };
135            LayoutDirection dir = isRtl ? LayoutDirection.RTL : LayoutDirection.LTR;
136            InputStream stream = getIcon(iconName, densityInOut, dir, pathOut,
137                    true /*tryOtherDensities*/);
138            density = densityInOut[0];
139
140            if (stream != null) {
141                // look for a cached bitmap
142                Bitmap bitmap = Bridge.getCachedBitmap(pathOut[0], true /*isFramework*/);
143                if (bitmap == null) {
144                    try {
145                        bitmap = Bitmap_Delegate.createBitmap(stream, false /*isMutable*/, density);
146                        Bridge.setCachedBitmap(pathOut[0], bitmap, true /*isFramework*/);
147                    } catch (IOException e) {
148                        return;
149                    }
150                }
151
152                if (bitmap != null) {
153                    BitmapDrawable drawable = new BitmapDrawable(getContext().getResources(),
154                            bitmap);
155                    imageView.setImageDrawable(drawable);
156                }
157            }
158        }
159    }
160
161    protected void loadIcon(int index, String iconReference) {
162        ResourceValue value = getResourceValue(iconReference);
163        if (value != null) {
164            loadIcon(index, value);
165        }
166    }
167
168    protected void loadIconById(int id, String iconReference) {
169        ResourceValue value = getResourceValue(iconReference);
170        if (value != null) {
171            loadIconById(id, value);
172        }
173    }
174
175
176    protected Drawable loadIcon(int index, ResourceType type, String name) {
177        BridgeContext bridgeContext = (BridgeContext) mContext;
178        RenderResources res = bridgeContext.getRenderResources();
179
180        // find the resource
181        ResourceValue value = res.getFrameworkResource(type, name);
182
183        // resolve it if needed
184        value = res.resolveResValue(value);
185        return loadIcon(index, value);
186    }
187
188    private Drawable loadIcon(int index, ResourceValue value) {
189        View child = getChildAt(index);
190        if (child instanceof ImageView) {
191            ImageView imageView = (ImageView) child;
192
193            return loadIcon(imageView, value);
194        }
195
196        return null;
197    }
198
199    private Drawable loadIconById(int id, ResourceValue value) {
200        View child = findViewById(id);
201        if (child instanceof ImageView) {
202            ImageView imageView = (ImageView) child;
203
204            return loadIcon(imageView, value);
205        }
206
207        return null;
208    }
209
210
211    private Drawable loadIcon(ImageView imageView, ResourceValue value) {
212        Drawable drawable = ResourceHelper.getDrawable(value, (BridgeContext) mContext);
213        if (drawable != null) {
214            imageView.setImageDrawable(drawable);
215        }
216
217        return drawable;
218    }
219
220    protected TextView setText(int index, String stringReference) {
221        View child = getChildAt(index);
222        if (child instanceof TextView) {
223            TextView textView = (TextView) child;
224            setText(textView, stringReference);
225            return textView;
226        }
227
228        return null;
229    }
230
231    protected TextView setTextById(int id, String stringReference) {
232        View child = findViewById(id);
233        if (child instanceof TextView) {
234            TextView textView = (TextView) child;
235            setText(textView, stringReference);
236            return textView;
237        }
238
239        return null;
240    }
241
242    private void setText(TextView textView, String stringReference) {
243        ResourceValue value = getResourceValue(stringReference);
244        if (value != null) {
245            textView.setText(value.getValue());
246        } else {
247            textView.setText(stringReference);
248        }
249    }
250
251    protected void setStyle(String themeEntryName) {
252
253        BridgeContext bridgeContext = (BridgeContext) mContext;
254        RenderResources res = bridgeContext.getRenderResources();
255
256        ResourceValue value = res.findItemInTheme(themeEntryName, true /*isFrameworkAttr*/);
257        value = res.resolveResValue(value);
258
259        if (value instanceof StyleResourceValue == false) {
260            return;
261        }
262
263        StyleResourceValue style = (StyleResourceValue) value;
264
265        // get the background
266        ResourceValue backgroundValue = res.findItemInStyle(style, "background",
267                true /*isFrameworkAttr*/);
268        backgroundValue = res.resolveResValue(backgroundValue);
269        if (backgroundValue != null) {
270            Drawable d = ResourceHelper.getDrawable(backgroundValue, bridgeContext);
271            if (d != null) {
272                setBackground(d);
273            }
274        }
275
276        TextView textView = getStyleableTextView();
277        if (textView != null) {
278            // get the text style
279            ResourceValue textStyleValue = res.findItemInStyle(style, "titleTextStyle",
280                    true /*isFrameworkAttr*/);
281            textStyleValue = res.resolveResValue(textStyleValue);
282            if (textStyleValue instanceof StyleResourceValue) {
283                StyleResourceValue textStyle = (StyleResourceValue) textStyleValue;
284
285                ResourceValue textSize = res.findItemInStyle(textStyle, "textSize",
286                        true /*isFrameworkAttr*/);
287                textSize = res.resolveResValue(textSize);
288
289                if (textSize != null) {
290                    TypedValue out = new TypedValue();
291                    if (ResourceHelper.parseFloatAttribute("textSize", textSize.getValue(), out,
292                            true /*requireUnit*/)) {
293                        textView.setTextSize(
294                                out.getDimension(bridgeContext.getResources().getDisplayMetrics()));
295                    }
296                }
297
298
299                ResourceValue textColor = res.findItemInStyle(textStyle, "textColor",
300                        true /*isFrameworkAttr*/);
301                textColor = res.resolveResValue(textColor);
302                if (textColor != null) {
303                    ColorStateList stateList = ResourceHelper.getColorStateList(
304                            textColor, bridgeContext);
305                    if (stateList != null) {
306                        textView.setTextColor(stateList);
307                    }
308                }
309            }
310        }
311    }
312
313    private ResourceValue getResourceValue(String reference) {
314        BridgeContext bridgeContext = (BridgeContext) mContext;
315        RenderResources res = bridgeContext.getRenderResources();
316
317        // find the resource
318        ResourceValue value = res.findResValue(reference, false /*isFramework*/);
319
320        // resolve it if needed
321        return res.resolveResValue(value);
322    }
323}
324