CustomBar.java revision 04ce81113107d2bfa0b8248b13145b4cf24cb943
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.setBackgroundDrawable(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 Drawable loadIcon(int index, ResourceType type, String name) {
149        BridgeContext bridgeContext = (BridgeContext) mContext;
150        RenderResources res = bridgeContext.getRenderResources();
151
152        // find the resource
153        ResourceValue value = res.getFrameworkResource(type, name);
154
155        // resolve it if needed
156        value = res.resolveResValue(value);
157        return loadIcon(index, value);
158    }
159
160    private Drawable loadIcon(int index, ResourceValue value) {
161        View child = getChildAt(index);
162        if (child instanceof ImageView) {
163            ImageView imageView = (ImageView) child;
164
165            Drawable drawable = ResourceHelper.getDrawable(
166                    value, (BridgeContext) mContext);
167            if (drawable != null) {
168                imageView.setBackgroundDrawable(drawable);
169            }
170
171            return drawable;
172        }
173
174        return null;
175    }
176
177    protected TextView setText(int index, String stringReference) {
178        View child = getChildAt(index);
179        if (child instanceof TextView) {
180            TextView textView = (TextView) child;
181            ResourceValue value = getResourceValue(stringReference);
182            if (value != null) {
183                textView.setText(value.getValue());
184            } else {
185                textView.setText(stringReference);
186            }
187            return textView;
188        }
189
190        return null;
191    }
192
193    protected void setStyle(String themeEntryName) {
194
195        BridgeContext bridgeContext = (BridgeContext) mContext;
196        RenderResources res = bridgeContext.getRenderResources();
197
198        ResourceValue value = res.findItemInTheme(themeEntryName);
199        value = res.resolveResValue(value);
200
201        if (value instanceof StyleResourceValue == false) {
202            return;
203        }
204
205        StyleResourceValue style = (StyleResourceValue) value;
206
207        // get the background
208        ResourceValue backgroundValue = res.findItemInStyle(style, "background");
209        backgroundValue = res.resolveResValue(backgroundValue);
210        if (backgroundValue != null) {
211            Drawable d = ResourceHelper.getDrawable(backgroundValue, bridgeContext);
212            if (d != null) {
213                setBackgroundDrawable(d);
214            }
215        }
216
217        TextView textView = getStyleableTextView();
218        if (textView != null) {
219            // get the text style
220            ResourceValue textStyleValue = res.findItemInStyle(style, "titleTextStyle");
221            textStyleValue = res.resolveResValue(textStyleValue);
222            if (textStyleValue instanceof StyleResourceValue) {
223                StyleResourceValue textStyle = (StyleResourceValue) textStyleValue;
224
225                ResourceValue textSize = res.findItemInStyle(textStyle, "textSize");
226                textSize = res.resolveResValue(textSize);
227
228                if (textSize != null) {
229                    TypedValue out = new TypedValue();
230                    if (ResourceHelper.parseFloatAttribute("textSize", textSize.getValue(), out,
231                            true /*requireUnit*/)) {
232                        textView.setTextSize(
233                                out.getDimension(bridgeContext.getResources().mMetrics));
234                    }
235                }
236
237
238                ResourceValue textColor = res.findItemInStyle(textStyle, "textColor");
239                textColor = res.resolveResValue(textColor);
240                if (textColor != null) {
241                    ColorStateList stateList = ResourceHelper.getColorStateList(
242                            textColor, bridgeContext);
243                    if (stateList != null) {
244                        textView.setTextColor(stateList);
245                    }
246                }
247            }
248        }
249    }
250
251    private ResourceValue getResourceValue(String reference) {
252        BridgeContext bridgeContext = (BridgeContext) mContext;
253        RenderResources res = bridgeContext.getRenderResources();
254
255        // find the resource
256        ResourceValue value = res.findResValue(reference, false /*isFramework*/);
257
258        // resolve it if needed
259        return res.resolveResValue(value);
260    }
261}
262