summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@android.com>2010-11-09 18:25:03 -0800
committerXavier Ducrohet <xav@android.com>2010-11-11 10:08:19 -0800
commitc2e9651bf386a1f7bf7fc706cf5424950570470c (patch)
tree83d204bdbe75d466a6ce82587efed8d2a03f0641 /tools
parent762b33f9494ba48aa1be3701d345b692e8432af9 (diff)
downloadframeworks_base-c2e9651bf386a1f7bf7fc706cf5424950570470c.zip
frameworks_base-c2e9651bf386a1f7bf7fc706cf5424950570470c.tar.gz
frameworks_base-c2e9651bf386a1f7bf7fc706cf5424950570470c.tar.bz2
Layoutlib: New bridge implementation using the new API 5.
Since the new API prepare for stateful layoutlib, major reorganization of the code. New "android" sub-package for all extended android classes. Also moved BridgeInflater in here so that all extended classes are in this package. Only delegates and classes replacing renamed classes are in their original android.* packages. Also created full file for the empty implementations of IWindow and IWindowSession. New "impl" for the dirty work implementation. Main package contains the basic implementation of the API. Most of the code that was in Bridge is now in .impl.LayoutSceneImpl, with the main init/inflate/render code split into the contrustrutor, inflate() and render(). Change-Id: Ie15b15e5a1b2388cd6ef82e518345b1fc02ec981
Diffstat (limited to 'tools')
-rw-r--r--tools/layoutlib/bridge/.classpath6
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java4
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/util/FloatMath_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/view/SurfaceView.java2
-rw-r--r--tools/layoutlib/bridge/src/android/webkit/WebView.java2
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java1032
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeLayoutScene.java80
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/LayoutResult.java126
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeAssetManager.java (renamed from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java)8
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java (renamed from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentProvider.java)2
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentResolver.java (renamed from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentResolver.java)2
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java (renamed from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java)97
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java (renamed from tools/layoutlib/bridge/src/android/view/BridgeInflater.java)8
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java (renamed from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeResources.java)22
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java (renamed from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java)7
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java92
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java163
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java (renamed from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeXmlBlockParser.java)2
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlPullAttributes.java (renamed from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeXmlPullAttributes.java)4
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/MockView.java (renamed from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java)2
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/NinePatchDrawable.java (renamed from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/NinePatchDrawable.java)4
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java (renamed from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/DelegateManager.java)2
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/FontLoader.java (renamed from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/FontLoader.java)2
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java689
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java (renamed from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/ResourceHelper.java)8
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/TempResourceValue.java (renamed from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/ResourceValue.java)26
-rw-r--r--tools/layoutlib/bridge/src/com/google/android/maps/MapView.java2
-rw-r--r--tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java (renamed from tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/BridgeXmlBlockParserTest.java)4
40 files changed, 1326 insertions, 1098 deletions
diff --git a/tools/layoutlib/bridge/.classpath b/tools/layoutlib/bridge/.classpath
index aeeffa6..7204ace 100644
--- a/tools/layoutlib/bridge/.classpath
+++ b/tools/layoutlib/bridge/.classpath
@@ -4,9 +4,9 @@
<classpathentry kind="src" path="tests"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
- <classpathentry kind="var" path="ANDROID_SRC/prebuilt/common/layoutlib_api/layoutlib_api-prebuilt.jar"/>
- <classpathentry kind="var" path="ANDROID_SRC/prebuilt/common/kxml2/kxml2-2.3.0.jar" sourcepath="/ANDROID_SRC/dalvik/libcore/xml/src/main/java"/>
- <classpathentry kind="var" path="ANDROID_OUT_FRAMEWORK/ninepatch.jar" sourcepath="/ANDROID_SRC/development/tools/ninepatch/src"/>
+ <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilt/common/layoutlib_api/layoutlib_api-prebuilt.jar"/>
+ <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilt/common/kxml2/kxml2-2.3.0.jar" sourcepath="/ANDROID_PLAT_SRC/dalvik/libcore/xml/src/main/java"/>
+ <classpathentry kind="var" path="ANDROID_PLAT_OUT_FRAMEWORK/ninepatch.jar" sourcepath="/ANDROID_PLAT_SRC/development/tools/ninepatch/src"/>
<classpathentry kind="var" path="ANDROID_PLAT_SRC/out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar" sourcepath="/ANDROID_PLAT_SRC/frameworks/base"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index e97b1e6..392462f 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -17,7 +17,7 @@
package android.graphics;
import com.android.layoutlib.api.IDensityBasedResourceValue.Density;
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
import android.graphics.Bitmap.Config;
import android.os.Parcel;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index ce8e960..374bbb4 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -17,7 +17,7 @@
package android.graphics;
import com.android.layoutlib.api.ILayoutLog;
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
import android.graphics.Paint_Delegate.FontInfo;
import android.text.TextUtils;
diff --git a/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java
index 59b6a91..7ee72d8 100644
--- a/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java
@@ -16,7 +16,7 @@
package android.graphics;
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
/**
* Delegate implementing the native methods of android.graphics.DashPathEffect
diff --git a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
index 405e537..7573dc1 100644
--- a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
@@ -16,7 +16,7 @@
package android.graphics;
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
import android.graphics.Shader.TileMode;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
index 0966f39..77de32d 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
@@ -17,7 +17,7 @@
package android.graphics;
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
import android.graphics.Matrix.ScaleToFit;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index 6e90bdd..d83a33b 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -16,7 +16,7 @@
package android.graphics;
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.FontMetricsInt;
diff --git a/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java
index 6827ae7..ce7eef0 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java
@@ -16,7 +16,7 @@
package android.graphics;
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
/**
* Delegate implementing the native methods of android.graphics.PathEffect
diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
index c242e80..a5885ea 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
@@ -16,7 +16,7 @@
package android.graphics;
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
/**
* Delegate implementing the native methods of android.graphics.PorterDuffXfermode
diff --git a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
index c4e764c..c36ce53 100644
--- a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
@@ -16,7 +16,7 @@
package android.graphics;
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
import android.graphics.Shader.TileMode;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
index 4dcf144..646ac80 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
@@ -16,7 +16,7 @@
package android.graphics;
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
/**
* Delegate implementing the native methods of android.graphics.Shader
diff --git a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
index 0492e4f..358c3c7 100644
--- a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
@@ -16,7 +16,7 @@
package android.graphics;
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
import java.awt.Paint;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
index 7e90e7d..0b54a0e 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
@@ -16,8 +16,8 @@
package android.graphics;
-import com.android.layoutlib.bridge.DelegateManager;
-import com.android.layoutlib.bridge.FontLoader;
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.layoutlib.bridge.impl.FontLoader;
import android.content.res.AssetManager;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java
index d4408cf..0c1170d 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java
@@ -16,7 +16,7 @@
package android.graphics;
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
/**
* Delegate implementing the native methods of android.graphics.Xfermode
diff --git a/tools/layoutlib/bridge/src/android/util/FloatMath_Delegate.java b/tools/layoutlib/bridge/src/android/util/FloatMath_Delegate.java
index ed24e16..9ca1338 100644
--- a/tools/layoutlib/bridge/src/android/util/FloatMath_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/util/FloatMath_Delegate.java
@@ -16,7 +16,7 @@
package android.util;
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
/**
* Delegate implementing the native methods of android.util.FloatMath
diff --git a/tools/layoutlib/bridge/src/android/view/SurfaceView.java b/tools/layoutlib/bridge/src/android/view/SurfaceView.java
index ce32da9..f7db98a 100644
--- a/tools/layoutlib/bridge/src/android/view/SurfaceView.java
+++ b/tools/layoutlib/bridge/src/android/view/SurfaceView.java
@@ -16,7 +16,7 @@
package android.view;
-import com.android.layoutlib.bridge.MockView;
+import com.android.layoutlib.bridge.android.MockView;
import android.content.Context;
import android.graphics.Canvas;
diff --git a/tools/layoutlib/bridge/src/android/webkit/WebView.java b/tools/layoutlib/bridge/src/android/webkit/WebView.java
index 3b66188..a20a9d1 100644
--- a/tools/layoutlib/bridge/src/android/webkit/WebView.java
+++ b/tools/layoutlib/bridge/src/android/webkit/WebView.java
@@ -16,7 +16,7 @@
package android.webkit;
-import com.android.layoutlib.bridge.MockView;
+import com.android.layoutlib.bridge.android.MockView;
import android.content.Context;
import android.graphics.Bitmap;
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 996a942..d2092d1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -16,63 +16,26 @@
package com.android.layoutlib.bridge;
-import com.android.internal.util.XmlUtils;
-import com.android.layoutlib.api.ILayoutBridge;
import com.android.layoutlib.api.ILayoutLog;
-import com.android.layoutlib.api.ILayoutResult;
import com.android.layoutlib.api.IProjectCallback;
import com.android.layoutlib.api.IResourceValue;
-import com.android.layoutlib.api.IStyleResourceValue;
import com.android.layoutlib.api.IXmlPullParser;
-import com.android.layoutlib.api.IDensityBasedResourceValue.Density;
-import com.android.layoutlib.api.ILayoutResult.ILayoutViewInfo;
-import com.android.layoutlib.bridge.LayoutResult.LayoutViewInfo;
+import com.android.layoutlib.api.LayoutBridge;
+import com.android.layoutlib.api.SceneParams;
+import com.android.layoutlib.api.SceneResult;
+import com.android.layoutlib.bridge.android.BridgeAssetManager;
+import com.android.layoutlib.bridge.impl.FontLoader;
+import com.android.layoutlib.bridge.impl.LayoutSceneImpl;
import com.android.ninepatch.NinePatch;
import com.android.tools.layoutlib.create.MethodAdapter;
import com.android.tools.layoutlib.create.OverrideMethod;
-import android.app.Fragment_Delegate;
-import android.content.ClipData;
-import android.content.res.Configuration;
import android.graphics.Bitmap;
-import android.graphics.Bitmap_Delegate;
-import android.graphics.Canvas;
-import android.graphics.Canvas_Delegate;
-import android.graphics.Rect;
-import android.graphics.Region;
import android.graphics.Typeface_Delegate;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
-import android.view.BridgeInflater;
-import android.view.DragEvent;
-import android.view.IWindow;
-import android.view.IWindowSession;
-import android.view.InputChannel;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.Surface;
-import android.view.SurfaceView;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.View.AttachInfo;
-import android.view.View.MeasureSpec;
-import android.view.WindowManager.LayoutParams;
-import android.widget.FrameLayout;
-import android.widget.TabHost;
-import android.widget.TabWidget;
-import java.awt.image.BufferedImage;
import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
-import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@@ -81,10 +44,7 @@ import java.util.Map;
* <p/>To use this bridge, simply instantiate an object of type {@link Bridge} and call
* {@link #computeLayout(IXmlPullParser, Object, int, int, String, boolean, Map, Map, IProjectCallback, ILayoutLog)}.
*/
-public final class Bridge implements ILayoutBridge {
-
- private static final int DEFAULT_TITLE_BAR_HEIGHT = 25;
- private static final int DEFAULT_STATUS_BAR_HEIGHT = 25;
+public final class Bridge extends LayoutBridge {
public static class StaticMethodNotImplementedException extends RuntimeException {
private static final long serialVersionUID = 1L;
@@ -143,34 +103,28 @@ public final class Bridge implements ILayoutBridge {
}
};
- /**
- * Logger defined during a compute layout operation.
- * <p/>
- * This logger is generally set to {@link #sDefaultLogger} except during rendering
- * operations when it might be set to a specific provided logger.
- * <p/>
- * To change this value, use a block synchronized on {@link #sDefaultLogger}.
- */
- private static ILayoutLog sLogger = sDefaultLogger;
-
- /*
- * (non-Javadoc)
- * @see com.android.layoutlib.api.ILayoutBridge#getApiLevel()
- */
+ @Override
public int getApiLevel() {
- return API_CURRENT;
+ return LayoutBridge.API_CURRENT;
}
/*
* (non-Javadoc)
* @see com.android.layoutlib.api.ILayoutLibBridge#init(java.lang.String, java.util.Map)
*/
- public boolean init(
- String fontOsLocation, Map<String, Map<String, Integer>> enumValueMap) {
+ @Override
+ public boolean init(String fontOsLocation, Map<String, Map<String, Integer>> enumValueMap) {
+ BridgeAssetManager.initSystem();
return sinit(fontOsLocation, enumValueMap);
}
+ @Override
+ public boolean dispose() {
+ BridgeAssetManager.clearSystem();
+ return true;
+ }
+
private static synchronized boolean sinit(String fontOsLocation,
Map<String, Map<String, Integer>> enumValueMap) {
@@ -189,12 +143,8 @@ public final class Bridge implements ILayoutBridge {
OverrideMethod.setDefaultListener(new MethodAdapter() {
@Override
public void onInvokeV(String signature, boolean isNative, Object caller) {
- if (sLogger != null) {
- synchronized (sDefaultLogger) {
- sLogger.error("Missing Stub: " + signature +
- (isNative ? " (native)" : ""));
- }
- }
+ sDefaultLogger.error("Missing Stub: " + signature +
+ (isNative ? " (native)" : ""));
if (debug.equalsIgnoreCase("throw")) {
// Throwing this exception doesn't seem that useful. It breaks
@@ -278,236 +228,82 @@ public final class Bridge implements ILayoutBridge {
return true;
}
- /*
- * For compatilibty purposes, we implement the old deprecated version of computeLayout.
- * (non-Javadoc)
- * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, java.lang.String, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog)
+ /**
+ * Sets a 9 patch in a project cache or in the framework cache.
+ * @param value the path of the 9 patch
+ * @param ninePatch the 9 patch object
+ * @param projectKey the key of the project, or null to put the bitmap in the framework cache.
*/
- @Deprecated
- public ILayoutResult computeLayout(IXmlPullParser layoutDescription,
- Object projectKey,
- int screenWidth, int screenHeight, String themeName,
- Map<String, Map<String, IResourceValue>> projectResources,
- Map<String, Map<String, IResourceValue>> frameworkResources,
- IProjectCallback customViewLoader, ILayoutLog logger) {
- boolean isProjectTheme = false;
- if (themeName.charAt(0) == '*') {
- themeName = themeName.substring(1);
- isProjectTheme = true;
- }
-
- return computeLayout(layoutDescription, projectKey,
- screenWidth, screenHeight, DisplayMetrics.DENSITY_DEFAULT,
- DisplayMetrics.DENSITY_DEFAULT, DisplayMetrics.DENSITY_DEFAULT,
- themeName, isProjectTheme,
- projectResources, frameworkResources, customViewLoader, logger);
- }
+ public static void setCached9Patch(String value, NinePatch ninePatch, Object projectKey) {
+ if (projectKey != null) {
+ Map<String, SoftReference<NinePatch>> map = sProject9PatchCache.get(projectKey);
- /*
- * For compatilibty purposes, we implement the old deprecated version of computeLayout.
- * (non-Javadoc)
- * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, java.lang.String, boolean, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog)
- */
- @Deprecated
- public ILayoutResult computeLayout(IXmlPullParser layoutDescription, Object projectKey,
- int screenWidth, int screenHeight, String themeName, boolean isProjectTheme,
- Map<String, Map<String, IResourceValue>> projectResources,
- Map<String, Map<String, IResourceValue>> frameworkResources,
- IProjectCallback customViewLoader, ILayoutLog logger) {
- return computeLayout(layoutDescription, projectKey,
- screenWidth, screenHeight, DisplayMetrics.DENSITY_DEFAULT,
- DisplayMetrics.DENSITY_DEFAULT, DisplayMetrics.DENSITY_DEFAULT,
- themeName, isProjectTheme,
- projectResources, frameworkResources, customViewLoader, logger);
- }
+ if (map == null) {
+ map = new HashMap<String, SoftReference<NinePatch>>();
+ sProject9PatchCache.put(projectKey, map);
+ }
- /*
- * For compatilibty purposes, we implement the old deprecated version of computeLayout.
- * (non-Javadoc)
- * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, int, float, float, java.lang.String, boolean, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog)
- */
- public ILayoutResult computeLayout(IXmlPullParser layoutDescription, Object projectKey,
- int screenWidth, int screenHeight, int density, float xdpi, float ydpi,
- String themeName, boolean isProjectTheme,
- Map<String, Map<String, IResourceValue>> projectResources,
- Map<String, Map<String, IResourceValue>> frameworkResources,
- IProjectCallback customViewLoader, ILayoutLog logger) {
- return computeLayout(layoutDescription, projectKey,
- screenWidth, screenHeight, false /* renderFullSize */,
- density, xdpi, ydpi, themeName, isProjectTheme,
- projectResources, frameworkResources, customViewLoader, logger);
+ map.put(value, new SoftReference<NinePatch>(ninePatch));
+ } else {
+ sFramework9PatchCache.put(value, new SoftReference<NinePatch>(ninePatch));
+ }
}
- /*
- * (non-Javadoc)
- * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, boolean, int, float, float, java.lang.String, boolean, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog)
+ /**
+ * Starts a layout session by inflating and rendering it. The method returns a
+ * {@link ILayoutScene} on which further actions can be taken.
+ *
+ * @param layoutDescription the {@link IXmlPullParser} letting the LayoutLib Bridge visit the
+ * layout file.
+ * @param projectKey An Object identifying the project. This is used for the cache mechanism.
+ * @param screenWidth the screen width
+ * @param screenHeight the screen height
+ * @param renderFullSize if true, the rendering will render the full size needed by the
+ * layout. This size is never smaller than <var>screenWidth</var> x <var>screenHeight</var>.
+ * @param density the density factor for the screen.
+ * @param xdpi the screen actual dpi in X
+ * @param ydpi the screen actual dpi in Y
+ * @param themeName The name of the theme to use.
+ * @param isProjectTheme true if the theme is a project theme, false if it is a framework theme.
+ * @param projectResources the resources of the project. The map contains (String, map) pairs
+ * where the string is the type of the resource reference used in the layout file, and the
+ * map contains (String, {@link IResourceValue}) pairs where the key is the resource name,
+ * and the value is the resource value.
+ * @param frameworkResources the framework resources. The map contains (String, map) pairs
+ * where the string is the type of the resource reference used in the layout file, and the map
+ * contains (String, {@link IResourceValue}) pairs where the key is the resource name, and the
+ * value is the resource value.
+ * @param projectCallback The {@link IProjectCallback} object to get information from
+ * the project.
+ * @param logger the object responsible for displaying warning/errors to the user.
+ * @return a new {@link ILayoutScene} object that contains the result of the layout.
+ * @since 5
*/
- public ILayoutResult computeLayout(IXmlPullParser layoutDescription, Object projectKey,
- int screenWidth, int screenHeight, boolean renderFullSize,
- int density, float xdpi, float ydpi,
- String themeName, boolean isProjectTheme,
- Map<String, Map<String, IResourceValue>> projectResources,
- Map<String, Map<String, IResourceValue>> frameworkResources,
- IProjectCallback customViewLoader, ILayoutLog logger) {
- if (logger == null) {
- logger = sDefaultLogger;
- }
-
- synchronized (sDefaultLogger) {
- sLogger = logger;
- }
-
- // find the current theme and compute the style inheritance map
- Map<IStyleResourceValue, IStyleResourceValue> styleParentMap =
- new HashMap<IStyleResourceValue, IStyleResourceValue>();
-
- IStyleResourceValue currentTheme = computeStyleMaps(themeName, isProjectTheme,
- projectResources.get(BridgeConstants.RES_STYLE),
- frameworkResources.get(BridgeConstants.RES_STYLE), styleParentMap);
-
- BridgeContext context = null;
+ @Override
+ public BridgeLayoutScene createScene(SceneParams params) {
try {
- // we need to make sure the Looper has been initialized for this thread.
- // this is required for View that creates Handler objects.
- if (Looper.myLooper() == null) {
- Looper.prepare();
- }
-
- // setup the display Metrics.
- DisplayMetrics metrics = new DisplayMetrics();
- metrics.densityDpi = density;
- metrics.density = density / (float) DisplayMetrics.DENSITY_DEFAULT;
- metrics.scaledDensity = metrics.density;
- metrics.widthPixels = screenWidth;
- metrics.heightPixels = screenHeight;
- metrics.xdpi = xdpi;
- metrics.ydpi = ydpi;
-
- context = new BridgeContext(projectKey, metrics, currentTheme, projectResources,
- frameworkResources, styleParentMap, customViewLoader, logger);
- BridgeInflater inflater = new BridgeInflater(context, customViewLoader);
- context.setBridgeInflater(inflater);
- inflater.setFactory2(context);
-
- IResourceValue windowBackground = null;
- int screenOffset = 0;
- if (currentTheme != null) {
- windowBackground = context.findItemInStyle(currentTheme, "windowBackground");
- windowBackground = context.resolveResValue(windowBackground);
-
- screenOffset = getScreenOffset(frameworkResources, currentTheme, context);
- }
-
- BridgeXmlBlockParser parser = new BridgeXmlBlockParser(layoutDescription,
- context, false /* platformResourceFlag */);
-
- ViewGroup root = new FrameLayout(context);
-
- // Sets the project callback (custom view loader) to the fragment delegate so that
- // it can instantiate the custom Fragment.
- Fragment_Delegate.setProjectCallback(customViewLoader);
-
- View view = inflater.inflate(parser, root);
-
- // post-inflate process. For now this supports TabHost/TabWidget
- postInflateProcess(view, customViewLoader);
-
- Fragment_Delegate.setProjectCallback(null);
-
- // set the AttachInfo on the root view.
- AttachInfo info = new AttachInfo(new WindowSession(), new Window(),
- new Handler(), null);
- info.mHasWindowFocus = true;
- info.mWindowVisibility = View.VISIBLE;
- info.mInTouchMode = false; // this is so that we can display selections.
- root.dispatchAttachedToWindow(info, 0);
-
- // get the background drawable
- if (windowBackground != null) {
- Drawable d = ResourceHelper.getDrawable(windowBackground,
- context, true /* isFramework */);
- root.setBackgroundDrawable(d);
- }
-
- // measure the views
- int w_spec, h_spec;
-
- if (renderFullSize) {
- // measure the full size needed by the layout.
- w_spec = MeasureSpec.makeMeasureSpec(screenWidth,
- MeasureSpec.UNSPECIFIED); // this lets us know the actual needed size
- h_spec = MeasureSpec.makeMeasureSpec(screenHeight - screenOffset,
- MeasureSpec.UNSPECIFIED); // this lets us know the actual needed size
- root.measure(w_spec, h_spec);
-
- int neededWidth = root.getChildAt(0).getMeasuredWidth();
- if (neededWidth > screenWidth) {
- screenWidth = neededWidth;
- }
-
- int neededHeight = root.getChildAt(0).getMeasuredHeight();
- if (neededHeight > screenHeight - screenOffset) {
- screenHeight = neededHeight + screenOffset;
+ SceneResult lastResult = SceneResult.SUCCESS;
+ LayoutSceneImpl scene = null;
+ synchronized (this) {
+ try {
+ scene = new LayoutSceneImpl(params);
+
+ scene.prepare();
+ lastResult = scene.inflate();
+ if (lastResult == SceneResult.SUCCESS) {
+ lastResult = scene.render();
+ }
+ } finally {
+ if (scene != null) {
+ scene.cleanup();
+ }
}
}
- // remeasure with only the size we need
- // This must always be done before the call to layout
- w_spec = MeasureSpec.makeMeasureSpec(screenWidth, MeasureSpec.EXACTLY);
- h_spec = MeasureSpec.makeMeasureSpec(screenHeight - screenOffset,
- MeasureSpec.EXACTLY);
- root.measure(w_spec, h_spec);
-
- // now do the layout.
- root.layout(0, screenOffset, screenWidth, screenHeight);
-
- // draw the views
- // create the BufferedImage into which the layout will be rendered.
- BufferedImage image = new BufferedImage(screenWidth, screenHeight - screenOffset,
- BufferedImage.TYPE_INT_ARGB);
-
- // create an Android bitmap around the BufferedImage
- Bitmap bitmap = Bitmap_Delegate.createBitmap(image, Density.getEnum(density));
-
- // create a Canvas around the Android bitmap
- Canvas canvas = new Canvas(bitmap);
-
- // to set the logger, get the native delegate
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(canvas);
- canvasDelegate.setLogger(logger);
-
- root.draw(canvas);
- canvasDelegate.dispose();
-
- return new LayoutResult(
- visit(((ViewGroup)view).getChildAt(0), context),
- image);
-
- } catch (PostInflateException e) {
- return new LayoutResult(ILayoutResult.ERROR, "Error during post inflation process:\n"
- + e.getMessage());
- } catch (Throwable e) {
- // get the real cause of the exception.
- Throwable t = e;
- while (t.getCause() != null) {
- t = t.getCause();
- }
-
- // log it
- logger.error(t);
-
- // then return with an ERROR status and the message from the real exception
- return new LayoutResult(ILayoutResult.ERROR,
- t.getClass().getSimpleName() + ": " + t.getMessage());
- } finally {
- // Make sure to remove static references, otherwise we could not unload the lib
- BridgeResources.clearSystem();
- BridgeAssetManager.clearSystem();
-
- // Remove the global logger
- synchronized (sDefaultLogger) {
- sLogger = sDefaultLogger;
- }
+ return new BridgeLayoutScene(this, scene, lastResult);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ return new BridgeLayoutScene(this, null, new SceneResult("error!", t));
}
}
@@ -515,6 +311,7 @@ public final class Bridge implements ILayoutBridge {
* (non-Javadoc)
* @see com.android.layoutlib.api.ILayoutLibBridge#clearCaches(java.lang.Object)
*/
+ @Override
public void clearCaches(Object projectKey) {
if (projectKey != null) {
sProjectBitmapCache.remove(projectKey);
@@ -556,367 +353,25 @@ public final class Bridge implements ILayoutBridge {
return null;
}
- static Map<String, Integer> getEnumValues(String attributeName) {
- if (sEnumValueMap != null) {
- return sEnumValueMap.get(attributeName);
- }
-
- return null;
- }
-
- /**
- * Visits a View and its children and generate a {@link ILayoutViewInfo} containing the
- * bounds of all the views.
- * @param view the root View
- * @param context the context.
- */
- private ILayoutViewInfo visit(View view, BridgeContext context) {
- if (view == null) {
- return null;
- }
-
- LayoutViewInfo result = new LayoutViewInfo(view.getClass().getName(),
- context.getViewKey(view),
- view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
-
- if (view instanceof ViewGroup) {
- ViewGroup group = ((ViewGroup) view);
- int n = group.getChildCount();
- ILayoutViewInfo[] children = new ILayoutViewInfo[n];
- for (int i = 0; i < group.getChildCount(); i++) {
- children[i] = visit(group.getChildAt(i), context);
- }
- result.setChildren(children);
- }
-
- return result;
- }
-
- /**
- * Compute style information from the given list of style for the project and framework.
- * @param themeName the name of the current theme. In order to differentiate project and
- * platform themes sharing the same name, all project themes must be prepended with
- * a '*' character.
- * @param isProjectTheme Is this a project theme
- * @param inProjectStyleMap the project style map
- * @param inFrameworkStyleMap the framework style map
- * @param outInheritanceMap the map of style inheritance. This is filled by the method
- * @return the {@link IStyleResourceValue} matching <var>themeName</var>
- */
- private IStyleResourceValue computeStyleMaps(
- String themeName, boolean isProjectTheme, Map<String,
- IResourceValue> inProjectStyleMap, Map<String, IResourceValue> inFrameworkStyleMap,
- Map<IStyleResourceValue, IStyleResourceValue> outInheritanceMap) {
-
- if (inProjectStyleMap != null && inFrameworkStyleMap != null) {
- // first, get the theme
- IResourceValue theme = null;
-
- // project theme names have been prepended with a *
- if (isProjectTheme) {
- theme = inProjectStyleMap.get(themeName);
- } else {
- theme = inFrameworkStyleMap.get(themeName);
- }
-
- if (theme instanceof IStyleResourceValue) {
- // compute the inheritance map for both the project and framework styles
- computeStyleInheritance(inProjectStyleMap.values(), inProjectStyleMap,
- inFrameworkStyleMap, outInheritanceMap);
-
- // Compute the style inheritance for the framework styles/themes.
- // Since, for those, the style parent values do not contain 'android:'
- // we want to force looking in the framework style only to avoid using
- // similarly named styles from the project.
- // To do this, we pass null in lieu of the project style map.
- computeStyleInheritance(inFrameworkStyleMap.values(), null /*inProjectStyleMap */,
- inFrameworkStyleMap, outInheritanceMap);
-
- return (IStyleResourceValue)theme;
- }
- }
-
- return null;
- }
-
- /**
- * Compute the parent style for all the styles in a given list.
- * @param styles the styles for which we compute the parent.
- * @param inProjectStyleMap the map of project styles.
- * @param inFrameworkStyleMap the map of framework styles.
- * @param outInheritanceMap the map of style inheritance. This is filled by the method.
- */
- private void computeStyleInheritance(Collection<IResourceValue> styles,
- Map<String, IResourceValue> inProjectStyleMap,
- Map<String, IResourceValue> inFrameworkStyleMap,
- Map<IStyleResourceValue, IStyleResourceValue> outInheritanceMap) {
- for (IResourceValue value : styles) {
- if (value instanceof IStyleResourceValue) {
- IStyleResourceValue style = (IStyleResourceValue)value;
- IStyleResourceValue parentStyle = null;
-
- // first look for a specified parent.
- String parentName = style.getParentStyle();
-
- // no specified parent? try to infer it from the name of the style.
- if (parentName == null) {
- parentName = getParentName(value.getName());
- }
-
- if (parentName != null) {
- parentStyle = getStyle(parentName, inProjectStyleMap, inFrameworkStyleMap);
-
- if (parentStyle != null) {
- outInheritanceMap.put(style, parentStyle);
- }
- }
- }
- }
- }
-
/**
- * Searches for and returns the {@link IStyleResourceValue} from a given name.
- * <p/>The format of the name can be:
- * <ul>
- * <li>[android:]&lt;name&gt;</li>
- * <li>[android:]style/&lt;name&gt;</li>
- * <li>@[android:]style/&lt;name&gt;</li>
- * </ul>
- * @param parentName the name of the style.
- * @param inProjectStyleMap the project style map. Can be <code>null</code>
- * @param inFrameworkStyleMap the framework style map.
- * @return The matching {@link IStyleResourceValue} object or <code>null</code> if not found.
+ * Returns the list of possible enums for a given attribute name.
*/
- private IStyleResourceValue getStyle(String parentName,
- Map<String, IResourceValue> inProjectStyleMap,
- Map<String, IResourceValue> inFrameworkStyleMap) {
- boolean frameworkOnly = false;
-
- String name = parentName;
-
- // remove the useless @ if it's there
- if (name.startsWith(BridgeConstants.PREFIX_RESOURCE_REF)) {
- name = name.substring(BridgeConstants.PREFIX_RESOURCE_REF.length());
- }
-
- // check for framework identifier.
- if (name.startsWith(BridgeConstants.PREFIX_ANDROID)) {
- frameworkOnly = true;
- name = name.substring(BridgeConstants.PREFIX_ANDROID.length());
- }
-
- // at this point we could have the format <type>/<name>. we want only the name as long as
- // the type is style.
- if (name.startsWith(BridgeConstants.REFERENCE_STYLE)) {
- name = name.substring(BridgeConstants.REFERENCE_STYLE.length());
- } else if (name.indexOf('/') != -1) {
- return null;
- }
-
- IResourceValue parent = null;
-
- // if allowed, search in the project resources.
- if (frameworkOnly == false && inProjectStyleMap != null) {
- parent = inProjectStyleMap.get(name);
- }
-
- // if not found, then look in the framework resources.
- if (parent == null) {
- parent = inFrameworkStyleMap.get(name);
- }
-
- // make sure the result is the proper class type and return it.
- if (parent instanceof IStyleResourceValue) {
- return (IStyleResourceValue)parent;
- }
-
- sLogger.error(String.format("Unable to resolve parent style name: %s", parentName));
-
- return null;
- }
-
- /**
- * Computes the name of the parent style, or <code>null</code> if the style is a root style.
- */
- private String getParentName(String styleName) {
- int index = styleName.lastIndexOf('.');
- if (index != -1) {
- return styleName.substring(0, index);
+ public static Map<String, Integer> getEnumValues(String attributeName) {
+ if (sEnumValueMap != null) {
+ return sEnumValueMap.get(attributeName);
}
return null;
}
/**
- * Returns the top screen offset. This depends on whether the current theme defines the user
- * of the title and status bars.
- * @param frameworkResources The framework resources
- * @param currentTheme The current theme
- * @param context The context
- * @return the pixel height offset
- */
- private int getScreenOffset(Map<String, Map<String, IResourceValue>> frameworkResources,
- IStyleResourceValue currentTheme, BridgeContext context) {
- int offset = 0;
-
- // get the title bar flag from the current theme.
- IResourceValue value = context.findItemInStyle(currentTheme, "windowNoTitle");
-
- // because it may reference something else, we resolve it.
- value = context.resolveResValue(value);
-
- // if there's a value and it's true (default is false)
- if (value == null || value.getValue() == null ||
- XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) {
- // default size of the window title bar
- int defaultOffset = DEFAULT_TITLE_BAR_HEIGHT;
-
- // get value from the theme.
- value = context.findItemInStyle(currentTheme, "windowTitleSize");
-
- // resolve it
- value = context.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
- defaultOffset = (int)typedValue.getDimension(context.getResources().mMetrics);
- }
- }
-
- offset += defaultOffset;
- }
-
- // get the fullscreen flag from the current theme.
- value = context.findItemInStyle(currentTheme, "windowFullscreen");
-
- // because it may reference something else, we resolve it.
- value = context.resolveResValue(value);
-
- if (value == null || value.getValue() == null ||
- XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) {
-
- // default value
- int defaultOffset = DEFAULT_STATUS_BAR_HEIGHT;
-
- // get the real value, first the list of Dimensions from the framework map
- Map<String, IResourceValue> dimens = frameworkResources.get(BridgeConstants.RES_DIMEN);
-
- // now get the value
- value = dimens.get("status_bar_height");
- if (value != null) {
- TypedValue typedValue = ResourceHelper.getValue(value.getValue());
- if (typedValue != null) {
- // compute the pixel value based on the display metrics
- defaultOffset = (int)typedValue.getDimension(context.getResources().mMetrics);
- }
- }
-
- // add the computed offset.
- offset += defaultOffset;
- }
-
- return offset;
- }
-
- /**
- * Post process on a view hierachy that was just inflated.
- * <p/>At the moment this only support TabHost: If {@link TabHost} is detected, look for the
- * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically
- * based on the content of the {@link FrameLayout}.
- * @param view the root view to process.
- * @param projectCallback callback to the project.
- */
- private void postInflateProcess(View view, IProjectCallback projectCallback)
- throws PostInflateException {
- if (view instanceof TabHost) {
- setupTabHost((TabHost)view, projectCallback);
- } else if (view instanceof ViewGroup) {
- ViewGroup group = (ViewGroup)view;
- final int count = group.getChildCount();
- for (int c = 0 ; c < count ; c++) {
- View child = group.getChildAt(c);
- postInflateProcess(child, projectCallback);
- }
- }
- }
-
- /**
- * Sets up a {@link TabHost} object.
- * @param tabHost the TabHost to setup.
- * @param projectCallback The project callback object to access the project R class.
- * @throws PostInflateException
- */
- private void setupTabHost(TabHost tabHost, IProjectCallback projectCallback)
- throws PostInflateException {
- // look for the TabWidget, and the FrameLayout. They have their own specific names
- View v = tabHost.findViewById(android.R.id.tabs);
-
- if (v == null) {
- throw new PostInflateException(
- "TabHost requires a TabWidget with id \"android:id/tabs\".\n");
- }
-
- if ((v instanceof TabWidget) == false) {
- throw new PostInflateException(String.format(
- "TabHost requires a TabWidget with id \"android:id/tabs\".\n" +
- "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName()));
- }
-
- v = tabHost.findViewById(android.R.id.tabcontent);
-
- if (v == null) {
- // TODO: see if we can fake tabs even without the FrameLayout (same below when the framelayout is empty)
- throw new PostInflateException(
- "TabHost requires a FrameLayout with id \"android:id/tabcontent\".");
- }
-
- if ((v instanceof FrameLayout) == false) {
- throw new PostInflateException(String.format(
- "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" +
- "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName()));
- }
-
- FrameLayout content = (FrameLayout)v;
-
- // now process the content of the framelayout and dynamically create tabs for it.
- final int count = content.getChildCount();
-
- if (count == 0) {
- throw new PostInflateException(
- "The FrameLayout for the TabHost has no content. Rendering failed.\n");
- }
-
- // this must be called before addTab() so that the TabHost searches its TabWidget
- // and FrameLayout.
- tabHost.setup();
-
- // for each child of the framelayout, add a new TabSpec
- for (int i = 0 ; i < count ; i++) {
- View child = content.getChildAt(i);
- String tabSpec = String.format("tab_spec%d", i+1);
- int id = child.getId();
- String[] resource = projectCallback.resolveResourceValue(id);
- String name;
- if (resource != null) {
- name = resource[0]; // 0 is resource name, 1 is resource type.
- } else {
- name = String.format("Tab %d", i+1); // default name if id is unresolved.
- }
- tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id));
- }
- }
-
- /**
* Returns the bitmap for a specific path, from a specific project cache, or from the
* framework cache.
* @param value the path of the bitmap
* @param projectKey the key of the project, or null to query the framework cache.
* @return the cached Bitmap or null if not found.
*/
- static Bitmap getCachedBitmap(String value, Object projectKey) {
+ public static Bitmap getCachedBitmap(String value, Object projectKey) {
if (projectKey != null) {
Map<String, SoftReference<Bitmap>> map = sProjectBitmapCache.get(projectKey);
if (map != null) {
@@ -941,7 +396,7 @@ public final class Bridge implements ILayoutBridge {
* @param bmp the Bitmap object
* @param projectKey the key of the project, or null to put the bitmap in the framework cache.
*/
- static void setCachedBitmap(String value, Bitmap bmp, Object projectKey) {
+ public static void setCachedBitmap(String value, Bitmap bmp, Object projectKey) {
if (projectKey != null) {
Map<String, SoftReference<Bitmap>> map = sProjectBitmapCache.get(projectKey);
@@ -963,7 +418,7 @@ public final class Bridge implements ILayoutBridge {
* @param projectKey the key of the project, or null to query the framework cache.
* @return the cached 9 patch or null if not found.
*/
- static NinePatch getCached9Patch(String value, Object projectKey) {
+ public static NinePatch getCached9Patch(String value, Object projectKey) {
if (projectKey != null) {
Map<String, SoftReference<NinePatch>> map = sProject9PatchCache.get(projectKey);
@@ -983,262 +438,69 @@ public final class Bridge implements ILayoutBridge {
return null;
}
- /**
- * Sets a 9 patch in a project cache or in the framework cache.
- * @param value the path of the 9 patch
- * @param ninePatch the 9 patch object
- * @param projectKey the key of the project, or null to put the bitmap in the framework cache.
- */
- static void setCached9Patch(String value, NinePatch ninePatch, Object projectKey) {
- if (projectKey != null) {
- Map<String, SoftReference<NinePatch>> map = sProject9PatchCache.get(projectKey);
- if (map == null) {
- map = new HashMap<String, SoftReference<NinePatch>>();
- sProject9PatchCache.put(projectKey, map);
- }
+ // ---------- OBSOLETE API METHODS ----------
- map.put(value, new SoftReference<NinePatch>(ninePatch));
- } else {
- sFramework9PatchCache.put(value, new SoftReference<NinePatch>(ninePatch));
- }
+ /*
+ * For compatilibty purposes, we implement the old deprecated version of computeLayout.
+ * (non-Javadoc)
+ * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, java.lang.String, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog)
+ */
+ @Deprecated
+ public com.android.layoutlib.api.ILayoutResult computeLayout(IXmlPullParser layoutDescription,
+ Object projectKey,
+ int screenWidth, int screenHeight, String themeName,
+ Map<String, Map<String, IResourceValue>> projectResources,
+ Map<String, Map<String, IResourceValue>> frameworkResources,
+ IProjectCallback customViewLoader, ILayoutLog logger) {
+ throw new UnsupportedOperationException();
}
- private static final class PostInflateException extends Exception {
- private static final long serialVersionUID = 1L;
-
- public PostInflateException(String message) {
- super(message);
- }
+ /*
+ * For compatilibty purposes, we implement the old deprecated version of computeLayout.
+ * (non-Javadoc)
+ * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, java.lang.String, boolean, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog)
+ */
+ @Deprecated
+ public com.android.layoutlib.api.ILayoutResult computeLayout(IXmlPullParser layoutDescription,
+ Object projectKey,
+ int screenWidth, int screenHeight, String themeName, boolean isProjectTheme,
+ Map<String, Map<String, IResourceValue>> projectResources,
+ Map<String, Map<String, IResourceValue>> frameworkResources,
+ IProjectCallback customViewLoader, ILayoutLog logger) {
+ throw new UnsupportedOperationException();
}
- /**
- * Implementation of {@link IWindowSession} so that mSession is not null in
- * the {@link SurfaceView}.
+ /*
+ * For compatilibty purposes, we implement the old deprecated version of computeLayout.
+ * (non-Javadoc)
+ * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, int, float, float, java.lang.String, boolean, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog)
*/
- private static final class WindowSession implements IWindowSession {
-
- @SuppressWarnings("unused")
- public int add(IWindow arg0, LayoutParams arg1, int arg2, Rect arg3,
- InputChannel outInputchannel)
- throws RemoteException {
- // pass for now.
- return 0;
- }
-
- @SuppressWarnings("unused")
- public int addWithoutInputChannel(IWindow arg0, LayoutParams arg1, int arg2, Rect arg3)
- throws RemoteException {
- // pass for now.
- return 0;
- }
-
- @SuppressWarnings("unused")
- public void finishDrawing(IWindow arg0) throws RemoteException {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public void finishKey(IWindow arg0) throws RemoteException {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public boolean getInTouchMode() throws RemoteException {
- // pass for now.
- return false;
- }
-
- @SuppressWarnings("unused")
- public boolean performHapticFeedback(IWindow window, int effectId, boolean always) {
- // pass for now.
- return false;
- }
-
- @SuppressWarnings("unused")
- public MotionEvent getPendingPointerMove(IWindow arg0) throws RemoteException {
- // pass for now.
- return null;
- }
-
- @SuppressWarnings("unused")
- public MotionEvent getPendingTrackballMove(IWindow arg0) throws RemoteException {
- // pass for now.
- return null;
- }
-
- @SuppressWarnings("unused")
- public int relayout(IWindow arg0, LayoutParams arg1, int arg2, int arg3, int arg4,
- boolean arg4_5, Rect arg5, Rect arg6, Rect arg7, Configuration arg7b, Surface arg8)
- throws RemoteException {
- // pass for now.
- return 0;
- }
-
- public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public void remove(IWindow arg0) throws RemoteException {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public void setInTouchMode(boolean arg0) throws RemoteException {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public void setTransparentRegion(IWindow arg0, Region arg1) throws RemoteException {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public void setInsets(IWindow window, int touchable, Rect contentInsets,
- Rect visibleInsets) {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public IBinder prepareDrag(IWindow window, boolean localOnly,
- int thumbnailWidth, int thumbnailHeight, Surface outSurface)
- throws RemoteException {
- // pass for now
- return null;
- }
-
- @SuppressWarnings("unused")
- public boolean performDrag(IWindow window, IBinder dragToken,
- float touchX, float touchY, float thumbCenterX, float thumbCenterY,
- ClipData data)
- throws RemoteException {
- // pass for now
- return false;
- }
-
- @SuppressWarnings("unused")
- public void reportDropResult(IWindow window, boolean consumed) throws RemoteException {
- // pass for now
- }
-
- @SuppressWarnings("unused")
- public void dragRecipientEntered(IWindow window) throws RemoteException {
- // pass for now
- }
-
- @SuppressWarnings("unused")
- public void dragRecipientExited(IWindow window) throws RemoteException {
- // pass for now
- }
-
- @SuppressWarnings("unused")
- public void setWallpaperPosition(IBinder window, float x, float y,
- float xStep, float yStep) {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public void wallpaperOffsetsComplete(IBinder window) {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
- int z, Bundle extras, boolean sync) {
- // pass for now.
- return null;
- }
-
- @SuppressWarnings("unused")
- public void wallpaperCommandComplete(IBinder window, Bundle result) {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public void closeSystemDialogs(String reason) {
- // pass for now.
- }
-
- public IBinder asBinder() {
- // pass for now.
- return null;
- }
+ @Deprecated
+ public com.android.layoutlib.api.ILayoutResult computeLayout(IXmlPullParser layoutDescription,
+ Object projectKey,
+ int screenWidth, int screenHeight, int density, float xdpi, float ydpi,
+ String themeName, boolean isProjectTheme,
+ Map<String, Map<String, IResourceValue>> projectResources,
+ Map<String, Map<String, IResourceValue>> frameworkResources,
+ IProjectCallback customViewLoader, ILayoutLog logger) {
+ throw new UnsupportedOperationException();
}
- /**
- * Implementation of {@link IWindow} to pass to the {@link AttachInfo}.
+ /*
+ * (non-Javadoc)
+ * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, boolean, int, float, float, java.lang.String, boolean, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog)
*/
- private static final class Window implements IWindow {
-
- @SuppressWarnings("unused")
- public void dispatchAppVisibility(boolean arg0) throws RemoteException {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public void dispatchGetNewSurface() throws RemoteException {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public void dispatchKey(KeyEvent arg0) throws RemoteException {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public void dispatchPointer(MotionEvent arg0, long arg1, boolean arg2) throws RemoteException {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public void dispatchTrackball(MotionEvent arg0, long arg1, boolean arg2) throws RemoteException {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public void executeCommand(String arg0, String arg1, ParcelFileDescriptor arg2)
- throws RemoteException {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public void resized(int arg0, int arg1, Rect arg2, Rect arg3, boolean arg4, Configuration arg5)
- throws RemoteException {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public void windowFocusChanged(boolean arg0, boolean arg1) throws RemoteException {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep,
- boolean sync) {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public void dispatchWallpaperCommand(String action, int x, int y,
- int z, Bundle extras, boolean sync) {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public void closeSystemDialogs(String reason) {
- // pass for now.
- }
-
- @SuppressWarnings("unused")
- public void dispatchDragEvent(DragEvent event) {
- // pass for now.
- }
-
- public IBinder asBinder() {
- // pass for now.
- return null;
- }
+ @Deprecated
+ public com.android.layoutlib.api.ILayoutResult computeLayout(IXmlPullParser layoutDescription,
+ Object projectKey,
+ int screenWidth, int screenHeight, boolean renderFullSize,
+ int density, float xdpi, float ydpi,
+ String themeName, boolean isProjectTheme,
+ Map<String, Map<String, IResourceValue>> projectResources,
+ Map<String, Map<String, IResourceValue>> frameworkResources,
+ IProjectCallback customViewLoader, ILayoutLog logger) {
+ throw new UnsupportedOperationException();
}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeLayoutScene.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeLayoutScene.java
new file mode 100644
index 0000000..5fcb9ff
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeLayoutScene.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 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;
+
+import com.android.layoutlib.api.LayoutScene;
+import com.android.layoutlib.api.SceneResult;
+import com.android.layoutlib.api.ViewInfo;
+import com.android.layoutlib.bridge.impl.LayoutSceneImpl;
+
+import java.awt.image.BufferedImage;
+
+/**
+ * An implementation of {@link LayoutScene}.
+ *
+ * This is a pretty basic class that does almost nothing. All of the work is done in
+ * {@link LayoutSceneImpl}.
+ *
+ */
+public class BridgeLayoutScene extends LayoutScene {
+
+ private final Bridge mBridge;
+ private final LayoutSceneImpl mScene;
+ private SceneResult mLastResult;
+
+ @Override
+ public SceneResult getResult() {
+ return mLastResult;
+ }
+
+ @Override
+ public BufferedImage getImage() {
+ return mScene.getImage();
+ }
+
+ @Override
+ public ViewInfo getRootView() {
+ return mScene.getViewInfo();
+ }
+
+ @Override
+ public SceneResult render() {
+
+ synchronized (mBridge) {
+ try {
+ mScene.prepare();
+ mLastResult = mScene.render();
+ } finally {
+ mScene.cleanup();
+ }
+ }
+
+ return mLastResult;
+ }
+
+ @Override
+ public void dispose() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*package*/ BridgeLayoutScene(Bridge bridge, LayoutSceneImpl scene, SceneResult lastResult) {
+ mBridge = bridge;
+ mScene = scene;
+ mLastResult = lastResult;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/LayoutResult.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/LayoutResult.java
deleted file mode 100644
index c4c5225..0000000
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/LayoutResult.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2008 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;
-
-import com.android.layoutlib.api.ILayoutResult;
-
-import java.awt.image.BufferedImage;
-
-/**
- * Implementation of {@link ILayoutResult}
- */
-public final class LayoutResult implements ILayoutResult {
-
- private final ILayoutViewInfo mRootView;
- private final BufferedImage mImage;
- private final int mSuccess;
- private final String mErrorMessage;
-
- /**
- * Creates a {@link #SUCCESS} {@link ILayoutResult} with the specified params
- * @param rootView
- * @param image
- */
- public LayoutResult(ILayoutViewInfo rootView, BufferedImage image) {
- mSuccess = SUCCESS;
- mErrorMessage = null;
- mRootView = rootView;
- mImage = image;
- }
-
- /**
- * Creates a LayoutResult with a specific success code and associated message
- * @param code
- * @param message
- */
- public LayoutResult(int code, String message) {
- mSuccess = code;
- mErrorMessage = message;
- mRootView = null;
- mImage = null;
- }
-
- public int getSuccess() {
- return mSuccess;
- }
-
- public String getErrorMessage() {
- return mErrorMessage;
- }
-
- public BufferedImage getImage() {
- return mImage;
- }
-
- public ILayoutViewInfo getRootView() {
- return mRootView;
- }
-
- /**
- * Implementation of {@link ILayoutResult.ILayoutViewInfo}
- */
- public static final class LayoutViewInfo implements ILayoutViewInfo {
- private final Object mKey;
- private final String mName;
- private final int mLeft;
- private final int mRight;
- private final int mTop;
- private final int mBottom;
- private ILayoutViewInfo[] mChildren;
-
- public LayoutViewInfo(String name, Object key, int left, int top, int right, int bottom) {
- mName = name;
- mKey = key;
- mLeft = left;
- mRight = right;
- mTop = top;
- mBottom = bottom;
- }
-
- public void setChildren(ILayoutViewInfo[] children) {
- mChildren = children;
- }
-
- public ILayoutViewInfo[] getChildren() {
- return mChildren;
- }
-
- public Object getViewKey() {
- return mKey;
- }
-
- public String getName() {
- return mName;
- }
-
- public int getLeft() {
- return mLeft;
- }
-
- public int getTop() {
- return mTop;
- }
-
- public int getRight() {
- return mRight;
- }
-
- public int getBottom() {
- return mBottom;
- }
- }
-}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeAssetManager.java
index 71803fc..a825060 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeAssetManager.java
@@ -14,7 +14,9 @@
* limitations under the License.
*/
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
+
+import com.android.layoutlib.bridge.Bridge;
import android.content.res.AssetManager;
@@ -28,7 +30,7 @@ public class BridgeAssetManager extends AssetManager {
* <p/>
* {@link Bridge} calls this method after setting up a new bridge.
*/
- /*package*/ static AssetManager initSystem() {
+ /*package*/ public static AssetManager initSystem() {
if (!(AssetManager.sSystem instanceof BridgeAssetManager)) {
// Note that AssetManager() creates a system AssetManager and we override it
// with our BridgeAssetManager.
@@ -42,7 +44,7 @@ public class BridgeAssetManager extends AssetManager {
* Clears the static {@link AssetManager#sSystem} to make sure we don't leave objects
* around that would prevent us from unloading the library.
*/
- /*package*/ static void clearSystem() {
+ public static void clearSystem() {
AssetManager.sSystem = null;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentProvider.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
index 9d6dd27..3835378 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentProvider.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentResolver.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentResolver.java
index e15cb69..0257686 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentResolver.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentResolver.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index b9899b2..2fa97a3 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -14,12 +14,15 @@
* limitations under the License.
*/
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
import com.android.layoutlib.api.ILayoutLog;
import com.android.layoutlib.api.IProjectCallback;
import com.android.layoutlib.api.IResourceValue;
import com.android.layoutlib.api.IStyleResourceValue;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.BridgeConstants;
+import com.android.layoutlib.bridge.impl.TempResourceValue;
import android.app.Activity;
import android.app.Fragment;
@@ -50,7 +53,6 @@ import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
-import android.view.BridgeInflater;
import android.view.LayoutInflater;
import android.view.View;
@@ -66,15 +68,16 @@ import java.util.TreeMap;
import java.util.Map.Entry;
/**
- * Custom implementation of Context to handle non compiled resources.
+ * Custom implementation of Context/Activity to handle non compiled resources.
*/
public final class BridgeContext extends Activity {
- private final Resources mResources;
- private final Theme mTheme;
+ private Resources mResources;
+ private Theme mTheme;
private final HashMap<View, Object> mViewKeyMap = new HashMap<View, Object>();
private final IStyleResourceValue mThemeValues;
private final Object mProjectKey;
+ private final DisplayMetrics mMetrics;
private final Map<String, Map<String, IResourceValue>> mProjectResources;
private final Map<String, Map<String, IResourceValue>> mFrameworkResources;
private final Map<IStyleResourceValue, IStyleResourceValue> mStyleInheritanceMap;
@@ -105,28 +108,18 @@ public final class BridgeContext extends Activity {
* contains (String, {@link IResourceValue}) pairs where the key is the resource name, and the
* value is the resource value.
* @param styleInheritanceMap
- * @param customViewLoader
+ * @param projectCallback
*/
public BridgeContext(Object projectKey, DisplayMetrics metrics,
IStyleResourceValue currentTheme,
Map<String, Map<String, IResourceValue>> projectResources,
Map<String, Map<String, IResourceValue>> frameworkResources,
Map<IStyleResourceValue, IStyleResourceValue> styleInheritanceMap,
- IProjectCallback customViewLoader, ILayoutLog logger) {
+ IProjectCallback projectCallback, ILayoutLog logger) {
mProjectKey = projectKey;
- mProjectCallback = customViewLoader;
+ mMetrics = metrics;
+ mProjectCallback = projectCallback;
mLogger = logger;
- Configuration config = new Configuration();
-
- AssetManager assetManager = BridgeAssetManager.initSystem();
- mResources = BridgeResources.initSystem(
- this,
- assetManager,
- metrics,
- config,
- customViewLoader);
-
- mTheme = mResources.newTheme();
mThemeValues = currentTheme;
mProjectResources = projectResources;
@@ -137,6 +130,32 @@ public final class BridgeContext extends Activity {
mFragments.mActivity = this;
}
+ /**
+ * Initializes the {@link Resources} singleton to be linked to this {@link Context}, its
+ * {@link DisplayMetrics}, {@link Configuration}, and {@link IProjectCallback}.
+ *
+ * @see #disposeResources()
+ */
+ public void initResources() {
+ AssetManager assetManager = AssetManager.getSystem();
+ Configuration config = new Configuration();
+
+ mResources = BridgeResources.initSystem(
+ this,
+ assetManager,
+ mMetrics,
+ config,
+ mProjectCallback);
+ mTheme = mResources.newTheme();
+ }
+
+ /**
+ * Disposes the {@link Resources} singleton.
+ */
+ public void disposeResources() {
+ BridgeResources.disposeSystem();
+ }
+
public void setBridgeInflater(BridgeInflater inflater) {
mInflater = inflater;
}
@@ -266,6 +285,15 @@ public final class BridgeContext extends Activity {
return null;
}
+ Object key = null;
+ if (parser != null) {
+ key = parser.getViewKey();
+ }
+ if (key != null) {
+ String attrs_name = Bridge.resolveResourceValue(attrs);
+ System.out.println("KEY: " + key.toString() + "(" + attrs_name + ")");
+ }
+
boolean[] frameworkAttributes = new boolean[1];
TreeMap<Integer, String> styleNameMap = searchAttrs(attrs, frameworkAttributes);
@@ -281,6 +309,9 @@ public final class BridgeContext extends Activity {
customStyle = parser.getAttributeValue(null /* namespace*/, "style");
}
if (customStyle != null) {
+ if (key != null) {
+ print("style", customStyle, false);
+ }
IResourceValue item = findResValue(customStyle, false /*forceFrameworkOnly*/);
if (item instanceof IStyleResourceValue) {
@@ -292,6 +323,10 @@ public final class BridgeContext extends Activity {
// get the name from the int.
String defStyleName = searchAttr(defStyleAttr);
+ if (key != null) {
+ print("style", defStyleName, true);
+ }
+
// look for the style in the current theme, and its parent:
if (mThemeValues != null) {
IResourceValue item = findItemInStyle(mThemeValues, defStyleName);
@@ -350,11 +385,20 @@ public final class BridgeContext extends Activity {
// if we found a value, we make sure this doesn't reference another value.
// So we resolve it.
if (resValue != null) {
+ if (key != null) {
+ print(name, resValue.getValue(), true);
+ }
+
resValue = resolveResValue(resValue);
+ } else if (key != null) {
+ print(name, "<unknown>", true);
}
ta.bridgeSetValue(index, name, resValue);
} else {
+ if (key != null) {
+ print(name, value, false);
+ }
// there is a value in the XML, but we need to resolve it in case it's
// referencing another resource or a theme value.
ta.bridgeSetValue(index, name, resolveValue(null, name, value));
@@ -367,6 +411,15 @@ public final class BridgeContext extends Activity {
return ta;
}
+ private void print(String name, String value, boolean isDefault) {
+ System.out.print("\t" + name + " : " + value);
+ if (isDefault) {
+ System.out.println(" (default)");
+ } else {
+ System.out.println("");
+ }
+ }
+
@Override
public Looper getMainLooper() {
return Looper.myLooper();
@@ -433,7 +486,7 @@ public final class BridgeContext extends Activity {
// if resValue is null, but value is not null, this means it was not a reference.
// we return the name/value wrapper in a IResourceValue
if (resValue == null) {
- return new ResourceValue(type, name, value);
+ return new TempResourceValue(type, name, value);
}
// we resolved a first reference, but we need to make sure this isn't a reference also.
@@ -453,7 +506,7 @@ public final class BridgeContext extends Activity {
* @param value the value containing the reference to resolve.
* @return a {@link IResourceValue} object or <code>null</code>
*/
- IResourceValue resolveResValue(IResourceValue value) {
+ public IResourceValue resolveResValue(IResourceValue value) {
if (value == null) {
return null;
}
@@ -661,7 +714,7 @@ public final class BridgeContext extends Activity {
* @param itemName the name of the item to search for.
* @return the {@link IResourceValue} object or <code>null</code>
*/
- IResourceValue findItemInStyle(IStyleResourceValue style, String itemName) {
+ public IResourceValue findItemInStyle(IStyleResourceValue style, String itemName) {
IResourceValue item = style.findItem(itemName);
// if we didn't find it, we look in the parent style (if applicable)
diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java
index 4bc8855..b4a28a6 100644
--- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java
@@ -14,20 +14,22 @@
* limitations under the License.
*/
-package android.view;
+package com.android.layoutlib.bridge.android;
import com.android.layoutlib.api.IProjectCallback;
import com.android.layoutlib.api.IResourceValue;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.BridgeConstants;
-import com.android.layoutlib.bridge.BridgeContext;
-import com.android.layoutlib.bridge.BridgeXmlBlockParser;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;
import android.content.Context;
import android.util.AttributeSet;
+import android.view.InflateException;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
import java.io.File;
import java.io.FileReader;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeResources.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
index 6358abb..46eb776 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
@@ -14,10 +14,13 @@
* limitations under the License.
*/
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
import com.android.layoutlib.api.IProjectCallback;
import com.android.layoutlib.api.IResourceValue;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.BridgeConstants;
+import com.android.layoutlib.bridge.impl.ResourceHelper;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;
@@ -64,21 +67,18 @@ public final class BridgeResources extends Resources {
DisplayMetrics metrics,
Configuration config,
IProjectCallback projectCallback) {
- if (!(Resources.mSystem instanceof BridgeResources)) {
- Resources.mSystem = new BridgeResources(context,
- assets,
- metrics,
- config,
- projectCallback);
- }
- return Resources.mSystem;
+ return Resources.mSystem = new BridgeResources(context,
+ assets,
+ metrics,
+ config,
+ projectCallback);
}
/**
- * Clears the static {@link Resources#mSystem} to make sure we don't leave objects
+ * Disposes the static {@link Resources#mSystem} to make sure we don't leave objects
* around that would prevent us from unloading the library.
*/
- /*package*/ static void clearSystem() {
+ /*package*/ static void disposeSystem() {
if (Resources.mSystem instanceof BridgeResources) {
((BridgeResources)(Resources.mSystem)).mContext = null;
((BridgeResources)(Resources.mSystem)).mProjectCallback = null;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
index 70c5bd7..c3ab461 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
@@ -14,11 +14,14 @@
* limitations under the License.
*/
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
import com.android.internal.util.XmlUtils;
import com.android.layoutlib.api.IResourceValue;
import com.android.layoutlib.api.IStyleResourceValue;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.BridgeConstants;
+import com.android.layoutlib.bridge.impl.ResourceHelper;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;
@@ -36,7 +39,7 @@ import java.io.FileReader;
import java.util.Map;
/**
- * TODO: describe.
+ * Custom implementation of TypedArray to handle non compiled resources.
*/
public final class BridgeTypedArray extends TypedArray {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
new file mode 100644
index 0000000..c04c9e8
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2010 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.android;
+
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.view.DragEvent;
+import android.view.IWindow;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View.AttachInfo;
+
+/**
+ * Implementation of {@link IWindow} to pass to the {@link AttachInfo}.
+ */
+public final class BridgeWindow implements IWindow {
+
+ public void dispatchAppVisibility(boolean arg0) throws RemoteException {
+ // pass for now.
+ }
+
+ public void dispatchGetNewSurface() throws RemoteException {
+ // pass for now.
+ }
+
+ public void dispatchKey(KeyEvent arg0) throws RemoteException {
+ // pass for now.
+ }
+
+ public void dispatchPointer(MotionEvent arg0, long arg1, boolean arg2) throws RemoteException {
+ // pass for now.
+ }
+
+ public void dispatchTrackball(MotionEvent arg0, long arg1, boolean arg2) throws RemoteException {
+ // pass for now.
+ }
+
+ public void executeCommand(String arg0, String arg1, ParcelFileDescriptor arg2)
+ throws RemoteException {
+ // pass for now.
+ }
+
+ public void resized(int arg0, int arg1, Rect arg2, Rect arg3, boolean arg4, Configuration arg5)
+ throws RemoteException {
+ // pass for now.
+ }
+
+ public void windowFocusChanged(boolean arg0, boolean arg1) throws RemoteException {
+ // pass for now.
+ }
+
+ public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep,
+ boolean sync) {
+ // pass for now.
+ }
+
+ public void dispatchWallpaperCommand(String action, int x, int y,
+ int z, Bundle extras, boolean sync) {
+ // pass for now.
+ }
+
+ public void closeSystemDialogs(String reason) {
+ // pass for now.
+ }
+
+ public void dispatchDragEvent(DragEvent event) {
+ // pass for now.
+ }
+
+ public IBinder asBinder() {
+ // pass for now.
+ return null;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
new file mode 100644
index 0000000..74e5a65
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2010 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.android;
+
+import android.content.ClipData;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.view.IWindow;
+import android.view.IWindowSession;
+import android.view.InputChannel;
+import android.view.MotionEvent;
+import android.view.Surface;
+import android.view.SurfaceView;
+import android.view.WindowManager.LayoutParams;
+
+/**
+ * Implementation of {@link IWindowSession} so that mSession is not null in
+ * the {@link SurfaceView}.
+ */
+public final class BridgeWindowSession implements IWindowSession {
+
+ public int add(IWindow arg0, LayoutParams arg1, int arg2, Rect arg3,
+ InputChannel outInputchannel)
+ throws RemoteException {
+ // pass for now.
+ return 0;
+ }
+
+ public int addWithoutInputChannel(IWindow arg0, LayoutParams arg1, int arg2, Rect arg3)
+ throws RemoteException {
+ // pass for now.
+ return 0;
+ }
+
+ public void finishDrawing(IWindow arg0) throws RemoteException {
+ // pass for now.
+ }
+
+ public void finishKey(IWindow arg0) throws RemoteException {
+ // pass for now.
+ }
+
+ public boolean getInTouchMode() throws RemoteException {
+ // pass for now.
+ return false;
+ }
+
+ public boolean performHapticFeedback(IWindow window, int effectId, boolean always) {
+ // pass for now.
+ return false;
+ }
+
+ public MotionEvent getPendingPointerMove(IWindow arg0) throws RemoteException {
+ // pass for now.
+ return null;
+ }
+
+ public MotionEvent getPendingTrackballMove(IWindow arg0) throws RemoteException {
+ // pass for now.
+ return null;
+ }
+
+ public int relayout(IWindow arg0, LayoutParams arg1, int arg2, int arg3, int arg4,
+ boolean arg4_5, Rect arg5, Rect arg6, Rect arg7, Configuration arg7b, Surface arg8)
+ throws RemoteException {
+ // pass for now.
+ return 0;
+ }
+
+ public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
+ // pass for now.
+ }
+
+ public void remove(IWindow arg0) throws RemoteException {
+ // pass for now.
+ }
+
+ public void setInTouchMode(boolean arg0) throws RemoteException {
+ // pass for now.
+ }
+
+ public void setTransparentRegion(IWindow arg0, Region arg1) throws RemoteException {
+ // pass for now.
+ }
+
+ public void setInsets(IWindow window, int touchable, Rect contentInsets,
+ Rect visibleInsets) {
+ // pass for now.
+ }
+
+ public IBinder prepareDrag(IWindow window, boolean localOnly,
+ int thumbnailWidth, int thumbnailHeight, Surface outSurface)
+ throws RemoteException {
+ // pass for now
+ return null;
+ }
+
+ public boolean performDrag(IWindow window, IBinder dragToken,
+ float touchX, float touchY, float thumbCenterX, float thumbCenterY,
+ ClipData data)
+ throws RemoteException {
+ // pass for now
+ return false;
+ }
+
+ public void reportDropResult(IWindow window, boolean consumed) throws RemoteException {
+ // pass for now
+ }
+
+ public void dragRecipientEntered(IWindow window) throws RemoteException {
+ // pass for now
+ }
+
+ public void dragRecipientExited(IWindow window) throws RemoteException {
+ // pass for now
+ }
+
+ public void setWallpaperPosition(IBinder window, float x, float y,
+ float xStep, float yStep) {
+ // pass for now.
+ }
+
+ public void wallpaperOffsetsComplete(IBinder window) {
+ // pass for now.
+ }
+
+ public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
+ int z, Bundle extras, boolean sync) {
+ // pass for now.
+ return null;
+ }
+
+ public void wallpaperCommandComplete(IBinder window, Bundle result) {
+ // pass for now.
+ }
+
+ public void closeSystemDialogs(String reason) {
+ // pass for now.
+ }
+
+ public IBinder asBinder() {
+ // pass for now.
+ return null;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeXmlBlockParser.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java
index d842a66..24f61c8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeXmlBlockParser.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
import com.android.layoutlib.api.IXmlPullParser;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeXmlPullAttributes.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlPullAttributes.java
index d145ff6..c99b70b 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeXmlPullAttributes.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlPullAttributes.java
@@ -14,9 +14,11 @@
* limitations under the License.
*/
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
import com.android.layoutlib.api.IResourceValue;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.BridgeConstants;
import org.xmlpull.v1.XmlPullParser;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/MockView.java
index 1ca3182..e5bddcb 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/MockView.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
import android.content.Context;
import android.graphics.Canvas;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/NinePatchDrawable.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/NinePatchDrawable.java
index 2c92567..4efa631 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/NinePatchDrawable.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/NinePatchDrawable.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
import com.android.ninepatch.NinePatch;
@@ -28,7 +28,7 @@ public class NinePatchDrawable extends Drawable {
private NinePatch m9Patch;
- NinePatchDrawable(NinePatch ninePatch) {
+ public NinePatchDrawable(NinePatch ninePatch) {
m9Patch = ninePatch;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/DelegateManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
index 3d9f960..169d751 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/DelegateManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.impl;
import android.util.SparseArray;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/FontLoader.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/FontLoader.java
index de89a81..5d56370 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/FontLoader.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/FontLoader.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.impl;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
new file mode 100644
index 0000000..2012229
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
@@ -0,0 +1,689 @@
+/*
+ * Copyright (C) 2010 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.impl;
+
+import com.android.internal.util.XmlUtils;
+import com.android.layoutlib.api.IProjectCallback;
+import com.android.layoutlib.api.IResourceValue;
+import com.android.layoutlib.api.IStyleResourceValue;
+import com.android.layoutlib.api.LayoutBridge;
+import com.android.layoutlib.api.SceneParams;
+import com.android.layoutlib.api.SceneResult;
+import com.android.layoutlib.api.ViewInfo;
+import com.android.layoutlib.api.IDensityBasedResourceValue.Density;
+import com.android.layoutlib.bridge.BridgeConstants;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.android.BridgeInflater;
+import com.android.layoutlib.bridge.android.BridgeWindow;
+import com.android.layoutlib.bridge.android.BridgeWindowSession;
+import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
+
+import android.app.Fragment_Delegate;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap_Delegate;
+import android.graphics.Canvas;
+import android.graphics.Canvas_Delegate;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.View.AttachInfo;
+import android.view.View.MeasureSpec;
+import android.widget.FrameLayout;
+import android.widget.TabHost;
+import android.widget.TabWidget;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Class managing a layout "scene".
+ *
+ * A scene is a stateful representation of a layout file. It is initialized with data coming through
+ * the {@link LayoutBridge} API to inflate the layout. Further actions and rendering can then
+ * be done on the layout.
+ *
+ */
+public class LayoutSceneImpl {
+
+ private static final int DEFAULT_TITLE_BAR_HEIGHT = 25;
+ private static final int DEFAULT_STATUS_BAR_HEIGHT = 25;
+
+ private final SceneParams mParams;
+
+ // scene state
+ private BridgeContext mContext;
+ private BridgeXmlBlockParser mBlockParser;
+ private BridgeInflater mInflater;
+ private IStyleResourceValue mCurrentTheme;
+ private int mScreenOffset;
+ private IResourceValue mWindowBackground;
+ private FrameLayout mViewRoot;
+
+ // information being returned through the API
+ private BufferedImage mImage;
+ private ViewInfo mViewInfo;
+
+ private static final class PostInflateException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public PostInflateException(String message) {
+ super(message);
+ }
+ }
+
+ /**
+ * Creates a layout scene with all the information coming from the layout bridge API.
+ *
+ * This also calls {@link LayoutSceneImpl#prepare()}.
+ * <p>
+ * <b>THIS MUST BE INSIDE A SYNCHRONIZED BLOCK on the BRIDGE OBJECT.<b>
+ *
+ * @see LayoutBridge#createScene(com.android.layoutlib.api.SceneParams)
+ */
+ public LayoutSceneImpl(SceneParams params) {
+ // we need to make sure the Looper has been initialized for this thread.
+ // this is required for View that creates Handler objects.
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+
+ // copy the params.
+ mParams = new SceneParams(params);
+
+ // setup the display Metrics.
+ DisplayMetrics metrics = new DisplayMetrics();
+ metrics.densityDpi = mParams.getDensity();
+ metrics.density = mParams.getDensity() / (float) DisplayMetrics.DENSITY_DEFAULT;
+ metrics.scaledDensity = metrics.density;
+ metrics.widthPixels = mParams.getScreenWidth();
+ metrics.heightPixels = mParams.getScreenHeight();
+ metrics.xdpi = mParams.getXdpi();
+ metrics.ydpi = mParams.getYdpi();
+
+ // find the current theme and compute the style inheritance map
+ Map<IStyleResourceValue, IStyleResourceValue> styleParentMap =
+ new HashMap<IStyleResourceValue, IStyleResourceValue>();
+
+ mCurrentTheme = computeStyleMaps(mParams.getThemeName(), mParams.getIsProjectTheme(),
+ mParams.getProjectResources().get(BridgeConstants.RES_STYLE),
+ mParams.getFrameworkResources().get(BridgeConstants.RES_STYLE), styleParentMap);
+
+ // build the context
+ mContext = new BridgeContext(mParams.getProjectKey(), metrics, mCurrentTheme,
+ mParams.getProjectResources(), mParams.getFrameworkResources(),
+ styleParentMap, mParams.getProjectCallback(), mParams.getLogger());
+
+ // make sure the Resources object references the context (and other objects) for this
+ // scene
+ mContext.initResources();
+
+ // get the screen offset and window-background resource
+ mWindowBackground = null;
+ mScreenOffset = 0;
+ if (mCurrentTheme != null && mParams.isCustomBackgroundEnabled() == false) {
+ mWindowBackground = mContext.findItemInStyle(mCurrentTheme, "windowBackground");
+ mWindowBackground = mContext.resolveResValue(mWindowBackground);
+
+ mScreenOffset = getScreenOffset(mParams.getFrameworkResources(), mCurrentTheme, mContext);
+ }
+
+ // build the inflater and parser.
+ mInflater = new BridgeInflater(mContext, mParams.getProjectCallback());
+ mContext.setBridgeInflater(mInflater);
+ mInflater.setFactory2(mContext);
+
+ mBlockParser = new BridgeXmlBlockParser(mParams.getLayoutDescription(),
+ mContext, false /* platformResourceFlag */);
+ }
+
+ /**
+ * Prepares the scene for action.
+ * <p>
+ * <b>THIS MUST BE INSIDE A SYNCHRONIZED BLOCK on the BRIDGE OBJECT.<b>
+ */
+ public void prepare() {
+ // we need to make sure the Looper has been initialized for this thread.
+ // this is required for View that creates Handler objects.
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+
+ // make sure the Resources object references the context (and other objects) for this
+ // scene
+ mContext.initResources();
+ }
+
+ /**
+ * Cleans up the scene after an action.
+ * <p>
+ * <b>THIS MUST BE INSIDE A SYNCHRONIZED BLOCK on the BRIDGE OBJECT.<b>
+ */
+ public void cleanup() {
+ // clean up the looper
+ Looper.sThreadLocal.remove();
+
+ // Make sure to remove static references, otherwise we could not unload the lib
+ mContext.disposeResources();
+ }
+
+ /**
+ * Inflates the layout.
+ * <p>
+ * <b>THIS MUST BE INSIDE A SYNCHRONIZED BLOCK on the BRIDGE OBJECT.<b>
+ */
+ public SceneResult inflate() {
+ try {
+
+ mViewRoot = new FrameLayout(mContext);
+
+ // 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);
+
+ // post-inflate process. For now this supports TabHost/TabWidget
+ postInflateProcess(view, mParams.getProjectCallback());
+
+ Fragment_Delegate.setProjectCallback(null);
+
+ // set the AttachInfo on the root view.
+ AttachInfo info = new AttachInfo(new BridgeWindowSession(), new BridgeWindow(),
+ new Handler(), null);
+ info.mHasWindowFocus = true;
+ info.mWindowVisibility = View.VISIBLE;
+ info.mInTouchMode = false; // this is so that we can display selections.
+ mViewRoot.dispatchAttachedToWindow(info, 0);
+
+ // get the background drawable
+ if (mWindowBackground != null) {
+ Drawable d = ResourceHelper.getDrawable(mWindowBackground,
+ mContext, true /* isFramework */);
+ mViewRoot.setBackgroundDrawable(d);
+ }
+
+ return SceneResult.SUCCESS;
+ } catch (PostInflateException e) {
+ return new SceneResult("Error during post inflation process:\n" + e.getMessage());
+ } catch (Throwable e) {
+ // get the real cause of the exception.
+ Throwable t = e;
+ while (t.getCause() != null) {
+ t = t.getCause();
+ }
+
+ // log it
+ mParams.getLogger().error(t);
+
+ return new SceneResult("Unknown error during inflation.", t);
+ }
+ }
+
+ /**
+ * Renders the scene.
+ * <p>
+ * <b>THIS MUST BE INSIDE A SYNCHRONIZED BLOCK on the BRIDGE OBJECT.<b>
+ */
+ public SceneResult render() {
+ try {
+ if (mViewRoot == null) {
+ return new SceneResult("Layout has not been inflated!");
+ }
+ // measure the views
+ int w_spec, h_spec;
+
+ int renderScreenWidth = mParams.getScreenWidth();
+ int renderScreenHeight = mParams.getScreenHeight();
+
+ if (mParams.getRenderFullSize()) {
+ // measure the full size needed by the layout.
+ w_spec = MeasureSpec.makeMeasureSpec(renderScreenWidth,
+ MeasureSpec.UNSPECIFIED); // this lets us know the actual needed size
+ h_spec = MeasureSpec.makeMeasureSpec(renderScreenHeight - mScreenOffset,
+ MeasureSpec.UNSPECIFIED); // this lets us know the actual needed size
+ mViewRoot.measure(w_spec, h_spec);
+
+ int neededWidth = mViewRoot.getChildAt(0).getMeasuredWidth();
+ if (neededWidth > renderScreenWidth) {
+ renderScreenWidth = neededWidth;
+ }
+
+ int neededHeight = mViewRoot.getChildAt(0).getMeasuredHeight();
+ if (neededHeight > renderScreenHeight - mScreenOffset) {
+ renderScreenHeight = neededHeight + mScreenOffset;
+ }
+ }
+
+ // remeasure with the size we need
+ // This must always be done before the call to layout
+ w_spec = MeasureSpec.makeMeasureSpec(renderScreenWidth, MeasureSpec.EXACTLY);
+ h_spec = MeasureSpec.makeMeasureSpec(renderScreenHeight - mScreenOffset,
+ MeasureSpec.EXACTLY);
+ mViewRoot.measure(w_spec, h_spec);
+
+ // now do the layout.
+ mViewRoot.layout(0, mScreenOffset, renderScreenWidth, renderScreenHeight);
+
+ // draw the views
+ // create the BufferedImage into which the layout will be rendered.
+ mImage = new BufferedImage(renderScreenWidth, renderScreenHeight - mScreenOffset,
+ BufferedImage.TYPE_INT_ARGB);
+
+ if (mParams.isCustomBackgroundEnabled()) {
+ Graphics2D gc = mImage.createGraphics();
+ gc.setColor(new Color(mParams.getCustomBackgroundColor()));
+ gc.fillRect(0, 0, renderScreenWidth, renderScreenHeight - mScreenOffset);
+ gc.dispose();
+ }
+
+ // create an Android bitmap around the BufferedImage
+ Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
+ Density.getEnum(mParams.getDensity()));
+
+ // create a Canvas around the Android bitmap
+ Canvas canvas = new Canvas(bitmap);
+
+ // to set the logger, get the native delegate
+ Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(canvas);
+ canvasDelegate.setLogger(mParams.getLogger());
+
+ mViewRoot.draw(canvas);
+ canvasDelegate.dispose();
+
+ mViewInfo = visit(((ViewGroup)mViewRoot).getChildAt(0), mContext);
+
+ // success!
+ return SceneResult.SUCCESS;
+ } catch (Throwable e) {
+ // get the real cause of the exception.
+ Throwable t = e;
+ while (t.getCause() != null) {
+ t = t.getCause();
+ }
+
+ // log it
+ mParams.getLogger().error(t);
+
+ return new SceneResult("Unknown error during inflation.", t);
+ }
+ }
+
+ /**
+ * Compute style information from the given list of style for the project and framework.
+ * @param themeName the name of the current theme. In order to differentiate project and
+ * platform themes sharing the same name, all project themes must be prepended with
+ * a '*' character.
+ * @param isProjectTheme Is this a project theme
+ * @param inProjectStyleMap the project style map
+ * @param inFrameworkStyleMap the framework style map
+ * @param outInheritanceMap the map of style inheritance. This is filled by the method
+ * @return the {@link IStyleResourceValue} matching <var>themeName</var>
+ */
+ private IStyleResourceValue computeStyleMaps(
+ String themeName, boolean isProjectTheme, Map<String,
+ IResourceValue> inProjectStyleMap, Map<String, IResourceValue> inFrameworkStyleMap,
+ Map<IStyleResourceValue, IStyleResourceValue> outInheritanceMap) {
+
+ if (inProjectStyleMap != null && inFrameworkStyleMap != null) {
+ // first, get the theme
+ IResourceValue theme = null;
+
+ // project theme names have been prepended with a *
+ if (isProjectTheme) {
+ theme = inProjectStyleMap.get(themeName);
+ } else {
+ theme = inFrameworkStyleMap.get(themeName);
+ }
+
+ if (theme instanceof IStyleResourceValue) {
+ // compute the inheritance map for both the project and framework styles
+ computeStyleInheritance(inProjectStyleMap.values(), inProjectStyleMap,
+ inFrameworkStyleMap, outInheritanceMap);
+
+ // Compute the style inheritance for the framework styles/themes.
+ // Since, for those, the style parent values do not contain 'android:'
+ // we want to force looking in the framework style only to avoid using
+ // similarly named styles from the project.
+ // To do this, we pass null in lieu of the project style map.
+ computeStyleInheritance(inFrameworkStyleMap.values(), null /*inProjectStyleMap */,
+ inFrameworkStyleMap, outInheritanceMap);
+
+ return (IStyleResourceValue)theme;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Compute the parent style for all the styles in a given list.
+ * @param styles the styles for which we compute the parent.
+ * @param inProjectStyleMap the map of project styles.
+ * @param inFrameworkStyleMap the map of framework styles.
+ * @param outInheritanceMap the map of style inheritance. This is filled by the method.
+ */
+ private void computeStyleInheritance(Collection<IResourceValue> styles,
+ Map<String, IResourceValue> inProjectStyleMap,
+ Map<String, IResourceValue> inFrameworkStyleMap,
+ Map<IStyleResourceValue, IStyleResourceValue> outInheritanceMap) {
+ for (IResourceValue value : styles) {
+ if (value instanceof IStyleResourceValue) {
+ IStyleResourceValue style = (IStyleResourceValue)value;
+ IStyleResourceValue parentStyle = null;
+
+ // first look for a specified parent.
+ String parentName = style.getParentStyle();
+
+ // no specified parent? try to infer it from the name of the style.
+ if (parentName == null) {
+ parentName = getParentName(value.getName());
+ }
+
+ if (parentName != null) {
+ parentStyle = getStyle(parentName, inProjectStyleMap, inFrameworkStyleMap);
+
+ if (parentStyle != null) {
+ outInheritanceMap.put(style, parentStyle);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Searches for and returns the {@link IStyleResourceValue} from a given name.
+ * <p/>The format of the name can be:
+ * <ul>
+ * <li>[android:]&lt;name&gt;</li>
+ * <li>[android:]style/&lt;name&gt;</li>
+ * <li>@[android:]style/&lt;name&gt;</li>
+ * </ul>
+ * @param parentName the name of the style.
+ * @param inProjectStyleMap the project style map. Can be <code>null</code>
+ * @param inFrameworkStyleMap the framework style map.
+ * @return The matching {@link IStyleResourceValue} object or <code>null</code> if not found.
+ */
+ private IStyleResourceValue getStyle(String parentName,
+ Map<String, IResourceValue> inProjectStyleMap,
+ Map<String, IResourceValue> inFrameworkStyleMap) {
+ boolean frameworkOnly = false;
+
+ String name = parentName;
+
+ // remove the useless @ if it's there
+ if (name.startsWith(BridgeConstants.PREFIX_RESOURCE_REF)) {
+ name = name.substring(BridgeConstants.PREFIX_RESOURCE_REF.length());
+ }
+
+ // check for framework identifier.
+ if (name.startsWith(BridgeConstants.PREFIX_ANDROID)) {
+ frameworkOnly = true;
+ name = name.substring(BridgeConstants.PREFIX_ANDROID.length());
+ }
+
+ // at this point we could have the format <type>/<name>. we want only the name as long as
+ // the type is style.
+ if (name.startsWith(BridgeConstants.REFERENCE_STYLE)) {
+ name = name.substring(BridgeConstants.REFERENCE_STYLE.length());
+ } else if (name.indexOf('/') != -1) {
+ return null;
+ }
+
+ IResourceValue parent = null;
+
+ // if allowed, search in the project resources.
+ if (frameworkOnly == false && inProjectStyleMap != null) {
+ parent = inProjectStyleMap.get(name);
+ }
+
+ // if not found, then look in the framework resources.
+ if (parent == null) {
+ parent = inFrameworkStyleMap.get(name);
+ }
+
+ // make sure the result is the proper class type and return it.
+ if (parent instanceof IStyleResourceValue) {
+ return (IStyleResourceValue)parent;
+ }
+
+ mParams.getLogger().error(
+ String.format("Unable to resolve parent style name: %s", parentName));
+
+ return null;
+ }
+
+ /**
+ * Computes the name of the parent style, or <code>null</code> if the style is a root style.
+ */
+ private String getParentName(String styleName) {
+ int index = styleName.lastIndexOf('.');
+ if (index != -1) {
+ return styleName.substring(0, index);
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the top screen offset. This depends on whether the current theme defines the user
+ * of the title and status bars.
+ * @param frameworkResources The framework resources
+ * @param currentTheme The current theme
+ * @param context The context
+ * @return the pixel height offset
+ */
+ private int getScreenOffset(Map<String, Map<String, IResourceValue>> frameworkResources,
+ IStyleResourceValue currentTheme, BridgeContext context) {
+ int offset = 0;
+
+ // get the title bar flag from the current theme.
+ IResourceValue value = context.findItemInStyle(currentTheme, "windowNoTitle");
+
+ // because it may reference something else, we resolve it.
+ value = context.resolveResValue(value);
+
+ // if there's a value and it's true (default is false)
+ if (value == null || value.getValue() == null ||
+ XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) {
+ // default size of the window title bar
+ int defaultOffset = DEFAULT_TITLE_BAR_HEIGHT;
+
+ // get value from the theme.
+ value = context.findItemInStyle(currentTheme, "windowTitleSize");
+
+ // resolve it
+ value = context.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
+ defaultOffset = (int)typedValue.getDimension(context.getResources().mMetrics);
+ }
+ }
+
+ offset += defaultOffset;
+ }
+
+ // get the fullscreen flag from the current theme.
+ value = context.findItemInStyle(currentTheme, "windowFullscreen");
+
+ // because it may reference something else, we resolve it.
+ value = context.resolveResValue(value);
+
+ if (value == null || value.getValue() == null ||
+ XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) {
+
+ // default value
+ int defaultOffset = DEFAULT_STATUS_BAR_HEIGHT;
+
+ // get the real value, first the list of Dimensions from the framework map
+ Map<String, IResourceValue> dimens = frameworkResources.get(BridgeConstants.RES_DIMEN);
+
+ // now get the value
+ value = dimens.get("status_bar_height");
+ if (value != null) {
+ TypedValue typedValue = ResourceHelper.getValue(value.getValue());
+ if (typedValue != null) {
+ // compute the pixel value based on the display metrics
+ defaultOffset = (int)typedValue.getDimension(context.getResources().mMetrics);
+ }
+ }
+
+ // add the computed offset.
+ offset += defaultOffset;
+ }
+
+ return offset;
+
+ }
+
+ /**
+ * Post process on a view hierachy that was just inflated.
+ * <p/>At the moment this only support TabHost: If {@link TabHost} is detected, look for the
+ * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically
+ * based on the content of the {@link FrameLayout}.
+ * @param view the root view to process.
+ * @param projectCallback callback to the project.
+ */
+ private void postInflateProcess(View view, IProjectCallback projectCallback)
+ throws PostInflateException {
+ if (view instanceof TabHost) {
+ setupTabHost((TabHost)view, projectCallback);
+ } else if (view instanceof ViewGroup) {
+ ViewGroup group = (ViewGroup)view;
+ final int count = group.getChildCount();
+ for (int c = 0 ; c < count ; c++) {
+ View child = group.getChildAt(c);
+ postInflateProcess(child, projectCallback);
+ }
+ }
+ }
+
+ /**
+ * Sets up a {@link TabHost} object.
+ * @param tabHost the TabHost to setup.
+ * @param projectCallback The project callback object to access the project R class.
+ * @throws PostInflateException
+ */
+ private void setupTabHost(TabHost tabHost, IProjectCallback projectCallback)
+ throws PostInflateException {
+ // look for the TabWidget, and the FrameLayout. They have their own specific names
+ View v = tabHost.findViewById(android.R.id.tabs);
+
+ if (v == null) {
+ throw new PostInflateException(
+ "TabHost requires a TabWidget with id \"android:id/tabs\".\n");
+ }
+
+ if ((v instanceof TabWidget) == false) {
+ throw new PostInflateException(String.format(
+ "TabHost requires a TabWidget with id \"android:id/tabs\".\n" +
+ "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName()));
+ }
+
+ v = tabHost.findViewById(android.R.id.tabcontent);
+
+ if (v == null) {
+ // TODO: see if we can fake tabs even without the FrameLayout (same below when the framelayout is empty)
+ throw new PostInflateException(
+ "TabHost requires a FrameLayout with id \"android:id/tabcontent\".");
+ }
+
+ if ((v instanceof FrameLayout) == false) {
+ throw new PostInflateException(String.format(
+ "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" +
+ "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName()));
+ }
+
+ FrameLayout content = (FrameLayout)v;
+
+ // now process the content of the framelayout and dynamically create tabs for it.
+ final int count = content.getChildCount();
+
+ if (count == 0) {
+ throw new PostInflateException(
+ "The FrameLayout for the TabHost has no content. Rendering failed.\n");
+ }
+
+ // this must be called before addTab() so that the TabHost searches its TabWidget
+ // and FrameLayout.
+ tabHost.setup();
+
+ // for each child of the framelayout, add a new TabSpec
+ for (int i = 0 ; i < count ; i++) {
+ View child = content.getChildAt(i);
+ String tabSpec = String.format("tab_spec%d", i+1);
+ int id = child.getId();
+ String[] resource = projectCallback.resolveResourceValue(id);
+ String name;
+ if (resource != null) {
+ name = resource[0]; // 0 is resource name, 1 is resource type.
+ } else {
+ name = String.format("Tab %d", i+1); // default name if id is unresolved.
+ }
+ tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id));
+ }
+ }
+
+
+ /**
+ * 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.
+ */
+ private ViewInfo visit(View view, BridgeContext context) {
+ if (view == null) {
+ return null;
+ }
+
+ ViewInfo result = new ViewInfo(view.getClass().getName(),
+ context.getViewKey(view),
+ view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
+
+ if (view instanceof ViewGroup) {
+ ViewGroup group = ((ViewGroup) view);
+ List<ViewInfo> children = new ArrayList<ViewInfo>();
+ for (int i = 0; i < group.getChildCount(); i++) {
+ children.add(visit(group.getChildAt(i), context));
+ }
+ result.setChildren(children);
+ }
+
+ return result;
+ }
+
+ public BufferedImage getImage() {
+ return mImage;
+ }
+
+ public ViewInfo getViewInfo() {
+ return mViewInfo;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index f13ecdc..3e506b8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -14,11 +14,15 @@
* limitations under the License.
*/
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.impl;
import com.android.layoutlib.api.IDensityBasedResourceValue;
import com.android.layoutlib.api.IDensityBasedResourceValue.Density;
import com.android.layoutlib.api.IResourceValue;
+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.android.NinePatchDrawable;
import com.android.ninepatch.NinePatch;
import org.kxml2.io.KXmlParser;
@@ -56,7 +60,7 @@ public final class ResourceHelper {
* @return the color as an int
* @throw NumberFormatException if the conversion failed.
*/
- static int getColor(String value) {
+ public static int getColor(String value) {
if (value != null) {
if (value.startsWith("#") == false) {
throw new NumberFormatException();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/ResourceValue.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/TempResourceValue.java
index 01a4871..4ab98ce 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/ResourceValue.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/TempResourceValue.java
@@ -14,24 +14,24 @@
* limitations under the License.
*/
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.impl;
+import com.android.layoutlib.api.ILayoutBridge;
import com.android.layoutlib.api.IResourceValue;
/**
- * Basic implementation of IResourceValue.
+ * Basic implementation of IResourceValue for when it is needed to dynamically make a new
+ * {@link IResourceValue} object.
+ *
+ * Most of the time, implementations of IResourceValue come through the {@link ILayoutBridge}
+ * API.
*/
-class ResourceValue implements IResourceValue {
+public class TempResourceValue implements IResourceValue {
private final String mType;
private final String mName;
private String mValue = null;
-
- ResourceValue(String name) {
- mType = null;
- mName = name;
- }
- public ResourceValue(String type, String name, String value) {
+ public TempResourceValue(String type, String name, String value) {
mType = type;
mName = name;
mValue = value;
@@ -44,16 +44,16 @@ class ResourceValue implements IResourceValue {
public final String getName() {
return mName;
}
-
+
public final String getValue() {
return mValue;
}
-
+
public final void setValue(String value) {
mValue = value;
}
-
- public void replaceWith(ResourceValue value) {
+
+ public void replaceWith(TempResourceValue value) {
mValue = value.mValue;
}
diff --git a/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java b/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java
index 6d013bb..1ec6262 100644
--- a/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java
+++ b/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java
@@ -16,7 +16,7 @@
package com.google.android.maps;
-import com.android.layoutlib.bridge.MockView;
+import com.android.layoutlib.bridge.android.MockView;
import android.content.Context;
import android.os.Bundle;
diff --git a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/BridgeXmlBlockParserTest.java b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java
index db1262f..3252fb4 100644
--- a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/BridgeXmlBlockParserTest.java
+++ b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java
@@ -14,7 +14,9 @@
* limitations under the License.
*/
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
+
+import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
import org.kxml2.io.KXmlParser;
import org.w3c.dom.Node;