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