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.LayoutDirection;
     29 import com.android.resources.ResourceType;
     30 
     31 import org.xmlpull.v1.XmlPullParser;
     32 import org.xmlpull.v1.XmlPullParserException;
     33 
     34 import android.content.Context;
     35 import android.content.res.ColorStateList;
     36 import android.graphics.Bitmap;
     37 import android.graphics.Bitmap_Delegate;
     38 import android.graphics.drawable.BitmapDrawable;
     39 import android.graphics.drawable.Drawable;
     40 import android.util.TypedValue;
     41 import android.view.Gravity;
     42 import android.view.LayoutInflater;
     43 import android.view.View;
     44 import android.widget.ImageView;
     45 import android.widget.LinearLayout;
     46 import android.widget.TextView;
     47 
     48 import java.io.IOException;
     49 import 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  */
     60 abstract 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             }
    115             // couldn't find resource with direction qualifier. try without.
    116             if (direction != null) {
    117                 return getIcon(iconName, densityInOut, null, pathOut, true);
    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(TypedValue.COMPLEX_UNIT_PX,
    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