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;
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
62    private final int mSimulatedPlatformVersion;
63
64    protected abstract TextView getStyleableTextView();
65
66    protected CustomBar(Context context, int orientation, String layoutPath,
67            String name, int simulatedPlatformVersion) throws XmlPullParserException {
68        super(context);
69        mSimulatedPlatformVersion = simulatedPlatformVersion;
70        setOrientation(orientation);
71        if (orientation == LinearLayout.HORIZONTAL) {
72            setGravity(Gravity.CENTER_VERTICAL);
73        } else {
74            setGravity(Gravity.CENTER_HORIZONTAL);
75        }
76
77        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
78                Context.LAYOUT_INFLATER_SERVICE);
79
80        XmlPullParser parser = ParserFactory.create(getClass().getResourceAsStream(layoutPath),
81                name);
82
83        BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser(
84                parser, (BridgeContext) context, false /*platformFile*/);
85
86        try {
87            inflater.inflate(bridgeParser, this, true);
88        } finally {
89            bridgeParser.ensurePopped();
90        }
91    }
92
93    protected void loadIcon(int index, String iconName, Density density) {
94        loadIcon(index, iconName, density, false);
95    }
96
97    protected void loadIcon(int index, String iconName, Density density, boolean isRtl) {
98        View child = getChildAt(index);
99        if (child instanceof ImageView) {
100            ImageView imageView = (ImageView) child;
101
102            LayoutDirection dir = isRtl ? LayoutDirection.RTL : null;
103            IconLoader iconLoader = new IconLoader(iconName, density, mSimulatedPlatformVersion,
104                    dir);
105            InputStream stream = iconLoader.getIcon();
106
107            if (stream != null) {
108                density = iconLoader.getDensity();
109                String path = iconLoader.getPath();
110                // look for a cached bitmap
111                Bitmap bitmap = Bridge.getCachedBitmap(path, true /*isFramework*/);
112                if (bitmap == null) {
113                    try {
114                        bitmap = Bitmap_Delegate.createBitmap(stream, false /*isMutable*/, density);
115                        Bridge.setCachedBitmap(path, bitmap, true /*isFramework*/);
116                    } catch (IOException e) {
117                        return;
118                    }
119                }
120
121                if (bitmap != null) {
122                    BitmapDrawable drawable = new BitmapDrawable(getContext().getResources(),
123                            bitmap);
124                    imageView.setImageDrawable(drawable);
125                }
126            }
127        }
128    }
129
130    protected TextView setText(int index, String string, boolean reference) {
131        View child = getChildAt(index);
132        if (child instanceof TextView) {
133            TextView textView = (TextView) child;
134            setText(textView, string, reference);
135            return textView;
136        }
137
138        return null;
139    }
140
141    private void setText(TextView textView, String string, boolean reference) {
142        if (reference) {
143            ResourceValue value = getResourceValue(string);
144            if (value != null) {
145                string = value.getValue();
146            }
147        }
148        textView.setText(string);
149    }
150
151    protected void setStyle(String themeEntryName) {
152
153        BridgeContext bridgeContext = (BridgeContext) mContext;
154        RenderResources res = bridgeContext.getRenderResources();
155
156        ResourceValue value = res.findItemInTheme(themeEntryName, true /*isFrameworkAttr*/);
157        value = res.resolveResValue(value);
158
159        if (!(value instanceof StyleResourceValue)) {
160            return;
161        }
162
163        StyleResourceValue style = (StyleResourceValue) value;
164
165        // get the background
166        ResourceValue backgroundValue = res.findItemInStyle(style, "background",
167                true /*isFrameworkAttr*/);
168        backgroundValue = res.resolveResValue(backgroundValue);
169        if (backgroundValue != null) {
170            Drawable d = ResourceHelper.getDrawable(backgroundValue, bridgeContext);
171            if (d != null) {
172                setBackground(d);
173            }
174        }
175
176        TextView textView = getStyleableTextView();
177        if (textView != null) {
178            // get the text style
179            ResourceValue textStyleValue = res.findItemInStyle(style, "titleTextStyle",
180                    true /*isFrameworkAttr*/);
181            textStyleValue = res.resolveResValue(textStyleValue);
182            if (textStyleValue instanceof StyleResourceValue) {
183                StyleResourceValue textStyle = (StyleResourceValue) textStyleValue;
184
185                ResourceValue textSize = res.findItemInStyle(textStyle, "textSize",
186                        true /*isFrameworkAttr*/);
187                textSize = res.resolveResValue(textSize);
188
189                if (textSize != null) {
190                    TypedValue out = new TypedValue();
191                    if (ResourceHelper.parseFloatAttribute("textSize", textSize.getValue(), out,
192                            true /*requireUnit*/)) {
193                        textView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
194                                out.getDimension(bridgeContext.getResources().getDisplayMetrics()));
195                    }
196                }
197
198
199                ResourceValue textColor = res.findItemInStyle(textStyle, "textColor",
200                        true /*isFrameworkAttr*/);
201                textColor = res.resolveResValue(textColor);
202                if (textColor != null) {
203                    ColorStateList stateList = ResourceHelper.getColorStateList(
204                            textColor, bridgeContext);
205                    if (stateList != null) {
206                        textView.setTextColor(stateList);
207                    }
208                }
209            }
210        }
211    }
212
213    private ResourceValue getResourceValue(String reference) {
214        BridgeContext bridgeContext = (BridgeContext) mContext;
215        RenderResources res = bridgeContext.getRenderResources();
216
217        // find the resource
218        ResourceValue value = res.findResValue(reference, false /*isFramework*/);
219
220        // resolve it if needed
221        return res.resolveResValue(value);
222    }
223}
224