Merge change 4544 into donut
* changes: Connect TabHost/TabWidget/FrameLayout in the layout editor.
This commit is contained in:
@@ -55,6 +55,8 @@ import android.view.View.AttachInfo;
|
|||||||
import android.view.View.MeasureSpec;
|
import android.view.View.MeasureSpec;
|
||||||
import android.view.WindowManager.LayoutParams;
|
import android.view.WindowManager.LayoutParams;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.TabHost;
|
||||||
|
import android.widget.TabWidget;
|
||||||
|
|
||||||
import java.lang.ref.SoftReference;
|
import java.lang.ref.SoftReference;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
@@ -69,10 +71,10 @@ import java.util.Map;
|
|||||||
* {@link #computeLayout(IXmlPullParser, Object, int, int, String, boolean, Map, Map, IProjectCallback, ILayoutLog)}.
|
* {@link #computeLayout(IXmlPullParser, Object, int, int, String, boolean, Map, Map, IProjectCallback, ILayoutLog)}.
|
||||||
*/
|
*/
|
||||||
public final class Bridge implements ILayoutBridge {
|
public final class Bridge implements ILayoutBridge {
|
||||||
|
|
||||||
private static final int DEFAULT_TITLE_BAR_HEIGHT = 25;
|
private static final int DEFAULT_TITLE_BAR_HEIGHT = 25;
|
||||||
private static final int DEFAULT_STATUS_BAR_HEIGHT = 25;
|
private static final int DEFAULT_STATUS_BAR_HEIGHT = 25;
|
||||||
|
|
||||||
public static class StaticMethodNotImplementedException extends RuntimeException {
|
public static class StaticMethodNotImplementedException extends RuntimeException {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@@ -82,19 +84,20 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps from id to resource name/type.
|
* Maps from id to resource name/type. This is for android.R only.
|
||||||
*/
|
*/
|
||||||
private final static Map<Integer, String[]> sRMap = new HashMap<Integer, String[]>();
|
private final static Map<Integer, String[]> sRMap = new HashMap<Integer, String[]>();
|
||||||
/**
|
/**
|
||||||
* Same as sRMap except for int[] instead of int resources.
|
* Same as sRMap except for int[] instead of int resources. This is for android.R only.
|
||||||
*/
|
*/
|
||||||
private final static Map<int[], String> sRArrayMap = new HashMap<int[], String>();
|
private final static Map<int[], String> sRArrayMap = new HashMap<int[], String>();
|
||||||
/**
|
/**
|
||||||
* Reverse map compared to sRMap, resource type -> (resource name -> id)
|
* Reverse map compared to sRMap, resource type -> (resource name -> id).
|
||||||
|
* This is for android.R only.
|
||||||
*/
|
*/
|
||||||
private final static Map<String, Map<String, Integer>> sRFullMap =
|
private final static Map<String, Map<String, Integer>> sRFullMap =
|
||||||
new HashMap<String, Map<String,Integer>>();
|
new HashMap<String, Map<String,Integer>>();
|
||||||
|
|
||||||
private final static Map<Object, Map<String, SoftReference<Bitmap>>> sProjectBitmapCache =
|
private final static Map<Object, Map<String, SoftReference<Bitmap>>> sProjectBitmapCache =
|
||||||
new HashMap<Object, Map<String, SoftReference<Bitmap>>>();
|
new HashMap<Object, Map<String, SoftReference<Bitmap>>>();
|
||||||
private final static Map<Object, Map<String, SoftReference<NinePatch>>> sProject9PatchCache =
|
private final static Map<Object, Map<String, SoftReference<NinePatch>>> sProject9PatchCache =
|
||||||
@@ -104,7 +107,7 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
new HashMap<String, SoftReference<Bitmap>>();
|
new HashMap<String, SoftReference<Bitmap>>();
|
||||||
private final static Map<String, SoftReference<NinePatch>> sFramework9PatchCache =
|
private final static Map<String, SoftReference<NinePatch>> sFramework9PatchCache =
|
||||||
new HashMap<String, SoftReference<NinePatch>>();
|
new HashMap<String, SoftReference<NinePatch>>();
|
||||||
|
|
||||||
private static Map<String, Map<String, Integer>> sEnumValueMap;
|
private static Map<String, Map<String, Integer>> sEnumValueMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -156,14 +159,14 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
|
|
||||||
return sinit(fontOsLocation, enumValueMap);
|
return sinit(fontOsLocation, enumValueMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static synchronized boolean sinit(String fontOsLocation,
|
private static synchronized boolean sinit(String fontOsLocation,
|
||||||
Map<String, Map<String, Integer>> enumValueMap) {
|
Map<String, Map<String, Integer>> enumValueMap) {
|
||||||
|
|
||||||
// When DEBUG_LAYOUT is set and is not 0 or false, setup a default listener
|
// When DEBUG_LAYOUT is set and is not 0 or false, setup a default listener
|
||||||
// on static (native) methods which prints the signature on the console and
|
// on static (native) methods which prints the signature on the console and
|
||||||
// throws an exception.
|
// throws an exception.
|
||||||
// This is useful when testing the rendering in ADT to identify static native
|
// This is useful when testing the rendering in ADT to identify static native
|
||||||
// methods that are ignored -- layoutlib_create makes them returns 0/false/null
|
// methods that are ignored -- layoutlib_create makes them returns 0/false/null
|
||||||
// which is generally OK yet might be a problem, so this is how you'd find out.
|
// which is generally OK yet might be a problem, so this is how you'd find out.
|
||||||
//
|
//
|
||||||
@@ -214,7 +217,7 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
sEnumValueMap = enumValueMap;
|
sEnumValueMap = enumValueMap;
|
||||||
|
|
||||||
// now parse com.android.internal.R (and only this one as android.R is a subset of
|
// now parse com.android.internal.R (and only this one as android.R is a subset of
|
||||||
@@ -226,13 +229,13 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
// int[] does not implement equals/hashCode, and if the parsing used a different class
|
// int[] does not implement equals/hashCode, and if the parsing used a different class
|
||||||
// loader for the R class, this would NOT work.
|
// loader for the R class, this would NOT work.
|
||||||
Class<?> r = com.android.internal.R.class;
|
Class<?> r = com.android.internal.R.class;
|
||||||
|
|
||||||
for (Class<?> inner : r.getDeclaredClasses()) {
|
for (Class<?> inner : r.getDeclaredClasses()) {
|
||||||
String resType = inner.getSimpleName();
|
String resType = inner.getSimpleName();
|
||||||
|
|
||||||
Map<String, Integer> fullMap = new HashMap<String, Integer>();
|
Map<String, Integer> fullMap = new HashMap<String, Integer>();
|
||||||
sRFullMap.put(resType, fullMap);
|
sRFullMap.put(resType, fullMap);
|
||||||
|
|
||||||
for (Field f : inner.getDeclaredFields()) {
|
for (Field f : inner.getDeclaredFields()) {
|
||||||
// only process static final fields. Since the final attribute may have
|
// only process static final fields. Since the final attribute may have
|
||||||
// been altered by layoutlib_create, we only check static
|
// been altered by layoutlib_create, we only check static
|
||||||
@@ -243,7 +246,7 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
// if the object is an int[] we put it in sRArrayMap
|
// if the object is an int[] we put it in sRArrayMap
|
||||||
sRArrayMap.put((int[]) f.get(null), f.getName());
|
sRArrayMap.put((int[]) f.get(null), f.getName());
|
||||||
} else if (type == int.class) {
|
} else if (type == int.class) {
|
||||||
Integer value = (Integer) f.get(null);
|
Integer value = (Integer) f.get(null);
|
||||||
sRMap.put(value, new String[] { f.getName(), resType });
|
sRMap.put(value, new String[] { f.getName(), resType });
|
||||||
fullMap.put(f.getName(), value);
|
fullMap.put(f.getName(), value);
|
||||||
} else {
|
} else {
|
||||||
@@ -281,7 +284,7 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
themeName = themeName.substring(1);
|
themeName = themeName.substring(1);
|
||||||
isProjectTheme = true;
|
isProjectTheme = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return computeLayout(layoutDescription, projectKey,
|
return computeLayout(layoutDescription, projectKey,
|
||||||
screenWidth, screenHeight, DisplayMetrics.DEFAULT_DENSITY,
|
screenWidth, screenHeight, DisplayMetrics.DEFAULT_DENSITY,
|
||||||
DisplayMetrics.DEFAULT_DENSITY, DisplayMetrics.DEFAULT_DENSITY,
|
DisplayMetrics.DEFAULT_DENSITY, DisplayMetrics.DEFAULT_DENSITY,
|
||||||
@@ -294,6 +297,7 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
* (non-Javadoc)
|
* (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)
|
* @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,
|
public ILayoutResult computeLayout(IXmlPullParser layoutDescription, Object projectKey,
|
||||||
int screenWidth, int screenHeight, String themeName, boolean isProjectTheme,
|
int screenWidth, int screenHeight, String themeName, boolean isProjectTheme,
|
||||||
Map<String, Map<String, IResourceValue>> projectResources,
|
Map<String, Map<String, IResourceValue>> projectResources,
|
||||||
@@ -319,7 +323,7 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
if (logger == null) {
|
if (logger == null) {
|
||||||
logger = sDefaultLogger;
|
logger = sDefaultLogger;
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (sDefaultLogger) {
|
synchronized (sDefaultLogger) {
|
||||||
sLogger = logger;
|
sLogger = logger;
|
||||||
}
|
}
|
||||||
@@ -327,12 +331,12 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
// find the current theme and compute the style inheritance map
|
// find the current theme and compute the style inheritance map
|
||||||
Map<IStyleResourceValue, IStyleResourceValue> styleParentMap =
|
Map<IStyleResourceValue, IStyleResourceValue> styleParentMap =
|
||||||
new HashMap<IStyleResourceValue, IStyleResourceValue>();
|
new HashMap<IStyleResourceValue, IStyleResourceValue>();
|
||||||
|
|
||||||
IStyleResourceValue currentTheme = computeStyleMaps(themeName, isProjectTheme,
|
IStyleResourceValue currentTheme = computeStyleMaps(themeName, isProjectTheme,
|
||||||
projectResources.get(BridgeConstants.RES_STYLE),
|
projectResources.get(BridgeConstants.RES_STYLE),
|
||||||
frameworkResources.get(BridgeConstants.RES_STYLE), styleParentMap);
|
frameworkResources.get(BridgeConstants.RES_STYLE), styleParentMap);
|
||||||
|
|
||||||
BridgeContext context = null;
|
BridgeContext context = null;
|
||||||
try {
|
try {
|
||||||
// setup the display Metrics.
|
// setup the display Metrics.
|
||||||
DisplayMetrics metrics = new DisplayMetrics();
|
DisplayMetrics metrics = new DisplayMetrics();
|
||||||
@@ -347,29 +351,32 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
frameworkResources, styleParentMap, customViewLoader, logger);
|
frameworkResources, styleParentMap, customViewLoader, logger);
|
||||||
BridgeInflater inflater = new BridgeInflater(context, customViewLoader);
|
BridgeInflater inflater = new BridgeInflater(context, customViewLoader);
|
||||||
context.setBridgeInflater(inflater);
|
context.setBridgeInflater(inflater);
|
||||||
|
|
||||||
IResourceValue windowBackground = null;
|
IResourceValue windowBackground = null;
|
||||||
int screenOffset = 0;
|
int screenOffset = 0;
|
||||||
if (currentTheme != null) {
|
if (currentTheme != null) {
|
||||||
windowBackground = context.findItemInStyle(currentTheme, "windowBackground");
|
windowBackground = context.findItemInStyle(currentTheme, "windowBackground");
|
||||||
windowBackground = context.resolveResValue(windowBackground);
|
windowBackground = context.resolveResValue(windowBackground);
|
||||||
|
|
||||||
screenOffset = getScreenOffset(currentTheme, context);
|
screenOffset = getScreenOffset(currentTheme, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we need to make sure the Looper has been initialized for this thread.
|
// we need to make sure the Looper has been initialized for this thread.
|
||||||
// this is required for View that creates Handler objects.
|
// this is required for View that creates Handler objects.
|
||||||
if (Looper.myLooper() == null) {
|
if (Looper.myLooper() == null) {
|
||||||
Looper.prepare();
|
Looper.prepare();
|
||||||
}
|
}
|
||||||
|
|
||||||
BridgeXmlBlockParser parser = new BridgeXmlBlockParser(layoutDescription,
|
BridgeXmlBlockParser parser = new BridgeXmlBlockParser(layoutDescription,
|
||||||
context, false /* platformResourceFlag */);
|
context, false /* platformResourceFlag */);
|
||||||
|
|
||||||
ViewGroup root = new FrameLayout(context);
|
ViewGroup root = new FrameLayout(context);
|
||||||
|
|
||||||
View view = inflater.inflate(parser, root);
|
View view = inflater.inflate(parser, root);
|
||||||
|
|
||||||
|
// post-inflate process. For now this supports TabHost/TabWidget
|
||||||
|
postInflateProcess(view, customViewLoader);
|
||||||
|
|
||||||
// set the AttachInfo on the root view.
|
// set the AttachInfo on the root view.
|
||||||
AttachInfo info = new AttachInfo(new WindowSession(), new Window(),
|
AttachInfo info = new AttachInfo(new WindowSession(), new Window(),
|
||||||
new Handler(), null);
|
new Handler(), null);
|
||||||
@@ -392,16 +399,19 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
// measure the views
|
// measure the views
|
||||||
view.measure(w_spec, h_spec);
|
view.measure(w_spec, h_spec);
|
||||||
view.layout(0, screenOffset, screenWidth, screenHeight);
|
view.layout(0, screenOffset, screenWidth, screenHeight);
|
||||||
|
|
||||||
// draw them
|
// draw them
|
||||||
BridgeCanvas canvas = new BridgeCanvas(screenWidth, screenHeight - screenOffset,
|
BridgeCanvas canvas = new BridgeCanvas(screenWidth, screenHeight - screenOffset,
|
||||||
logger);
|
logger);
|
||||||
|
|
||||||
root.draw(canvas);
|
root.draw(canvas);
|
||||||
canvas.dispose();
|
canvas.dispose();
|
||||||
|
|
||||||
return new LayoutResult(visit(((ViewGroup)view).getChildAt(0), context),
|
return new LayoutResult(visit(((ViewGroup)view).getChildAt(0), context),
|
||||||
canvas.getImage());
|
canvas.getImage());
|
||||||
|
} catch (PostInflateException e) {
|
||||||
|
return new LayoutResult(ILayoutResult.ERROR, "Error during post inflation process:\n"
|
||||||
|
+ e.getMessage());
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
// get the real cause of the exception.
|
// get the real cause of the exception.
|
||||||
Throwable t = e;
|
Throwable t = e;
|
||||||
@@ -419,7 +429,7 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
// Make sure to remove static references, otherwise we could not unload the lib
|
// Make sure to remove static references, otherwise we could not unload the lib
|
||||||
BridgeResources.clearSystem();
|
BridgeResources.clearSystem();
|
||||||
BridgeAssetManager.clearSystem();
|
BridgeAssetManager.clearSystem();
|
||||||
|
|
||||||
// Remove the global logger
|
// Remove the global logger
|
||||||
synchronized (sDefaultLogger) {
|
synchronized (sDefaultLogger) {
|
||||||
sLogger = sDefaultLogger;
|
sLogger = sDefaultLogger;
|
||||||
@@ -437,18 +447,18 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
sProject9PatchCache.remove(projectKey);
|
sProject9PatchCache.remove(projectKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns details of a framework resource from its integer value.
|
* Returns details of a framework resource from its integer value.
|
||||||
* @param value the integer value
|
* @param value the integer value
|
||||||
* @return an array of 2 strings containing the resource name and type, or null if the id
|
* @return an array of 2 strings containing the resource name and type, or null if the id
|
||||||
* does not match any resource.
|
* does not match any resource.
|
||||||
*/
|
*/
|
||||||
public static String[] resolveResourceValue(int value) {
|
public static String[] resolveResourceValue(int value) {
|
||||||
return sRMap.get(value);
|
return sRMap.get(value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the name of a framework resource whose value is an int array.
|
* Returns the name of a framework resource whose value is an int array.
|
||||||
* @param array
|
* @param array
|
||||||
@@ -456,7 +466,7 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
public static String resolveResourceValue(int[] array) {
|
public static String resolveResourceValue(int[] array) {
|
||||||
return sRArrayMap.get(array);
|
return sRArrayMap.get(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the integer id of a framework resource, from a given resource type and resource name.
|
* Returns the integer id of a framework resource, from a given resource type and resource name.
|
||||||
* @param type the type of the resource
|
* @param type the type of the resource
|
||||||
@@ -468,15 +478,15 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
if (map != null) {
|
if (map != null) {
|
||||||
return map.get(name);
|
return map.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Map<String, Integer> getEnumValues(String attributeName) {
|
static Map<String, Integer> getEnumValues(String attributeName) {
|
||||||
if (sEnumValueMap != null) {
|
if (sEnumValueMap != null) {
|
||||||
return sEnumValueMap.get(attributeName);
|
return sEnumValueMap.get(attributeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -507,13 +517,13 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute style information from the given list of style for the project and framework.
|
* 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
|
* @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
|
* platform themes sharing the same name, all project themes must be prepended with
|
||||||
* a '*' character.
|
* a '*' character.
|
||||||
* @param isProjectTheme Is this a project theme
|
* @param isProjectTheme Is this a project theme
|
||||||
* @param inProjectStyleMap the project style map
|
* @param inProjectStyleMap the project style map
|
||||||
* @param inFrameworkStyleMap the framework style map
|
* @param inFrameworkStyleMap the framework style map
|
||||||
* @param outInheritanceMap the map of style inheritance. This is filled by the method
|
* @param outInheritanceMap the map of style inheritance. This is filled by the method
|
||||||
@@ -523,23 +533,23 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
String themeName, boolean isProjectTheme, Map<String,
|
String themeName, boolean isProjectTheme, Map<String,
|
||||||
IResourceValue> inProjectStyleMap, Map<String, IResourceValue> inFrameworkStyleMap,
|
IResourceValue> inProjectStyleMap, Map<String, IResourceValue> inFrameworkStyleMap,
|
||||||
Map<IStyleResourceValue, IStyleResourceValue> outInheritanceMap) {
|
Map<IStyleResourceValue, IStyleResourceValue> outInheritanceMap) {
|
||||||
|
|
||||||
if (inProjectStyleMap != null && inFrameworkStyleMap != null) {
|
if (inProjectStyleMap != null && inFrameworkStyleMap != null) {
|
||||||
// first, get the theme
|
// first, get the theme
|
||||||
IResourceValue theme = null;
|
IResourceValue theme = null;
|
||||||
|
|
||||||
// project theme names have been prepended with a *
|
// project theme names have been prepended with a *
|
||||||
if (isProjectTheme) {
|
if (isProjectTheme) {
|
||||||
theme = inProjectStyleMap.get(themeName);
|
theme = inProjectStyleMap.get(themeName);
|
||||||
} else {
|
} else {
|
||||||
theme = inFrameworkStyleMap.get(themeName);
|
theme = inFrameworkStyleMap.get(themeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theme instanceof IStyleResourceValue) {
|
if (theme instanceof IStyleResourceValue) {
|
||||||
// compute the inheritance map for both the project and framework styles
|
// compute the inheritance map for both the project and framework styles
|
||||||
computeStyleInheritance(inProjectStyleMap.values(), inProjectStyleMap,
|
computeStyleInheritance(inProjectStyleMap.values(), inProjectStyleMap,
|
||||||
inFrameworkStyleMap, outInheritanceMap);
|
inFrameworkStyleMap, outInheritanceMap);
|
||||||
|
|
||||||
// Compute the style inheritance for the framework styles/themes.
|
// Compute the style inheritance for the framework styles/themes.
|
||||||
// Since, for those, the style parent values do not contain 'android:'
|
// Since, for those, the style parent values do not contain 'android:'
|
||||||
// we want to force looking in the framework style only to avoid using
|
// we want to force looking in the framework style only to avoid using
|
||||||
@@ -547,11 +557,11 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
// To do this, we pass null in lieu of the project style map.
|
// To do this, we pass null in lieu of the project style map.
|
||||||
computeStyleInheritance(inFrameworkStyleMap.values(), null /*inProjectStyleMap */,
|
computeStyleInheritance(inFrameworkStyleMap.values(), null /*inProjectStyleMap */,
|
||||||
inFrameworkStyleMap, outInheritanceMap);
|
inFrameworkStyleMap, outInheritanceMap);
|
||||||
|
|
||||||
return (IStyleResourceValue)theme;
|
return (IStyleResourceValue)theme;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,7 +583,7 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
|
|
||||||
// first look for a specified parent.
|
// first look for a specified parent.
|
||||||
String parentName = style.getParentStyle();
|
String parentName = style.getParentStyle();
|
||||||
|
|
||||||
// no specified parent? try to infer it from the name of the style.
|
// no specified parent? try to infer it from the name of the style.
|
||||||
if (parentName == null) {
|
if (parentName == null) {
|
||||||
parentName = getParentName(value.getName());
|
parentName = getParentName(value.getName());
|
||||||
@@ -581,7 +591,7 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
|
|
||||||
if (parentName != null) {
|
if (parentName != null) {
|
||||||
parentStyle = getStyle(parentName, inProjectStyleMap, inFrameworkStyleMap);
|
parentStyle = getStyle(parentName, inProjectStyleMap, inFrameworkStyleMap);
|
||||||
|
|
||||||
if (parentStyle != null) {
|
if (parentStyle != null) {
|
||||||
outInheritanceMap.put(style, parentStyle);
|
outInheritanceMap.put(style, parentStyle);
|
||||||
}
|
}
|
||||||
@@ -589,7 +599,7 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches for and returns the {@link IStyleResourceValue} from a given name.
|
* Searches for and returns the {@link IStyleResourceValue} from a given name.
|
||||||
* <p/>The format of the name can be:
|
* <p/>The format of the name can be:
|
||||||
@@ -607,27 +617,27 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
Map<String, IResourceValue> inProjectStyleMap,
|
Map<String, IResourceValue> inProjectStyleMap,
|
||||||
Map<String, IResourceValue> inFrameworkStyleMap) {
|
Map<String, IResourceValue> inFrameworkStyleMap) {
|
||||||
boolean frameworkOnly = false;
|
boolean frameworkOnly = false;
|
||||||
|
|
||||||
String name = parentName;
|
String name = parentName;
|
||||||
|
|
||||||
// remove the useless @ if it's there
|
// remove the useless @ if it's there
|
||||||
if (name.startsWith(BridgeConstants.PREFIX_RESOURCE_REF)) {
|
if (name.startsWith(BridgeConstants.PREFIX_RESOURCE_REF)) {
|
||||||
name = name.substring(BridgeConstants.PREFIX_RESOURCE_REF.length());
|
name = name.substring(BridgeConstants.PREFIX_RESOURCE_REF.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for framework identifier.
|
// check for framework identifier.
|
||||||
if (name.startsWith(BridgeConstants.PREFIX_ANDROID)) {
|
if (name.startsWith(BridgeConstants.PREFIX_ANDROID)) {
|
||||||
frameworkOnly = true;
|
frameworkOnly = true;
|
||||||
name = name.substring(BridgeConstants.PREFIX_ANDROID.length());
|
name = name.substring(BridgeConstants.PREFIX_ANDROID.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
// at this point we could have the format style/<name>. we want only the name
|
// at this point we could have the format style/<name>. we want only the name
|
||||||
if (name.startsWith(BridgeConstants.REFERENCE_STYLE)) {
|
if (name.startsWith(BridgeConstants.REFERENCE_STYLE)) {
|
||||||
name = name.substring(BridgeConstants.REFERENCE_STYLE.length());
|
name = name.substring(BridgeConstants.REFERENCE_STYLE.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
IResourceValue parent = null;
|
IResourceValue parent = null;
|
||||||
|
|
||||||
// if allowed, search in the project resources.
|
// if allowed, search in the project resources.
|
||||||
if (frameworkOnly == false && inProjectStyleMap != null) {
|
if (frameworkOnly == false && inProjectStyleMap != null) {
|
||||||
parent = inProjectStyleMap.get(name);
|
parent = inProjectStyleMap.get(name);
|
||||||
@@ -637,17 +647,17 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
if (parent == null) {
|
if (parent == null) {
|
||||||
parent = inFrameworkStyleMap.get(name);
|
parent = inFrameworkStyleMap.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure the result is the proper class type and return it.
|
// make sure the result is the proper class type and return it.
|
||||||
if (parent instanceof IStyleResourceValue) {
|
if (parent instanceof IStyleResourceValue) {
|
||||||
return (IStyleResourceValue)parent;
|
return (IStyleResourceValue)parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
sLogger.error(String.format("Unable to resolve parent style name: ", parentName));
|
sLogger.error(String.format("Unable to resolve parent style name: ", parentName));
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the name of the parent style, or <code>null</code> if the style is a root style.
|
* Computes the name of the parent style, or <code>null</code> if the style is a root style.
|
||||||
*/
|
*/
|
||||||
@@ -656,10 +666,10 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
return styleName.substring(0, index);
|
return styleName.substring(0, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the top screen offset. This depends on whether the current theme defines the user
|
* Returns the top screen offset. This depends on whether the current theme defines the user
|
||||||
* of the title and status bars.
|
* of the title and status bars.
|
||||||
@@ -670,7 +680,7 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
|
|
||||||
// get the title bar flag from the current theme.
|
// get the title bar flag from the current theme.
|
||||||
IResourceValue value = context.findItemInStyle(currentTheme, "windowNoTitle");
|
IResourceValue value = context.findItemInStyle(currentTheme, "windowNoTitle");
|
||||||
|
|
||||||
// because it may reference something else, we resolve it.
|
// because it may reference something else, we resolve it.
|
||||||
value = context.resolveResValue(value);
|
value = context.resolveResValue(value);
|
||||||
|
|
||||||
@@ -679,10 +689,10 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) {
|
XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) {
|
||||||
// get value from the theme.
|
// get value from the theme.
|
||||||
value = context.findItemInStyle(currentTheme, "windowTitleSize");
|
value = context.findItemInStyle(currentTheme, "windowTitleSize");
|
||||||
|
|
||||||
// resolve it
|
// resolve it
|
||||||
value = context.resolveResValue(value);
|
value = context.resolveResValue(value);
|
||||||
|
|
||||||
// default value
|
// default value
|
||||||
offset = DEFAULT_TITLE_BAR_HEIGHT;
|
offset = DEFAULT_TITLE_BAR_HEIGHT;
|
||||||
|
|
||||||
@@ -690,17 +700,17 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
if (value != null) {
|
if (value != null) {
|
||||||
TypedValue typedValue = ResourceHelper.getValue(value.getValue());
|
TypedValue typedValue = ResourceHelper.getValue(value.getValue());
|
||||||
if (typedValue != null) {
|
if (typedValue != null) {
|
||||||
offset = (int)typedValue.getDimension(context.getResources().mMetrics);
|
offset = (int)typedValue.getDimension(context.getResources().mMetrics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the fullscreen flag from the current theme.
|
// get the fullscreen flag from the current theme.
|
||||||
value = context.findItemInStyle(currentTheme, "windowFullscreen");
|
value = context.findItemInStyle(currentTheme, "windowFullscreen");
|
||||||
|
|
||||||
// because it may reference something else, we resolve it.
|
// because it may reference something else, we resolve it.
|
||||||
value = context.resolveResValue(value);
|
value = context.resolveResValue(value);
|
||||||
|
|
||||||
if (value == null || value.getValue() == null ||
|
if (value == null || value.getValue() == null ||
|
||||||
XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) {
|
XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) {
|
||||||
// FIXME: Right now this is hard-coded in the platform, but once there's a constant, we'll need to use it.
|
// FIXME: Right now this is hard-coded in the platform, but once there's a constant, we'll need to use it.
|
||||||
@@ -710,6 +720,94 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
return offset;
|
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
|
* Returns the bitmap for a specific path, from a specific project cache, or from the
|
||||||
* framework cache.
|
* framework cache.
|
||||||
@@ -750,7 +848,7 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
map = new HashMap<String, SoftReference<Bitmap>>();
|
map = new HashMap<String, SoftReference<Bitmap>>();
|
||||||
sProjectBitmapCache.put(projectKey, map);
|
sProjectBitmapCache.put(projectKey, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
map.put(value, new SoftReference<Bitmap>(bmp));
|
map.put(value, new SoftReference<Bitmap>(bmp));
|
||||||
} else {
|
} else {
|
||||||
sFrameworkBitmapCache.put(value, new SoftReference<Bitmap>(bmp));
|
sFrameworkBitmapCache.put(value, new SoftReference<Bitmap>(bmp));
|
||||||
@@ -767,7 +865,7 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
static NinePatch getCached9Patch(String value, Object projectKey) {
|
static NinePatch getCached9Patch(String value, Object projectKey) {
|
||||||
if (projectKey != null) {
|
if (projectKey != null) {
|
||||||
Map<String, SoftReference<NinePatch>> map = sProject9PatchCache.get(projectKey);
|
Map<String, SoftReference<NinePatch>> map = sProject9PatchCache.get(projectKey);
|
||||||
|
|
||||||
if (map != null) {
|
if (map != null) {
|
||||||
SoftReference<NinePatch> ref = map.get(value);
|
SoftReference<NinePatch> ref = map.get(value);
|
||||||
if (ref != null) {
|
if (ref != null) {
|
||||||
@@ -780,7 +878,7 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
return ref.get();
|
return ref.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -798,13 +896,21 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
map = new HashMap<String, SoftReference<NinePatch>>();
|
map = new HashMap<String, SoftReference<NinePatch>>();
|
||||||
sProject9PatchCache.put(projectKey, map);
|
sProject9PatchCache.put(projectKey, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
map.put(value, new SoftReference<NinePatch>(ninePatch));
|
map.put(value, new SoftReference<NinePatch>(ninePatch));
|
||||||
} else {
|
} else {
|
||||||
sFramework9PatchCache.put(value, new SoftReference<NinePatch>(ninePatch));
|
sFramework9PatchCache.put(value, new SoftReference<NinePatch>(ninePatch));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class PostInflateException extends Exception {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public PostInflateException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link IWindowSession} so that mSession is not null in
|
* Implementation of {@link IWindowSession} so that mSession is not null in
|
||||||
* the {@link SurfaceView}.
|
* the {@link SurfaceView}.
|
||||||
@@ -839,7 +945,7 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
// pass for now.
|
// pass for now.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public MotionEvent getPendingPointerMove(IWindow arg0) throws RemoteException {
|
public MotionEvent getPendingPointerMove(IWindow arg0) throws RemoteException {
|
||||||
// pass for now.
|
// pass for now.
|
||||||
@@ -863,7 +969,7 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
|
public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
|
||||||
// pass for now.
|
// pass for now.
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public void remove(IWindow arg0) throws RemoteException {
|
public void remove(IWindow arg0) throws RemoteException {
|
||||||
// pass for now.
|
// pass for now.
|
||||||
@@ -883,13 +989,13 @@ public final class Bridge implements ILayoutBridge {
|
|||||||
Rect visibleInsets) {
|
Rect visibleInsets) {
|
||||||
// pass for now.
|
// pass for now.
|
||||||
}
|
}
|
||||||
|
|
||||||
public IBinder asBinder() {
|
public IBinder asBinder() {
|
||||||
// pass for now.
|
// pass for now.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link IWindow} to pass to the {@link AttachInfo}.
|
* Implementation of {@link IWindow} to pass to the {@link AttachInfo}.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user