summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@android.com>2011-01-27 16:58:52 -0800
committerXavier Ducrohet <xav@android.com>2011-02-04 10:46:21 -0800
commitbbbb8326020368958a3f1d248878329e9d6b10c0 (patch)
tree74ec16b151a74dec647b657a68f83f1a178b4183 /tools
parente8d2b98526e7666b175b4df58b646ed56a572bb0 (diff)
downloadframeworks_base-bbbb8326020368958a3f1d248878329e9d6b10c0.zip
frameworks_base-bbbb8326020368958a3f1d248878329e9d6b10c0.tar.gz
frameworks_base-bbbb8326020368958a3f1d248878329e9d6b10c0.tar.bz2
LayoutLib: render system/title/action bars.
Also a few generic fixes in the layoutlib itself to support this. Change-Id: Ie3f24c9056bd3cc72f39f8a4f2c0861be15bff55
Diffstat (limited to 'tools')
-rw-r--r--tools/layoutlib/bridge/Android.mk2
-rw-r--r--tools/layoutlib/bridge/resources/bars/action_bar.xml11
-rw-r--r--tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.pngbin0 -> 3900 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.pngbin0 -> 3991 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.pngbin0 -> 3140 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/mdpi/stat_sys_wifi_signal_4_fully.pngbin0 -> 885 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/phone_system_bar.xml12
-rw-r--r--tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml20
-rw-r--r--tools/layoutlib/bridge/resources/bars/title_bar.xml7
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java29
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java14
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java10
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java78
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java2
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java212
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java47
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java42
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java45
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java46
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java323
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java71
21 files changed, 770 insertions, 201 deletions
diff --git a/tools/layoutlib/bridge/Android.mk b/tools/layoutlib/bridge/Android.mk
index 3d4c76a..ca7db8c 100644
--- a/tools/layoutlib/bridge/Android.mk
+++ b/tools/layoutlib/bridge/Android.mk
@@ -17,6 +17,8 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-java-files-under,src)
+LOCAL_JAVA_RESOURCE_DIRS := resources
+
LOCAL_JAVA_LIBRARIES := \
kxml2-2.3.0 \
diff --git a/tools/layoutlib/bridge/resources/bars/action_bar.xml b/tools/layoutlib/bridge/resources/bars/action_bar.xml
new file mode 100644
index 0000000..cd99a09
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/action_bar.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <ImageView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"/>
+</merge>
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png
new file mode 100644
index 0000000..4bcd2be
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png
new file mode 100644
index 0000000..cfeba3e
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png
new file mode 100644
index 0000000..1d97e05
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/mdpi/stat_sys_wifi_signal_4_fully.png
new file mode 100644
index 0000000..c629387
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/stat_sys_wifi_signal_4_fully.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml b/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml
new file mode 100644
index 0000000..29df909
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text=" "/>
+ <ImageView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center"/>
+</merge>
diff --git a/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml b/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml
new file mode 100644
index 0000000..8a3b87a
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <ImageView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"/>
+ <ImageView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"/>
+ <ImageView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"/>
+ <ImageView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center"/>
+</merge>
diff --git a/tools/layoutlib/bridge/resources/bars/title_bar.xml b/tools/layoutlib/bridge/resources/bars/title_bar.xml
new file mode 100644
index 0000000..29fcc4b
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/title_bar.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"/>
+</merge>
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
index 993c305..ee60eb4 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
@@ -18,6 +18,9 @@ package android.graphics;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.android.BridgeResources.NinePatchInputStream;
+import com.android.ninepatch.NinePatch;
+import com.android.ninepatch.NinePatchChunk;
import com.android.resources.Density;
import android.content.res.AssetManager;
@@ -438,6 +441,8 @@ public class BitmapFactory {
return null;
}
+ boolean isNinePatch = is instanceof NinePatchInputStream;
+
// we need mark/reset to work properly
if (!is.markSupported()) {
@@ -466,7 +471,29 @@ public class BitmapFactory {
if (opts != null) {
density = Density.getEnum(opts.inDensity);
}
- bm = Bitmap_Delegate.createBitmap(is, true, density);
+
+ if (isNinePatch) {
+ // load the bitmap as a nine patch
+ NinePatch ninePatch = NinePatch.load(is, true /*is9Patch*/, false /*convert*/);
+
+ // get the bitmap and chunk objects.
+ bm = Bitmap_Delegate.createBitmap(ninePatch.getImage(), true /*isMutable*/,
+ density);
+ NinePatchChunk chunk = ninePatch.getChunk();
+
+ // put the chunk in the bitmap
+ bm.setNinePatchChunk(NinePatch_Delegate.serialize(chunk));
+
+ // read the padding
+ int[] padding = chunk.getPadding();
+ outPadding.left = padding[0];
+ outPadding.top = padding[1];
+ outPadding.right = padding[2];
+ outPadding.bottom = padding[3];
+ } else {
+ // load the bitmap directly.
+ bm = Bitmap_Delegate.createBitmap(is, true, density);
+ }
} catch (IOException e) {
return null;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 93c81d1..65f6bed 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -21,7 +21,7 @@ import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
import com.android.ide.common.rendering.api.Capability;
import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.Params;
+import com.android.ide.common.rendering.api.RenderParams;
import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.Result;
import com.android.layoutlib.bridge.android.BridgeAssetManager;
@@ -293,15 +293,15 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
/**
* Starts a layout session by inflating and rendering it. The method returns a
- * {@link ILayoutScene} on which further actions can be taken.
+ * {@link RenderSession} on which further actions can be taken.
*
- * @param params the {@link SceneParams} object with all the information necessary to create
+ * @param params the {@link RenderParams} object with all the information necessary to create
* the scene.
- * @return a new {@link ILayoutScene} object that contains the result of the layout.
+ * @return a new {@link RenderSession} object that contains the result of the layout.
* @since 5
*/
@Override
- public RenderSession createSession(Params params) {
+ public RenderSession createSession(RenderParams params) {
try {
Result lastResult = SUCCESS.createResult();
RenderSessionImpl scene = new RenderSessionImpl(params);
@@ -331,10 +331,6 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
}
}
- /*
- * (non-Javadoc)
- * @see com.android.layoutlib.api.ILayoutLibBridge#clearCaches(java.lang.Object)
- */
@Override
public void clearCaches(Object projectKey) {
if (projectKey != null) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
index 0c6fa20..765fd99 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
@@ -18,7 +18,7 @@ package com.android.layoutlib.bridge;
import com.android.ide.common.rendering.api.IAnimationListener;
import com.android.ide.common.rendering.api.ILayoutPullParser;
-import com.android.ide.common.rendering.api.Params;
+import com.android.ide.common.rendering.api.RenderParams;
import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.Result;
import com.android.ide.common.rendering.api.ViewInfo;
@@ -128,7 +128,7 @@ public class BridgeRenderSession extends RenderSession {
boolean isFrameworkAnimation, IAnimationListener listener) {
try {
Bridge.prepareThread();
- mLastResult = mSession.acquire(Params.DEFAULT_TIMEOUT);
+ mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
if (mLastResult.isSuccess()) {
mLastResult = mSession.animate(targetObject, animationName, isFrameworkAnimation,
listener);
@@ -150,7 +150,7 @@ public class BridgeRenderSession extends RenderSession {
try {
Bridge.prepareThread();
- mLastResult = mSession.acquire(Params.DEFAULT_TIMEOUT);
+ mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
if (mLastResult.isSuccess()) {
mLastResult = mSession.insertChild((ViewGroup) parentView, childXml, index,
listener);
@@ -176,7 +176,7 @@ public class BridgeRenderSession extends RenderSession {
try {
Bridge.prepareThread();
- mLastResult = mSession.acquire(Params.DEFAULT_TIMEOUT);
+ mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
if (mLastResult.isSuccess()) {
mLastResult = mSession.moveChild((ViewGroup) parentView, (View) childView, index,
layoutParams, listener);
@@ -197,7 +197,7 @@ public class BridgeRenderSession extends RenderSession {
try {
Bridge.prepareThread();
- mLastResult = mSession.acquire(Params.DEFAULT_TIMEOUT);
+ mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
if (mLastResult.isSuccess()) {
mLastResult = mSession.removeChild((View) childView, listener);
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
index 5ea0a8d..d31fcc8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
@@ -22,6 +22,7 @@ import com.android.ide.common.rendering.api.ResourceValue;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.BridgeConstants;
import com.android.layoutlib.bridge.impl.ResourceHelper;
+import com.android.ninepatch.NinePatch;
import com.android.resources.ResourceType;
import com.android.util.Pair;
@@ -58,6 +59,18 @@ public final class BridgeResources extends Resources {
private boolean[] mPlatformResourceFlag = new boolean[1];
/**
+ * Simpler wrapper around FileInputStream. This is used when the input stream represent
+ * not a normal bitmap but a nine patch.
+ * This is useful when the InputStream is created in a method but used in another that needs
+ * to know whether this is 9-patch or not, such as BitmapFactory.
+ */
+ public class NinePatchInputStream extends FileInputStream {
+ public NinePatchInputStream(File file) throws FileNotFoundException {
+ super(file);
+ }
+ }
+
+ /**
* This initializes the static field {@link Resources#mSystem} which is used
* by methods who get global resources using {@link Resources#getSystem()}.
* <p/>
@@ -129,7 +142,7 @@ public final class BridgeResources extends Resources {
ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
- return ResourceHelper.getDrawable(value, mContext, value.isFramework());
+ return ResourceHelper.getDrawable(value, mContext);
}
// id was not found or not resolved. Throw a NotFoundException.
@@ -165,44 +178,9 @@ public final class BridgeResources extends Resources {
ResourceValue resValue = getResourceValue(id, mPlatformResourceFlag);
if (resValue != null) {
- String value = resValue.getValue();
- if (value != null) {
- // first check if the value is a file (xml most likely)
- File f = new File(value);
- if (f.isFile()) {
- try {
- // let the framework inflate the ColorStateList from the XML file, by
- // providing an XmlPullParser
- KXmlParser parser = new KXmlParser();
- parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
- parser.setInput(new FileReader(f));
-
- return ColorStateList.createFromXml(this,
- new BridgeXmlBlockParser(parser, mContext, resValue.isFramework()));
- } catch (XmlPullParserException e) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Failed to configure parser for " + value, e, null /*data*/);
- // we'll return null below.
- } catch (Exception e) {
- // this is an error and not warning since the file existence is
- // checked before attempting to parse it.
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
- "Failed to parse file " + value, e, null /*data*/);
-
- return null;
- }
- } else {
- // try to load the color state list from an int
- try {
- int color = ResourceHelper.getColor(value);
- return ColorStateList.valueOf(color);
- } catch (NumberFormatException e) {
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
- "Failed to convert " + value + " into a ColorStateList", e,
- null /*data*/);
- return null;
- }
- }
+ ColorStateList stateList = ResourceHelper.getColorStateList(resValue, mContext);
+ if (stateList != null) {
+ return stateList;
}
}
@@ -562,13 +540,19 @@ public final class BridgeResources extends Resources {
ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
- String v = value.getValue();
+ String path = value.getValue();
- if (v != null) {
+ if (path != null) {
// check this is a file
- File f = new File(value.getValue());
+ File f = new File(path);
if (f.isFile()) {
try {
+ // if it's a nine-patch return a custom input stream so that
+ // other methods (mainly bitmap factory) can detect it's a 9-patch
+ // and actually load it as a 9-patch instead of a normal bitmap
+ if (path.toLowerCase().endsWith(NinePatch.EXTENSION_9PATCH)) {
+ return new NinePatchInputStream(f);
+ }
return new FileInputStream(f);
} catch (FileNotFoundException e) {
NotFoundException newE = new NotFoundException();
@@ -590,9 +574,17 @@ public final class BridgeResources extends Resources {
public InputStream openRawResource(int id, TypedValue value) throws NotFoundException {
getValue(id, value, true);
- File f = new File(value.string.toString());
+ String path = value.string.toString();
+
+ File f = new File(path);
if (f.isFile()) {
try {
+ // if it's a nine-patch return a custom input stream so that
+ // other methods (mainly bitmap factory) can detect it's a 9-patch
+ // and actually load it as a 9-patch instead of a normal bitmap
+ if (path.toLowerCase().endsWith(NinePatch.EXTENSION_9PATCH)) {
+ return new NinePatchInputStream(f);
+ }
return new FileInputStream(f);
} catch (FileNotFoundException e) {
NotFoundException exception = new NotFoundException();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
index cf2c0ff..c226b8b 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
@@ -690,7 +690,7 @@ public final class BridgeTypedArray extends TypedArray {
return null;
}
- return ResourceHelper.getDrawable(value, mContext, mResourceData[index].isFramework());
+ return ResourceHelper.getDrawable(value, mContext);
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
new file mode 100644
index 0000000..f039994
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.bars;
+
+import com.android.ide.common.rendering.api.RenderResources;
+import com.android.ide.common.rendering.api.ResourceValue;
+import com.android.ide.common.rendering.api.StyleResourceValue;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
+import com.android.layoutlib.bridge.impl.ResourceHelper;
+import com.android.resources.Density;
+
+import org.kxml2.io.KXmlParser;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap_Delegate;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Base "bar" class for the window decor around the the edited layout.
+ * This is basically an horizontal layout that loads a given layout on creation (it is read
+ * through {@link Class#getResourceAsStream(String)}).
+ *
+ * The given layout should be a merge layout so that all the children belong to this class directly.
+ *
+ * It also provides a few utility methods to configure the content of the layout.
+ */
+abstract class CustomBar extends LinearLayout {
+
+ protected abstract TextView getStyleableTextView();
+
+ protected CustomBar(Context context, Density density, String layoutPath)
+ throws XmlPullParserException {
+ super(context);
+ setOrientation(LinearLayout.HORIZONTAL);
+ setBackgroundColor(0xFF000000);
+
+ LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+
+ KXmlParser parser = new KXmlParser();
+ parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
+ parser.setInput(
+ getClass().getResourceAsStream(layoutPath),
+ "UTF8");
+
+ BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser(
+ parser, (BridgeContext) context, false);
+
+ inflater.inflate(bridgeParser, this, true);
+ }
+
+ protected void loadIcon(int index, String iconName, Density density) {
+ View child = getChildAt(index);
+ if (child instanceof ImageView) {
+ ImageView imageView = (ImageView) child;
+
+ // bitmap url relative to this class
+ String path = "/bars/" + density.getResourceValue() + "/" + iconName;
+
+ // create a bitmap
+ Bitmap bitmap = Bridge.getCachedBitmap(path, true /*isFramework*/);
+
+ if (bitmap == null) {
+ InputStream stream = getClass().getResourceAsStream(path);
+
+ if (stream != null) {
+ try {
+ bitmap = Bitmap_Delegate.createBitmap(stream, false /*isMutable*/, density);
+ Bridge.setCachedBitmap(path, bitmap, true /*isFramework*/);
+ } catch (IOException e) {
+ return;
+ }
+ }
+ }
+
+ if (bitmap != null) {
+ BitmapDrawable drawable = new BitmapDrawable(getContext().getResources(), bitmap);
+ imageView.setBackgroundDrawable(drawable);
+ }
+ }
+ }
+
+ protected void loadIcon(int index, String iconReference) {
+ ResourceValue value = getResourceValue(iconReference);
+ if (value != null) {
+ View child = getChildAt(index);
+ if (child instanceof ImageView) {
+ ImageView imageView = (ImageView) child;
+
+ Drawable drawable = ResourceHelper.getDrawable(
+ value, (BridgeContext) mContext);
+ if (drawable != null) {
+ imageView.setBackgroundDrawable(drawable);
+ }
+ }
+ }
+ }
+
+ protected TextView setText(int index, String stringReference) {
+ View child = getChildAt(index);
+ if (child instanceof TextView) {
+ TextView textView = (TextView) child;
+ ResourceValue value = getResourceValue(stringReference);
+ if (value != null) {
+ textView.setText(value.getValue());
+ } else {
+ textView.setText(stringReference);
+ }
+ return textView;
+ }
+
+ return null;
+ }
+
+ protected void setStyle(String themeEntryName) {
+
+ BridgeContext bridgeContext = (BridgeContext) mContext;
+ RenderResources res = bridgeContext.getRenderResources();
+
+ ResourceValue value = res.findItemInTheme(themeEntryName);
+ value = res.resolveResValue(value);
+
+ if (value instanceof StyleResourceValue == false) {
+ return;
+ }
+
+ StyleResourceValue style = (StyleResourceValue) value;
+
+ // get the background
+ ResourceValue backgroundValue = res.findItemInStyle(style, "background");
+ backgroundValue = res.resolveResValue(backgroundValue);
+ if (backgroundValue != null) {
+ Drawable d = ResourceHelper.getDrawable(backgroundValue, bridgeContext);
+ if (d != null) {
+ setBackgroundDrawable(d);
+ }
+ }
+
+ TextView textView = getStyleableTextView();
+ if (textView != null) {
+ // get the text style
+ ResourceValue textStyleValue = res.findItemInStyle(style, "titleTextStyle");
+ textStyleValue = res.resolveResValue(textStyleValue);
+ if (textStyleValue instanceof StyleResourceValue) {
+ StyleResourceValue textStyle = (StyleResourceValue) textStyleValue;
+
+ ResourceValue textSize = res.findItemInStyle(textStyle, "textSize");
+ textSize = res.resolveResValue(textSize);
+
+ if (textSize != null) {
+ TypedValue out = new TypedValue();
+ if (ResourceHelper.stringToFloat(textSize.getValue(), out)) {
+ textView.setTextSize(
+ out.getDimension(bridgeContext.getResources().mMetrics));
+ }
+ }
+
+
+ ResourceValue textColor = res.findItemInStyle(textStyle, "textColor");
+ textColor = res.resolveResValue(textColor);
+ if (textColor != null) {
+ ColorStateList stateList = ResourceHelper.getColorStateList(
+ textColor, bridgeContext);
+ if (stateList != null) {
+ textView.setTextColor(stateList);
+ }
+ }
+ }
+ }
+ }
+
+ private ResourceValue getResourceValue(String reference) {
+ BridgeContext bridgeContext = (BridgeContext) mContext;
+ RenderResources res = bridgeContext.getRenderResources();
+
+ // find the resource
+ ResourceValue value = res.findResValue(reference, false /*isFramework*/);
+
+ // resolve it if needed
+ return res.resolveResValue(value);
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java
new file mode 100644
index 0000000..3af4e3a
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.bars;
+
+import com.android.resources.Density;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.widget.TextView;
+
+public class FakeActionBar extends CustomBar {
+
+ private TextView mTextView;
+
+ public FakeActionBar(Context context, Density density, String label, String icon)
+ throws XmlPullParserException {
+ super(context, density, "/bars/action_bar.xml");
+
+ // Cannot access the inside items through id because no R.id values have been
+ // created for them.
+ // We do know the order though.
+ loadIcon(0, icon);
+ mTextView = setText(1, label);
+
+ setStyle("actionBarStyle");
+ }
+
+ @Override
+ protected TextView getStyleableTextView() {
+ return mTextView;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java
new file mode 100644
index 0000000..92615dc
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.bars;
+
+import com.android.resources.Density;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.widget.TextView;
+
+public class PhoneSystemBar extends CustomBar {
+
+ public PhoneSystemBar(Context context, Density density) throws XmlPullParserException {
+ super(context, density, "/bars/tablet_system_bar.xml");
+
+ // Cannot access the inside items through id because no R.id values have been
+ // created for them.
+ // We do know the order though.
+ // 0 is the spacer
+ loadIcon(1, "stat_sys_wifi_signal_4_fully.png", density);
+ }
+
+ @Override
+ protected TextView getStyleableTextView() {
+ return null;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java
new file mode 100644
index 0000000..bc61799
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.bars;
+
+import com.android.resources.Density;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.widget.TextView;
+
+public class TabletSystemBar extends CustomBar {
+
+ public TabletSystemBar(Context context, Density density) throws XmlPullParserException {
+ super(context, density, "/bars/tablet_system_bar.xml");
+
+ // Cannot access the inside items through id because no R.id values have been
+ // created for them.
+ // We do know the order though.
+ loadIcon(0, "ic_sysbar_back_default.png", density);
+ loadIcon(1, "ic_sysbar_home_default.png", density);
+ loadIcon(2, "ic_sysbar_recent_default.png", density);
+ // 3 is the spacer
+ loadIcon(4, "stat_sys_wifi_signal_4_fully.png", density);
+ }
+
+ @Override
+ protected TextView getStyleableTextView() {
+ return null;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
new file mode 100644
index 0000000..d7401d9
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.bars;
+
+import com.android.resources.Density;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.widget.TextView;
+
+public class TitleBar extends CustomBar {
+
+ private TextView mTextView;
+
+ public TitleBar(Context context, Density density, String label)
+ throws XmlPullParserException {
+ super(context, density, "/bars/title_bar.xml");
+
+ // Cannot access the inside items through id because no R.id values have been
+ // created for them.
+ // We do know the order though.
+ mTextView = setText(0, label);
+
+ setStyle("windowTitleBackgroundStyle");
+ }
+
+ @Override
+ protected TextView getStyleableTextView() {
+ return mTextView;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index c8ad1d6..0aa2e6d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -29,14 +29,13 @@ import com.android.ide.common.rendering.api.IAnimationListener;
import com.android.ide.common.rendering.api.ILayoutPullParser;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.Params;
+import com.android.ide.common.rendering.api.RenderParams;
import com.android.ide.common.rendering.api.RenderResources;
import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.common.rendering.api.Result;
-import com.android.ide.common.rendering.api.StyleResourceValue;
import com.android.ide.common.rendering.api.ViewInfo;
-import com.android.ide.common.rendering.api.Params.RenderingMode;
+import com.android.ide.common.rendering.api.RenderParams.RenderingMode;
import com.android.ide.common.rendering.api.RenderResources.FrameworkResourceIdProvider;
import com.android.ide.common.rendering.api.Result.Status;
import com.android.internal.util.XmlUtils;
@@ -47,11 +46,16 @@ import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
import com.android.layoutlib.bridge.android.BridgeWindow;
import com.android.layoutlib.bridge.android.BridgeWindowSession;
import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
-import com.android.resources.Density;
+import com.android.layoutlib.bridge.bars.FakeActionBar;
+import com.android.layoutlib.bridge.bars.PhoneSystemBar;
+import com.android.layoutlib.bridge.bars.TabletSystemBar;
+import com.android.layoutlib.bridge.bars.TitleBar;
import com.android.resources.ResourceType;
import com.android.resources.ScreenSize;
import com.android.util.Pair;
+import org.xmlpull.v1.XmlPullParserException;
+
import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.LayoutTransition;
@@ -105,7 +109,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
*/
private static BridgeContext sCurrentContext = null;
- private final Params mParams;
+ private final RenderParams mParams;
// scene state
private RenderSession mScene;
@@ -113,17 +117,18 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
private BridgeXmlBlockParser mBlockParser;
private BridgeInflater mInflater;
private ResourceValue mWindowBackground;
- private FrameLayout mViewRoot;
+ private ViewGroup mViewRoot;
+ private FrameLayout mContentRoot;
private Canvas mCanvas;
private int mMeasuredScreenWidth = -1;
private int mMeasuredScreenHeight = -1;
- private boolean mIsAlphaChannelImage = true;
+ private boolean mIsAlphaChannelImage;
+ private boolean mWindowIsFloating;
private int mStatusBarSize;
- private int mTopBarSize;
private int mSystemBarSize;
- private int mTopOffset;
- private int mTotalBarSize;
+ private int mTitleBarSize;
+ private int mActionBarSize;
// information being returned through the API
@@ -146,9 +151,9 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
*
* @see LayoutBridge#createScene(com.android.layoutlib.api.SceneParams)
*/
- public RenderSessionImpl(Params params) {
+ public RenderSessionImpl(RenderParams params) {
// copy the params.
- mParams = new Params(params);
+ mParams = new RenderParams(params);
}
/**
@@ -172,8 +177,8 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
// setup the display Metrics.
DisplayMetrics metrics = new DisplayMetrics();
- metrics.densityDpi = mParams.getDensity();
- metrics.density = mParams.getDensity() / (float) DisplayMetrics.DENSITY_DEFAULT;
+ metrics.densityDpi = mParams.getDensity().getDpiValue();
+ metrics.density = metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
metrics.scaledDensity = metrics.density;
metrics.widthPixels = mParams.getScreenWidth();
metrics.heightPixels = mParams.getScreenHeight();
@@ -190,17 +195,16 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
mIsAlphaChannelImage = getBooleanThemeValue(resources,
"windowIsFloating", true /*defaultValue*/);
+ mWindowIsFloating = getBooleanThemeValue(resources, "windowIsFloating",
+ true /*defaultValue*/);
setUp();
findBackground(resources);
findStatusBar(resources, metrics);
- findTopBar(resources, metrics);
+ findActionBar(resources, metrics);
findSystemBar(resources, metrics);
- mTopOffset = mStatusBarSize + mTopBarSize;
- mTotalBarSize = mTopOffset + mSystemBarSize;
-
// build the inflater and parser.
mInflater = new BridgeInflater(mContext, mParams.getProjectCallback());
mContext.setBridgeInflater(mInflater);
@@ -353,13 +357,100 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
try {
- mViewRoot = new FrameLayout(mContext);
+ if (mWindowIsFloating || mParams.isForceNoDecor()) {
+ mViewRoot = mContentRoot = new FrameLayout(mContext);
+ } else {
+ /*
+ * we're creating the following layout
+ *
+ +-------------------------------------------------+
+ | System bar (only in phone UI) |
+ +-------------------------------------------------+
+ | Title/Action bar (optional) |
+ +-------------------------------------------------+
+ | Content, vertical extending |
+ | |
+ +-------------------------------------------------+
+ | System bar (only in tablet UI) |
+ +-------------------------------------------------+
+
+ */
+
+ LinearLayout topLayout = new LinearLayout(mContext);
+ mViewRoot = topLayout;
+ topLayout.setOrientation(LinearLayout.VERTICAL);
+
+ if (mStatusBarSize > 0) {
+ // system bar
+ try {
+ PhoneSystemBar systemBar = new PhoneSystemBar(mContext,
+ mParams.getDensity());
+ systemBar.setLayoutParams(
+ new LinearLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, mStatusBarSize));
+ topLayout.addView(systemBar);
+ } catch (XmlPullParserException e) {
+
+ }
+ }
+
+ // if the theme says no title/action bar, then the size will be 0
+ if (mActionBarSize > 0) {
+ try {
+ FakeActionBar actionBar = new FakeActionBar(mContext,
+ mParams.getDensity(),
+ mParams.getAppLabel(), mParams.getAppIcon());
+ actionBar.setLayoutParams(
+ new LinearLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, mActionBarSize));
+ topLayout.addView(actionBar);
+ } catch (XmlPullParserException e) {
+
+ }
+ } else if (mTitleBarSize > 0) {
+ try {
+ TitleBar titleBar = new TitleBar(mContext,
+ mParams.getDensity(), mParams.getAppLabel());
+ titleBar.setLayoutParams(
+ new LinearLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, mTitleBarSize));
+ topLayout.addView(titleBar);
+ } catch (XmlPullParserException e) {
+
+ }
+ }
+
+
+ // content frame
+ mContentRoot = new FrameLayout(mContext);
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ params.weight = 1;
+ mContentRoot.setLayoutParams(params);
+ topLayout.addView(mContentRoot);
+
+ if (mSystemBarSize > 0) {
+ // system bar
+ try {
+ TabletSystemBar systemBar = new TabletSystemBar(mContext,
+ mParams.getDensity());
+ systemBar.setLayoutParams(
+ new LinearLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT, mSystemBarSize));
+ topLayout.addView(systemBar);
+ } catch (XmlPullParserException e) {
+
+ }
+ }
+
+ }
+
// Sets the project callback (custom view loader) to the fragment delegate so that
// it can instantiate the custom Fragment.
Fragment_Delegate.setProjectCallback(mParams.getProjectCallback());
- View view = mInflater.inflate(mBlockParser, mViewRoot);
+ View view = mInflater.inflate(mBlockParser, mContentRoot);
Fragment_Delegate.setProjectCallback(null);
@@ -377,9 +468,8 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
// get the background drawable
if (mWindowBackground != null) {
- Drawable d = ResourceHelper.getDrawable(mWindowBackground,
- mContext, true /* isFramework */);
- mViewRoot.setBackgroundDrawable(d);
+ Drawable d = ResourceHelper.getDrawable(mWindowBackground, mContext);
+ mContentRoot.setBackgroundDrawable(d);
}
return SUCCESS.createResult();
@@ -408,8 +498,8 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
* @throws IllegalStateException if the current context is different than the one owned by
* the scene, or if {@link #acquire(long)} was not called.
*
- * @see SceneParams#getRenderingMode()
- * @see LayoutScene#render(long)
+ * @see RenderParams#getRenderingMode()
+ * @see RenderSession#render(long)
*/
public Result render(boolean freshRender) {
checkLock();
@@ -428,7 +518,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
if (mMeasuredScreenWidth == -1) {
newRenderSize = true;
mMeasuredScreenWidth = mParams.getScreenWidth();
- mMeasuredScreenHeight = mParams.getScreenHeight() - mTotalBarSize;
+ mMeasuredScreenHeight = mParams.getScreenHeight();
if (renderingMode != RenderingMode.NORMAL) {
// measure the full size needed by the layout.
@@ -476,11 +566,11 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
if (mParams.getImageFactory() != null) {
mImage = mParams.getImageFactory().getImage(
mMeasuredScreenWidth,
- mMeasuredScreenHeight + mTotalBarSize);
+ mMeasuredScreenHeight);
} else {
mImage = new BufferedImage(
mMeasuredScreenWidth,
- mMeasuredScreenHeight + mTotalBarSize,
+ mMeasuredScreenHeight,
BufferedImage.TYPE_INT_ARGB);
newImage = true;
}
@@ -491,46 +581,26 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
Graphics2D gc = mImage.createGraphics();
gc.setColor(new Color(mParams.getOverrideBgColor(), true));
gc.setComposite(AlphaComposite.Src);
- gc.fillRect(0, 0, mMeasuredScreenWidth,
- mMeasuredScreenHeight + mTotalBarSize);
+ gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
gc.dispose();
}
// create an Android bitmap around the BufferedImage
Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
- true /*isMutable*/,
- Density.getEnum(mParams.getDensity()));
+ true /*isMutable*/, mParams.getDensity());
// create a Canvas around the Android bitmap
mCanvas = new Canvas(bitmap);
- mCanvas.setDensity(mParams.getDensity());
- mCanvas.translate(0, mTopOffset);
+ mCanvas.setDensity(mParams.getDensity().getDpiValue());
}
if (freshRender && newImage == false) {
Graphics2D gc = mImage.createGraphics();
gc.setComposite(AlphaComposite.Src);
- if (mStatusBarSize > 0) {
- gc.setColor(new Color(0xFF3C3C3C, true));
- gc.fillRect(0, 0, mMeasuredScreenWidth, mStatusBarSize);
- }
-
- if (mTopBarSize > 0) {
- gc.setColor(new Color(0xFF7F7F7F, true));
- gc.fillRect(0, mStatusBarSize, mMeasuredScreenWidth, mTopOffset);
- }
-
- // erase the rest
gc.setColor(new Color(0x00000000, true));
- gc.fillRect(0, mTopOffset,
- mMeasuredScreenWidth, mMeasuredScreenHeight + mTopOffset);
-
- if (mSystemBarSize > 0) {
- gc.setColor(new Color(0xFF3C3C3C, true));
- gc.fillRect(0, mMeasuredScreenHeight + mTopOffset,
- mMeasuredScreenWidth, mMeasuredScreenHeight + mTotalBarSize);
- }
+ gc.fillRect(0, 0,
+ mMeasuredScreenWidth, mMeasuredScreenHeight);
// done
gc.dispose();
@@ -538,7 +608,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
mViewRoot.draw(mCanvas);
- mViewInfoList = visitAllChildren((ViewGroup)mViewRoot, mContext, mTopOffset);
+ mViewInfoList = startVisitingViews(mViewRoot, 0);
// success!
return SUCCESS.createResult();
@@ -561,7 +631,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
* @throws IllegalStateException if the current context is different than the one owned by
* the scene, or if {@link #acquire(long)} was not called.
*
- * @see LayoutScene#animate(Object, String, boolean, IAnimationListener)
+ * @see RenderSession#animate(Object, String, boolean, IAnimationListener)
*/
public Result animate(Object targetObject, String animationName,
boolean isFrameworkAnimation, IAnimationListener listener) {
@@ -617,7 +687,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
* @throws IllegalStateException if the current context is different than the one owned by
* the scene, or if {@link #acquire(long)} was not called.
*
- * @see LayoutScene#insertChild(Object, ILayoutPullParser, int, IAnimationListener)
+ * @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener)
*/
public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml,
final int index, IAnimationListener listener) {
@@ -696,7 +766,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
* @throws IllegalStateException if the current context is different than the one owned by
* the scene, or if {@link #acquire(long)} was not called.
*
- * @see LayoutScene#moveChild(Object, Object, int, Map, IAnimationListener)
+ * @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener)
*/
public Result moveChild(final ViewGroup newParentView, final View childView, final int index,
Map<String, String> layoutParamsMap, final IAnimationListener listener) {
@@ -892,7 +962,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
* @throws IllegalStateException if the current context is different than the one owned by
* the scene, or if {@link #acquire(long)} was not called.
*
- * @see LayoutScene#removeChild(Object, IAnimationListener)
+ * @see RenderSession#removeChild(Object, IAnimationListener)
*/
public Result removeChild(final View childView, IAnimationListener listener) {
checkLock();
@@ -989,40 +1059,12 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
return mParams.getConfigScreenSize() == ScreenSize.XLARGE;
}
- private boolean isHCApp() {
- RenderResources resources = mContext.getRenderResources();
-
- // the app must say it targets 11+ and the theme name must extend Theme.Holo or
- // Theme.Holo.Light (which does not extend Theme.Holo, but Theme.Light)
- if (mParams.getTargetSdkVersion() < 11) {
- return false;
- }
-
- StyleResourceValue currentTheme = resources.getCurrentTheme();
- StyleResourceValue holoTheme = resources.getTheme("Theme.Holo", true /*frameworkTheme*/);
-
- if (currentTheme == holoTheme ||
- resources.themeIsParentOf(holoTheme, currentTheme)) {
- return true;
- }
-
- StyleResourceValue holoLightTheme = resources.getTheme("Theme.Holo.Light",
- true /*frameworkTheme*/);
-
- if (currentTheme == holoLightTheme ||
- resources.themeIsParentOf(holoLightTheme, currentTheme)) {
- return true;
- }
-
- return false;
- }
-
private void findStatusBar(RenderResources resources, DisplayMetrics metrics) {
if (isTabletUi() == false) {
boolean windowFullscreen = getBooleanThemeValue(resources,
"windowFullscreen", false /*defaultValue*/);
- if (windowFullscreen == false) {
+ if (windowFullscreen == false && mWindowIsFloating == false) {
// default value
mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT;
@@ -1041,20 +1083,11 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
}
}
- private void findTopBar(RenderResources resources, DisplayMetrics metrics) {
- boolean windowIsFloating = getBooleanThemeValue(resources,
- "windowIsFloating", true /*defaultValue*/);
-
- if (windowIsFloating == false) {
- if (isHCApp()) {
- findActionBar(resources, metrics);
- } else {
- findTitleBar(resources, metrics);
- }
+ private void findActionBar(RenderResources resources, DisplayMetrics metrics) {
+ if (mWindowIsFloating) {
+ return;
}
- }
- private void findActionBar(RenderResources resources, DisplayMetrics metrics) {
boolean windowActionBar = getBooleanThemeValue(resources,
"windowActionBar", true /*defaultValue*/);
@@ -1062,7 +1095,7 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
if (windowActionBar) {
// default size of the window title bar
- mTopBarSize = DEFAULT_TITLE_BAR_HEIGHT;
+ mActionBarSize = DEFAULT_TITLE_BAR_HEIGHT;
// get value from the theme.
ResourceValue value = resources.findItemInTheme("actionBarSize");
@@ -1075,44 +1108,43 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
TypedValue typedValue = ResourceHelper.getValue(value.getValue());
if (typedValue != null) {
// compute the pixel value based on the display metrics
- mTopBarSize = (int)typedValue.getDimension(metrics);
+ mActionBarSize = (int)typedValue.getDimension(metrics);
}
}
- }
- }
-
- private void findTitleBar(RenderResources resources, DisplayMetrics metrics) {
- boolean windowNoTitle = getBooleanThemeValue(resources,
- "windowNoTitle", false /*defaultValue*/);
+ } else {
+ // action bar overrides title bar so only look for this one if action bar is hidden
+ boolean windowNoTitle = getBooleanThemeValue(resources,
+ "windowNoTitle", false /*defaultValue*/);
- if (windowNoTitle == false) {
+ if (windowNoTitle == false) {
- // default size of the window title bar
- mTopBarSize = DEFAULT_TITLE_BAR_HEIGHT;
+ // default size of the window title bar
+ mTitleBarSize = DEFAULT_TITLE_BAR_HEIGHT;
- // get value from the theme.
- ResourceValue value = resources.findItemInTheme("windowTitleSize");
+ // get value from the theme.
+ ResourceValue value = resources.findItemInTheme("windowTitleSize");
- // resolve it
- value = resources.resolveResValue(value);
+ // resolve it
+ value = resources.resolveResValue(value);
- if (value != null) {
- // get the numerical value, if available
- TypedValue typedValue = ResourceHelper.getValue(value.getValue());
- if (typedValue != null) {
- // compute the pixel value based on the display metrics
- mTopBarSize = (int)typedValue.getDimension(metrics);
+ if (value != null) {
+ // get the numerical value, if available
+ TypedValue typedValue = ResourceHelper.getValue(value.getValue());
+ if (typedValue != null) {
+ // compute the pixel value based on the display metrics
+ mTitleBarSize = (int)typedValue.getDimension(metrics);
+ }
}
}
+
}
}
private void findSystemBar(RenderResources resources, DisplayMetrics metrics) {
- if (isTabletUi() && getBooleanThemeValue(
- resources, "windowIsFloating", true /*defaultValue*/) == false) {
+ if (isTabletUi() && mWindowIsFloating == false) {
// default value
- mSystemBarSize = 56; // ??
+ mSystemBarSize = 48; // ??
// get the real value
ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
@@ -1244,40 +1276,71 @@ public class RenderSessionImpl extends FrameworkResourceIdProvider {
}
}
+ private List<ViewInfo> startVisitingViews(View view, int offset) {
+ if (view == null) {
+ return null;
+ }
+
+ // adjust the offset to this view.
+ offset += view.getTop();
+
+ if (view == mContentRoot) {
+ return visitAllChildren(mContentRoot, offset);
+ }
+
+ // otherwise, look for mContentRoot in the children
+ if (view instanceof ViewGroup) {
+ ViewGroup group = ((ViewGroup) view);
+
+ for (int i = 0; i < group.getChildCount(); i++) {
+ List<ViewInfo> list = startVisitingViews(group.getChildAt(i), offset);
+ if (list != null) {
+ return list;
+ }
+ }
+ }
+
+ return null;
+ }
/**
* Visits a View and its children and generate a {@link ViewInfo} containing the
* bounds of all the views.
* @param view the root View
- * @param context the context.
+ * @param offset an offset for the view bounds.
*/
- private ViewInfo visit(View view, BridgeContext context, int offset) {
+ private ViewInfo visit(View view, int offset) {
if (view == null) {
return null;
}
ViewInfo result = new ViewInfo(view.getClass().getName(),
- context.getViewKey(view),
+ mContext.getViewKey(view),
view.getLeft(), view.getTop() + offset, view.getRight(), view.getBottom() + offset,
view, view.getLayoutParams());
if (view instanceof ViewGroup) {
ViewGroup group = ((ViewGroup) view);
- result.setChildren(visitAllChildren(group, context, 0 /*offset*/));
+ result.setChildren(visitAllChildren(group, 0 /*offset*/));
}
return result;
}
- private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, BridgeContext context,
- int offset) {
+ /**
+ * Visits all the children of a given ViewGroup generate a list of {@link ViewInfo}
+ * containing the bounds of all the views.
+ * @param view the root View
+ * @param offset an offset for the view bounds.
+ */
+ private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset) {
if (viewGroup == null) {
return null;
}
List<ViewInfo> children = new ArrayList<ViewInfo>();
for (int i = 0; i < viewGroup.getChildCount(); i++) {
- children.add(visit(viewGroup.getChildAt(i), context, offset));
+ children.add(visit(viewGroup.getChildAt(i), offset));
}
return children;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index 25bb81c..cea7cf3 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -18,6 +18,7 @@ package com.android.layoutlib.bridge.impl;
import com.android.ide.common.rendering.api.DensityBasedResourceValue;
import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.ide.common.rendering.api.RenderResources;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.android.BridgeContext;
@@ -28,7 +29,9 @@ import com.android.resources.Density;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Bitmap_Delegate;
import android.graphics.NinePatch_Delegate;
@@ -108,19 +111,63 @@ public final class ResourceHelper {
throw new NumberFormatException();
}
+ public static ColorStateList getColorStateList(ResourceValue resValue, BridgeContext context) {
+ String value = resValue.getValue();
+ if (value != null) {
+ // first check if the value is a file (xml most likely)
+ File f = new File(value);
+ if (f.isFile()) {
+ try {
+ // let the framework inflate the ColorStateList from the XML file, by
+ // providing an XmlPullParser
+ KXmlParser parser = new KXmlParser();
+ parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
+ parser.setInput(new FileReader(f));
+
+ return ColorStateList.createFromXml(context.getResources(),
+ new BridgeXmlBlockParser(parser, context, resValue.isFramework()));
+ } catch (XmlPullParserException e) {
+ Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+ "Failed to configure parser for " + value, e, null /*data*/);
+ // we'll return null below.
+ } catch (Exception e) {
+ // this is an error and not warning since the file existence is
+ // checked before attempting to parse it.
+ Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
+ "Failed to parse file " + value, e, null /*data*/);
+
+ return null;
+ }
+ } else {
+ // try to load the color state list from an int
+ try {
+ int color = ResourceHelper.getColor(value);
+ return ColorStateList.valueOf(color);
+ } catch (NumberFormatException e) {
+ Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
+ "Failed to convert " + value + " into a ColorStateList", e,
+ null /*data*/);
+ return null;
+ }
+ }
+ }
+
+ return null;
+ }
+
/**
* Returns a drawable from the given value.
* @param value The value that contains a path to a 9 patch, a bitmap or a xml based drawable,
* or an hexadecimal color
- * @param context
- * @param isFramework indicates whether the resource is a framework resources.
- * Framework resources are cached, and loaded only once.
+ * @param context the current context
*/
- public static Drawable getDrawable(ResourceValue value, BridgeContext context,
- boolean isFramework) {
+ public static Drawable getDrawable(ResourceValue value, BridgeContext context) {
Drawable d = null;
String stringValue = value.getValue();
+ if (RenderResources.REFERENCE_NULL.equals(stringValue)) {
+ return null;
+ }
String lowerCaseValue = stringValue.toLowerCase();
@@ -129,9 +176,9 @@ public final class ResourceHelper {
if (file.isFile()) {
// see if we still have both the chunk and the bitmap in the caches
NinePatchChunk chunk = Bridge.getCached9Patch(stringValue,
- isFramework ? null : context.getProjectKey());
+ value.isFramework() ? null : context.getProjectKey());
Bitmap bitmap = Bridge.getCachedBitmap(stringValue,
- isFramework ? null : context.getProjectKey());
+ value.isFramework() ? null : context.getProjectKey());
// if either chunk or bitmap is null, then we reload the 9-patch file.
if (chunk == null || bitmap == null) {
@@ -143,7 +190,7 @@ public final class ResourceHelper {
chunk = ninePatch.getChunk();
Bridge.setCached9Patch(stringValue, chunk,
- isFramework ? null : context.getProjectKey());
+ value.isFramework() ? null : context.getProjectKey());
}
if (bitmap == null) {
@@ -158,7 +205,7 @@ public final class ResourceHelper {
density);
Bridge.setCachedBitmap(stringValue, bitmap,
- isFramework ? null : context.getProjectKey());
+ value.isFramework() ? null : context.getProjectKey());
}
}
} catch (MalformedURLException e) {
@@ -192,7 +239,7 @@ public final class ResourceHelper {
parser.setInput(new FileReader(f));
d = Drawable.createFromXml(context.getResources(),
- new BridgeXmlBlockParser(parser, context, isFramework));
+ new BridgeXmlBlockParser(parser, context, value.isFramework()));
return d;
} catch (Exception e) {
// this is an error and not warning since the file existence is checked before
@@ -212,7 +259,7 @@ public final class ResourceHelper {
if (bmpFile.isFile()) {
try {
Bitmap bitmap = Bridge.getCachedBitmap(stringValue,
- isFramework ? null : context.getProjectKey());
+ value.isFramework() ? null : context.getProjectKey());
if (bitmap == null) {
Density density = Density.MEDIUM;
@@ -223,7 +270,7 @@ public final class ResourceHelper {
bitmap = Bitmap_Delegate.createBitmap(bmpFile, false /*isMutable*/,
density);
Bridge.setCachedBitmap(stringValue, bitmap,
- isFramework ? null : context.getProjectKey());
+ value.isFramework() ? null : context.getProjectKey());
}
return new BitmapDrawable(context.getResources(), bitmap);