Home | History | Annotate | Download | only in bars
      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 
     17 package com.android.layoutlib.bridge.bars;
     18 
     19 import com.android.ide.common.rendering.api.RenderResources;
     20 import com.android.ide.common.rendering.api.ResourceValue;
     21 import com.android.ide.common.rendering.api.StyleResourceValue;
     22 import com.android.layoutlib.bridge.Bridge;
     23 import com.android.layoutlib.bridge.android.BridgeContext;
     24 import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
     25 import com.android.layoutlib.bridge.impl.ParserFactory;
     26 import com.android.layoutlib.bridge.impl.ResourceHelper;
     27 import com.android.resources.Density;
     28 import com.android.resources.ResourceType;
     29 
     30 import org.xmlpull.v1.XmlPullParser;
     31 import org.xmlpull.v1.XmlPullParserException;
     32 
     33 import android.content.Context;
     34 import android.content.res.ColorStateList;
     35 import android.graphics.Bitmap;
     36 import android.graphics.Bitmap_Delegate;
     37 import android.graphics.drawable.BitmapDrawable;
     38 import android.graphics.drawable.Drawable;
     39 import android.util.TypedValue;
     40 import android.view.Gravity;
     41 import android.view.LayoutInflater;
     42 import android.view.View;
     43 import android.widget.ImageView;
     44 import android.widget.LinearLayout;
     45 import android.widget.TextView;
     46 
     47 import java.io.IOException;
     48 import 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  */
     59 abstract 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().getDisplayMetrics()));
    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