Merge "LayoutLib: Adapt the HC layoutlib to GB. do not merge." into gingerbread

This commit is contained in:
Xavier Ducrohet
2011-02-24 14:44:58 -08:00
committed by Android (Google) Code Review
40 changed files with 308 additions and 1434 deletions

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</merge>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginLeft="3dip"
android:layout_marginRight="15dip"/>
</merge>

View File

@@ -1,59 +0,0 @@
/*
* 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 android.animation;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
/**
* Delegate implementing the native methods of android.animation.PropertyValuesHolder
*
* Through the layoutlib_create tool, the original native methods of PropertyValuesHolder have been
* replaced by calls to methods of the same name in this delegate class.
*
* Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager}
* around to map int to instance of the delegate.
*
* The main goal of this class' methods are to provide a native way to access setters and getters
* on some object. In this case we want to default to using Java reflection instead so the native
* methods do nothing.
*
*/
/*package*/ class PropertyValuesHolder_Delegate {
@LayoutlibDelegate
/*package*/ static int nGetIntMethod(Class<?> targetClass, String methodName) {
// return 0 to force PropertyValuesHolder to use Java reflection.
return 0;
}
@LayoutlibDelegate
/*package*/ static int nGetFloatMethod(Class<?> targetClass, String methodName) {
// return 0 to force PropertyValuesHolder to use Java reflection.
return 0;
}
@LayoutlibDelegate
/*package*/ static void nCallIntMethod(Object target, int methodID, int arg) {
// do nothing
}
@LayoutlibDelegate
/*package*/ static void nCallFloatMethod(Object target, int methodID, float arg) {
// do nothing
}
}

View File

@@ -1,104 +0,0 @@
/*
* 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 android.app;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.content.Context;
import android.os.Bundle;
/**
* Delegate used to provide new implementation of a select few methods of {@link Fragment}
*
* Through the layoutlib_create tool, the original methods of Fragment have been replaced
* by calls to methods of the same name in this delegate class.
*
* The methods being re-implemented are the ones responsible for instantiating Fragment objects.
* Because the classes of these objects are found in the project, these methods need access to
* {@link IProjectCallback} object. They are however static methods, so the callback is set
* before the inflation through {@link #setProjectCallback(IProjectCallback)}.
*/
public class Fragment_Delegate {
private static IProjectCallback sProjectCallback;
/**
* Sets the current {@link IProjectCallback} to be used to instantiate classes coming
* from the project being rendered.
*/
public static void setProjectCallback(IProjectCallback projectCallback) {
sProjectCallback = projectCallback;
}
/**
* Like {@link #instantiate(Context, String, Bundle)} but with a null
* argument Bundle.
*/
@LayoutlibDelegate
/*package*/ static Fragment instantiate(Context context, String fname) {
return instantiate(context, fname, null);
}
/**
* Create a new instance of a Fragment with the given class name. This is
* the same as calling its empty constructor.
*
* @param context The calling context being used to instantiate the fragment.
* This is currently just used to get its ClassLoader.
* @param fname The class name of the fragment to instantiate.
* @param args Bundle of arguments to supply to the fragment, which it
* can retrieve with {@link #getArguments()}. May be null.
* @return Returns a new fragment instance.
* @throws InstantiationException If there is a failure in instantiating
* the given fragment class. This is a runtime exception; it is not
* normally expected to happen.
*/
@LayoutlibDelegate
/*package*/ static Fragment instantiate(Context context, String fname, Bundle args) {
try {
if (sProjectCallback != null) {
Fragment f = (Fragment) sProjectCallback.loadView(fname,
new Class[0], new Object[0]);
if (args != null) {
args.setClassLoader(f.getClass().getClassLoader());
f.mArguments = args;
}
return f;
}
return null;
} catch (ClassNotFoundException e) {
throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname
+ ": make sure class name exists, is public, and has an"
+ " empty constructor that is public", e);
} catch (java.lang.InstantiationException e) {
throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname
+ ": make sure class name exists, is public, and has an"
+ " empty constructor that is public", e);
} catch (IllegalAccessException e) {
throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname
+ ": make sure class name exists, is public, and has an"
+ " empty constructor that is public", e);
} catch (Exception e) {
throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname
+ ": make sure class name exists, is public, and has an"
+ " empty constructor that is public", e);
}
}
}

View File

@@ -136,20 +136,17 @@ import java.io.InputStream;
@LayoutlibDelegate
/*package*/ static Bitmap nativeDecodeFileDescriptor(FileDescriptor fd,
Rect padding, Options opts) {
opts.inBitmap = null;
return null;
}
@LayoutlibDelegate
/*package*/ static Bitmap nativeDecodeAsset(int asset, Rect padding, Options opts) {
opts.inBitmap = null;
return null;
}
@LayoutlibDelegate
/*package*/ static Bitmap nativeDecodeByteArray(byte[] data, int offset,
int length, Options opts) {
opts.inBitmap = null;
return null;
}
@@ -159,9 +156,4 @@ import java.io.InputStream;
// BitmapFactory.finishDecode();
return chunk;
}
@LayoutlibDelegate
/*package*/ static boolean nativeIsSeekable(FileDescriptor fd) {
return true;
}
}

View File

@@ -79,13 +79,6 @@ public class BitmapShader_Delegate extends Shader_Delegate {
return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
/*package*/ static int nativePostCreate(int native_shader, int native_bitmap,
int shaderTileModeX, int shaderTileModeY) {
// pass, not needed.
return 0;
}
// ---- Private delegate/helper methods ----
private BitmapShader_Delegate(java.awt.image.BufferedImage image,

View File

@@ -62,8 +62,6 @@ public final class Bitmap_Delegate {
private final Config mConfig;
private BufferedImage mImage;
private boolean mHasAlpha = true;
private int mGenerationId = 0;
// ---- Public Helper methods ----
@@ -186,15 +184,6 @@ public final class Bitmap_Delegate {
return mHasAlpha && mConfig != Config.RGB_565;
}
/**
* Update the generationId.
*
* @see Bitmap#getGenerationId()
*/
public void change() {
mGenerationId++;
}
// ---- native methods ----
@LayoutlibDelegate
@@ -394,16 +383,6 @@ public final class Bitmap_Delegate {
"Bitmap.copyPixelsFromBuffer is not supported.", null, null /*data*/);
}
@LayoutlibDelegate
/*package*/ static int nativeGenerationId(int nativeBitmap) {
Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
if (delegate == null) {
return 0;
}
return delegate.mGenerationId;
}
@LayoutlibDelegate
/*package*/ static Bitmap nativeCreateFromParcel(Parcel p) {
// This is only called by Bitmap.CREATOR (Parcelable.Creator<Bitmap>), which is only
@@ -525,7 +504,7 @@ public final class Bitmap_Delegate {
int nativeInt = sManager.addNewDelegate(delegate);
// and create/return a new Bitmap with it
return new Bitmap(nativeInt, null /* buffer */, isMutable, null /*ninePatchChunk*/, density);
return new Bitmap(nativeInt, isMutable, null /*ninePatchChunk*/, density);
}
/**

View File

@@ -269,6 +269,13 @@ public final class Canvas_Delegate {
canvasDelegate.restoreTo(saveCount);
}
@LayoutlibDelegate
/*package*/ static void drawText(Canvas thisCanvas,
String text, float x, float y, Paint paint) {
native_drawText(thisCanvas.mNativeCanvas, text, 0, text.length(), x, y,
paint.mNativePaint);
}
@LayoutlibDelegate
/*package*/ static void drawPoints(Canvas thisCanvas, float[] pts, int offset, int count,
Paint paint) {
@@ -322,6 +329,12 @@ public final class Canvas_Delegate {
}
}
@LayoutlibDelegate
/*package*/ static int initGL() {
// not supported.
return 0;
}
@LayoutlibDelegate
/*package*/ static void native_setBitmap(int nativeCanvas, int bitmap) {
// get the delegate from the native int.
@@ -339,6 +352,11 @@ public final class Canvas_Delegate {
canvasDelegate.setBitmap(bitmapDelegate);
}
@LayoutlibDelegate
/*package*/ static void nativeSetViewport(int nCanvas, int w, int h) {
// only useful in GL which is not supported, so no need to do anything.
}
@LayoutlibDelegate
/*package*/ static int native_saveLayer(int nativeCanvas, RectF bounds,
int paint, int layerFlags) {
@@ -944,7 +962,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
/*package*/ static void native_drawText(int nativeCanvas,
final char[] text, final int index, final int count,
final float startX, final float startY, int flags, int paint) {
final float startX, final float startY, int paint) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
new GcSnapshot.Drawable() {
public void draw(Graphics2D graphics, Paint_Delegate paint) {
@@ -1044,30 +1062,12 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
/*package*/ static void native_drawText(int nativeCanvas, String text,
int start, int end, float x,
float y, int flags, int paint) {
float y, int paint) {
int count = end - start;
char[] buffer = TemporaryBuffer.obtain(count);
TextUtils.getChars(text, start, end, buffer, 0);
native_drawText(nativeCanvas, buffer, 0, count, x, y, flags, paint);
}
@LayoutlibDelegate
/*package*/ static void native_drawTextRun(int nativeCanvas, String text,
int start, int end, int contextStart, int contextEnd,
float x, float y, int flags, int paint) {
int count = end - start;
char[] buffer = TemporaryBuffer.obtain(count);
TextUtils.getChars(text, start, end, buffer, 0);
native_drawText(nativeCanvas, buffer, start, end, x, y, flags, paint);
}
@LayoutlibDelegate
/*package*/ static void native_drawTextRun(int nativeCanvas, char[] text,
int start, int count, int contextStart, int contextCount,
float x, float y, int flags, int paint) {
native_drawText(nativeCanvas, text, start, count, x, y, flags, paint);
native_drawText(nativeCanvas, buffer, 0, count, x, y, paint);
}
@LayoutlibDelegate
@@ -1094,7 +1094,7 @@ public final class Canvas_Delegate {
char[] text, int index,
int count, int path,
float hOffset,
float vOffset, int bidiFlags,
float vOffset,
int paint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -1106,7 +1106,7 @@ public final class Canvas_Delegate {
String text, int path,
float hOffset,
float vOffset,
int flags, int paint) {
int paint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Canvas.drawTextOnPath is not supported.", null, null /*data*/);

View File

@@ -56,7 +56,7 @@ public abstract class ColorFilter_Delegate {
// ---- native methods ----
@LayoutlibDelegate
/*package*/ static void finalizer(int native_instance, int nativeColorFilter) {
/*package*/ static void finalizer(int native_instance) {
sManager.removeJavaReferenceFor(native_instance);
}

View File

@@ -60,11 +60,5 @@ public class ColorMatrixColorFilter_Delegate extends ColorFilter_Delegate {
return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
/*package*/ static int nColorMatrixFilter(int nativeFilter, float[] array) {
// pass
return 0;
}
// ---- Private delegate/helper methods ----
}

View File

@@ -78,20 +78,6 @@ public class ComposeShader_Delegate extends Shader_Delegate {
return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
/*package*/ static int nativePostCreate1(int native_shader, int native_skiaShaderA,
int native_skiaShaderB, int native_mode) {
// pass, not needed.
return 0;
}
@LayoutlibDelegate
/*package*/ static int nativePostCreate2(int native_shader, int native_skiaShaderA,
int native_skiaShaderB, int porterDuffMode) {
// pass, not needed.
return 0;
}
// ---- Private delegate/helper methods ----
}

View File

@@ -60,11 +60,5 @@ public class LightingColorFilter_Delegate extends ColorFilter_Delegate {
return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
/*package*/ static int nCreateLightingFilter(int nativeFilter, int mul, int add) {
// pass
return 0;
}
// ---- Private delegate/helper methods ----
}

View File

@@ -54,7 +54,7 @@ public final class LinearGradient_Delegate extends Gradient_Delegate {
// ---- native methods ----
@LayoutlibDelegate
/*package*/ static int nativeCreate1(LinearGradient thisGradient,
/*package*/ static int nativeCreate1(
float x0, float y0, float x1, float y1,
int colors[], float positions[], int tileMode) {
LinearGradient_Delegate newDelegate = new LinearGradient_Delegate(x0, y0, x1, y1,
@@ -63,30 +63,13 @@ public final class LinearGradient_Delegate extends Gradient_Delegate {
}
@LayoutlibDelegate
/*package*/ static int nativeCreate2(LinearGradient thisGradient,
/*package*/ static int nativeCreate2(
float x0, float y0, float x1, float y1,
int color0, int color1, int tileMode) {
return nativeCreate1(thisGradient,
x0, y0, x1, y1, new int[] { color0, color1}, null /*positions*/,
return nativeCreate1(x0, y0, x1, y1, new int[] { color0, color1}, null /*positions*/,
tileMode);
}
@LayoutlibDelegate
/*package*/ static int nativePostCreate1(LinearGradient thisGradient,
int native_shader, float x0, float y0, float x1, float y1,
int colors[], float positions[], int tileMode) {
// nothing to be done here.
return 0;
}
@LayoutlibDelegate
/*package*/ static int nativePostCreate2(LinearGradient thisGradient,
int native_shader, float x0, float y0, float x1, float y1,
int color0, int color1, int tileMode) {
// nothing to be done here.
return 0;
}
// ---- Private delegate/helper methods ----
/**

View File

@@ -23,7 +23,6 @@ import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.FontMetricsInt;
import android.text.TextUtils;
import java.awt.BasicStroke;
import java.awt.Font;
@@ -90,7 +89,6 @@ public class Paint_Delegate {
private MaskFilter_Delegate mMaskFilter;
private Rasterizer_Delegate mRasterizer;
// ---- Public Helper methods ----
public static Paint_Delegate getDelegate(int native_paint) {
@@ -393,7 +391,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void nSetShadowLayer(Paint thisPaint, float radius, float dx, float dy,
/*package*/ static void setShadowLayer(Paint thisPaint, float radius, float dx, float dy,
int color) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -940,82 +938,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static float native_getTextRunAdvances(int native_object,
char[] text, int index, int count, int contextIndex, int contextCount,
int flags, float[] advances, int advancesIndex) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
return 0.f;
}
if (delegate.mFonts.size() > 0) {
// FIXME: handle multi-char characters (see measureText)
float totalAdvance = 0;
for (int i = 0; i < count; i++) {
char c = text[i + index];
boolean found = false;
for (FontInfo info : delegate.mFonts) {
if (info.mFont.canDisplay(c)) {
float adv = info.mMetrics.charWidth(c);
totalAdvance += adv;
if (advances != null) {
advances[i] = adv;
}
found = true;
break;
}
}
if (found == false) {
// no advance for this char.
if (advances != null) {
advances[i] = 0.f;
}
}
}
return totalAdvance;
}
return 0;
}
@LayoutlibDelegate
/*package*/ static float native_getTextRunAdvances(int native_object,
String text, int start, int end, int contextStart, int contextEnd,
int flags, float[] advances, int advancesIndex) {
// FIXME: support contextStart, contextEnd and direction flag
int count = end - start;
char[] buffer = TemporaryBuffer.obtain(count);
TextUtils.getChars(text, start, end, buffer, 0);
return native_getTextRunAdvances(native_object, buffer, 0, count, contextStart,
contextEnd - contextStart, flags, advances, advancesIndex);
}
@LayoutlibDelegate
/*package*/ static int native_getTextRunCursor(Paint thisPaint, int native_object, char[] text,
int contextStart, int contextLength, int flags, int offset, int cursorOpt) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Paint.getTextRunCursor is not supported.", null, null /*data*/);
return 0;
}
@LayoutlibDelegate
/*package*/ static int native_getTextRunCursor(Paint thisPaint, int native_object, String text,
int contextStart, int contextEnd, int flags, int offset, int cursorOpt) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Paint.getTextRunCursor is not supported.", null, null /*data*/);
return 0;
}
@LayoutlibDelegate
/*package*/ static void native_getTextPath(int native_object, int bidiFlags,
/*package*/ static void native_getTextPath(int native_object,
char[] text, int index, int count, float x, float y, int path) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -1023,7 +946,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static void native_getTextPath(int native_object, int bidiFlags,
/*package*/ static void native_getTextPath(int native_object,
String text, int start, int end, float x, float y, int path) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,

View File

@@ -60,12 +60,5 @@ public class PorterDuffColorFilter_Delegate extends ColorFilter_Delegate {
return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
/*package*/ static int nCreatePorterDuffFilter(int nativeFilter, int srcColor,
int porterDuffMode) {
// pass
return 0;
}
// ---- Private delegate/helper methods ----
}

View File

@@ -68,20 +68,6 @@ public class RadialGradient_Delegate extends Gradient_Delegate {
tileMode);
}
@LayoutlibDelegate
/*package*/ static int nativePostCreate1(int native_shader, float x, float y, float radius,
int colors[], float positions[], int tileMode) {
// nothing to be done here.
return 0;
}
@LayoutlibDelegate
/*package*/ static int nativePostCreate2(int native_shader, float x, float y, float radius,
int color0, int color1, int tileMode) {
// nothing to be done here.
return 0;
}
// ---- Private delegate/helper methods ----
/**

View File

@@ -469,16 +469,6 @@ public class Region_Delegate {
return region1.mArea.equals(region2.mArea);
}
@LayoutlibDelegate
/*package*/ static String nativeToString(int native_region) {
Region_Delegate region = sManager.getDelegate(native_region);
if (region == null) {
return "not found";
}
return region.mArea.toString();
}
// ---- Private delegate/helper methods ----
}

View File

@@ -76,13 +76,38 @@ public abstract class Shader_Delegate {
// ---- native methods ----
@LayoutlibDelegate
/*package*/ static void nativeDestructor(int native_shader, int native_skiaShader) {
/*package*/ static void nativeDestructor(int native_shader) {
sManager.removeJavaReferenceFor(native_shader);
}
@LayoutlibDelegate
/*package*/ static void nativeSetLocalMatrix(int native_shader, int native_skiaShader,
int matrix_instance) {
/*package*/ static boolean nativeGetLocalMatrix(int native_shader, int matrix_instance) {
// get the delegate from the native int.
Shader_Delegate shaderDelegate = sManager.getDelegate(native_shader);
if (shaderDelegate == null) {
return false;
}
// get the (optional) out matrix.
Matrix_Delegate outMatrixDelegate = Matrix_Delegate.getDelegate(matrix_instance);
if (shaderDelegate.mLocalMatrix == null || shaderDelegate.mLocalMatrix.isIdentity()) {
if (outMatrixDelegate != null) {
outMatrixDelegate.reset();
}
return false;
}
if (outMatrixDelegate != null) {
outMatrixDelegate.set(shaderDelegate.mLocalMatrix);
}
return true;
}
@LayoutlibDelegate
/*package*/ static void nativeSetLocalMatrix(int native_shader, int matrix_instance) {
// get the delegate from the native int.
Shader_Delegate shaderDelegate = sManager.getDelegate(native_shader);
if (shaderDelegate == null) {

View File

@@ -62,20 +62,6 @@ public class SweepGradient_Delegate extends Gradient_Delegate {
return nativeCreate1(x, y, new int[] { color0, color1 }, null /*positions*/);
}
@LayoutlibDelegate
/*package*/ static int nativePostCreate1(int native_shader, float cx, float cy,
int[] colors, float[] positions) {
// nothing to be done here.
return 0;
}
@LayoutlibDelegate
/*package*/ static int nativePostCreate2(int native_shader, float cx, float cy,
int color0, int color1) {
// nothing to be done here.
return 0;
}
// ---- Private delegate/helper methods ----
/**

View File

@@ -22,7 +22,10 @@ import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.util.AttributeSet;
import android.util.Xml;
import java.io.IOException;
@@ -32,66 +35,131 @@ import java.io.IOException;
* Through the layoutlib_create tool, the original methods of LayoutInflater have been replaced
* by calls to methods of the same name in this delegate class.
*
* Generally we don't want to copy-paste a huge method like that just for one small features,
* but because this is done after this platform is final and the next version (Honeycomb) has a
* better mechanism (or slightly less copy-paste), maintenance of this duplicated code is not
* a problem.
*
*/
public class LayoutInflater_Delegate {
/**
* Recursive method used to descend down the xml hierarchy and instantiate
* views, instantiate their children, and then call onFinishInflate().
*/
@LayoutlibDelegate
/*package*/ static void rInflate(LayoutInflater thisInflater,
XmlPullParser parser, View parent, final AttributeSet attrs,
boolean finishInflate) throws XmlPullParserException, IOException {
/*package*/ static void parseInclude(LayoutInflater thisInflater,
XmlPullParser parser, View parent, AttributeSet attrs)
throws XmlPullParserException, IOException {
if (finishInflate == false) {
// this is a merge rInflate!
if (thisInflater instanceof BridgeInflater) {
((BridgeInflater) thisInflater).setIsInMerge(true);
}
}
// ---- START DEFAULT IMPLEMENTATION.
final int depth = parser.getDepth();
int type;
while (((type = parser.next()) != XmlPullParser.END_TAG ||
parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
if (type != XmlPullParser.START_TAG) {
continue;
}
final String name = parser.getName();
if (LayoutInflater.TAG_REQUEST_FOCUS.equals(name)) {
thisInflater.parseRequestFocus(parser, parent);
} else if (LayoutInflater.TAG_INCLUDE.equals(name)) {
if (parser.getDepth() == 0) {
throw new InflateException("<include /> cannot be the root element");
if (parent instanceof ViewGroup) {
final int layout = attrs.getAttributeResourceValue(null, "layout", 0);
if (layout == 0) {
final String value = attrs.getAttributeValue(null, "layout");
if (value == null) {
throw new InflateException("You must specifiy a layout in the"
+ " include tag: <include layout=\"@layout/layoutID\" />");
} else {
throw new InflateException("You must specifiy a valid layout "
+ "reference. The layout ID " + value + " is not valid.");
}
thisInflater.parseInclude(parser, parent, attrs);
} else if (LayoutInflater.TAG_MERGE.equals(name)) {
throw new InflateException("<merge /> must be the root element");
} else {
final View view = thisInflater.createViewFromTag(parent, name, attrs);
final ViewGroup viewGroup = (ViewGroup) parent;
final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
thisInflater.rInflate(parser, view, attrs, true);
viewGroup.addView(view, params);
final XmlResourceParser childParser =
thisInflater.getContext().getResources().getLayout(layout);
try {
final AttributeSet childAttrs = Xml.asAttributeSet(childParser);
while ((type = childParser.next()) != XmlPullParser.START_TAG &&
type != XmlPullParser.END_DOCUMENT) {
// Empty.
}
if (type != XmlPullParser.START_TAG) {
throw new InflateException(childParser.getPositionDescription() +
": No start tag found!");
}
final String childName = childParser.getName();
if (LayoutInflater.TAG_MERGE.equals(childName)) {
// ---- START MODIFICATIONS ----
if (thisInflater instanceof BridgeInflater) {
((BridgeInflater) thisInflater).setIsInMerge(true);
}
// ---- END MODIFICATIONS ----
// Inflate all children.
thisInflater.rInflate(childParser, parent, childAttrs);
// ---- START MODIFICATIONS ----
if (thisInflater instanceof BridgeInflater) {
((BridgeInflater) thisInflater).setIsInMerge(false);
}
// ---- END MODIFICATIONS ----
} else {
final View view = thisInflater.createViewFromTag(childName, childAttrs);
final ViewGroup group = (ViewGroup) parent;
// We try to load the layout params set in the <include /> tag. If
// they don't exist, we will rely on the layout params set in the
// included XML file.
// During a layoutparams generation, a runtime exception is thrown
// if either layout_width or layout_height is missing. We catch
// this exception and set localParams accordingly: true means we
// successfully loaded layout params from the <include /> tag,
// false means we need to rely on the included layout params.
ViewGroup.LayoutParams params = null;
try {
params = group.generateLayoutParams(attrs);
} catch (RuntimeException e) {
params = group.generateLayoutParams(childAttrs);
} finally {
if (params != null) {
view.setLayoutParams(params);
}
}
// Inflate all children.
thisInflater.rInflate(childParser, view, childAttrs);
// Attempt to override the included layout's android:id with the
// one set on the <include /> tag itself.
TypedArray a = thisInflater.mContext.obtainStyledAttributes(attrs,
com.android.internal.R.styleable.View, 0, 0);
int id = a.getResourceId(com.android.internal.R.styleable.View_id, View.NO_ID);
// While we're at it, let's try to override android:visibility.
int visibility = a.getInt(com.android.internal.R.styleable.View_visibility, -1);
a.recycle();
if (id != View.NO_ID) {
view.setId(id);
}
switch (visibility) {
case 0:
view.setVisibility(View.VISIBLE);
break;
case 1:
view.setVisibility(View.INVISIBLE);
break;
case 2:
view.setVisibility(View.GONE);
break;
}
group.addView(view);
}
} finally {
childParser.close();
}
}
} else {
throw new InflateException("<include /> can only be used inside of a ViewGroup");
}
if (finishInflate) parent.onFinishInflate();
// ---- END DEFAULT IMPLEMENTATION.
if (finishInflate == false) {
// this is a merge rInflate!
if (thisInflater instanceof BridgeInflater) {
((BridgeInflater) thisInflater).setIsInMerge(false);
}
final int currentDepth = parser.getDepth();
while (((type = parser.next()) != XmlPullParser.END_TAG ||
parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) {
// Empty
}
}
}

View File

@@ -194,9 +194,7 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
Capability.RENDER,
Capability.LAYOUT_ONLY,
Capability.EMBEDDED_LAYOUT,
Capability.VIEW_MANIPULATION,
Capability.PLAY_ANIMATION,
Capability.ANIMATED_VIEW_MANIPULATION);
Capability.VIEW_MANIPULATION);
BridgeAssetManager.initSystem();

View File

@@ -126,19 +126,8 @@ public class BridgeRenderSession extends RenderSession {
@Override
public Result animate(Object targetObject, String animationName,
boolean isFrameworkAnimation, IAnimationListener listener) {
try {
Bridge.prepareThread();
mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
if (mLastResult.isSuccess()) {
mLastResult = mSession.animate(targetObject, animationName, isFrameworkAnimation,
listener);
}
} finally {
mSession.release();
Bridge.cleanupThread();
}
return mLastResult;
// Animation is only supported in API 11+
return super.animate(targetObject, animationName, isFrameworkAnimation, listener);
}
@Override

View File

@@ -28,7 +28,6 @@ import com.android.resources.ResourceType;
import com.android.util.Pair;
import android.app.Activity;
import android.app.Fragment;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -45,7 +44,6 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.Resources.Theme;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.graphics.Bitmap;
@@ -127,9 +125,6 @@ public final class BridgeContext extends Activity {
mRenderResources = renderResources;
mFragments.mCurState = Fragment.CREATED;
mFragments.mActivity = this;
mApplicationInfo = new ApplicationInfo();
mApplicationInfo.targetSdkVersion = targetSdkVersion;
}
@@ -992,13 +987,6 @@ public final class BridgeContext extends Activity {
return null;
}
@Override
public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1,
CursorFactory arg2, DatabaseErrorHandler arg3) {
// TODO Auto-generated method stub
return null;
}
@Override
public Drawable peekWallpaper() {
// TODO Auto-generated method stub
@@ -1136,12 +1124,6 @@ public final class BridgeContext extends Activity {
throw new UnsupportedOperationException();
}
@Override
public void startActivities(Intent[] arg0) {
// TODO Auto-generated method stub
}
@Override
public boolean isRestricted() {
return false;

View File

@@ -122,10 +122,10 @@ public final class BridgeInflater extends LayoutInflater {
}
@Override
public View createViewFromTag(View parent, String name, AttributeSet attrs) {
public View createViewFromTag(String name, AttributeSet attrs) {
View view = null;
try {
view = super.createViewFromTag(parent, name, attrs);
view = super.createViewFromTag(name, attrs);
} catch (InflateException e) {
// try to load the class from using the custom view loader
try {

View File

@@ -22,7 +22,6 @@ 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;
@@ -82,10 +81,6 @@ public final class BridgeWindow implements IWindow {
// pass for now.
}
public void dispatchDragEvent(DragEvent event) {
// pass for now.
}
public void dispatchSystemUiVisibilityChanged(int visibility) {
// pass for now.
}

View File

@@ -16,7 +16,6 @@
package com.android.layoutlib.bridge.android;
import android.content.ClipData;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.Region;
@@ -26,7 +25,6 @@ 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;
@@ -54,10 +52,6 @@ public final class BridgeWindowSession implements IWindowSession {
// pass for now.
}
public void finishKey(IWindow arg0) throws RemoteException {
// pass for now.
}
public boolean getInTouchMode() throws RemoteException {
// pass for now.
return false;
@@ -68,16 +62,6 @@ public final class BridgeWindowSession implements IWindowSession {
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 {
@@ -101,38 +85,6 @@ public final class BridgeWindowSession implements IWindowSession {
// pass for now.
}
public void setInsets(IWindow window, int touchable, Rect contentInsets,
Rect visibleInsets, Region touchableRegion) {
// pass for now.
}
public IBinder prepareDrag(IWindow window, int flags,
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.
@@ -152,18 +104,13 @@ public final class BridgeWindowSession implements IWindowSession {
// pass for now.
}
public void closeSystemDialogs(String reason) {
// pass for now.
}
public IBinder asBinder() {
// pass for now.
return null;
}
public IBinder prepareDrag(IWindow arg0, boolean arg1, int arg2, int arg3, Surface arg4)
throws RemoteException {
public void setInsets(IWindow arg0, int arg1, Rect arg2, Rect arg3) throws RemoteException {
// TODO Auto-generated method stub
return null;
}
}

View File

@@ -1,47 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.layoutlib.bridge.bars;
import com.android.resources.Density;
import org.xmlpull.v1.XmlPullParserException;
import android.content.Context;
import android.widget.TextView;
public class FakeActionBar extends CustomBar {
private TextView mTextView;
public FakeActionBar(Context context, Density density, String label, String icon)
throws XmlPullParserException {
super(context, density, "/bars/action_bar.xml");
// Cannot access the inside items through id because no R.id values have been
// created for them.
// We do know the order though.
loadIcon(0, icon);
mTextView = setText(1, label);
setStyle("actionBarStyle");
}
@Override
protected TextView getStyleableTextView() {
return mTextView;
}
}

View File

@@ -38,7 +38,7 @@ public class PhoneSystemBar extends CustomBar {
// Cannot access the inside items through id because no R.id values have been
// created for them.
// We do know the order though.
// 0 is the spacer
// 0 is the spacer.
loadIcon(1, "stat_sys_wifi_signal_4_fully.png", density);
Drawable drawable = loadIcon(2, ResourceType.DRAWABLE, "stat_sys_battery_charge");
if (drawable instanceof LevelListDrawable) {

View File

@@ -1,54 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.layoutlib.bridge.bars;
import com.android.resources.Density;
import com.android.resources.ResourceType;
import org.xmlpull.v1.XmlPullParserException;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LevelListDrawable;
import android.widget.TextView;
public class TabletSystemBar extends CustomBar {
public TabletSystemBar(Context context, Density density) throws XmlPullParserException {
super(context, density, "/bars/tablet_system_bar.xml");
setBackgroundColor(0xFF000000);
// Cannot access the inside items through id because no R.id values have been
// created for them.
// We do know the order though.
loadIcon(0, "ic_sysbar_back_default.png", density);
loadIcon(1, "ic_sysbar_home_default.png", density);
loadIcon(2, "ic_sysbar_recent_default.png", density);
// 3 is the spacer
loadIcon(4, "stat_sys_wifi_signal_4_fully.png", density);
Drawable drawable = loadIcon(5, ResourceType.DRAWABLE, "stat_sys_battery_charge");
if (drawable instanceof LevelListDrawable) {
((LevelListDrawable) drawable).setLevel(100);
}
}
@Override
protected TextView getStyleableTextView() {
return null;
}
}

View File

@@ -1,170 +0,0 @@
/*
* 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.ide.common.rendering.api.IAnimationListener;
import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.Result;
import com.android.ide.common.rendering.api.Result.Status;
import com.android.layoutlib.bridge.Bridge;
import android.animation.ValueAnimator;
import android.os.Handler;
import android.os.Handler_Delegate;
import android.os.Message;
import android.os.Handler_Delegate.IHandlerCallback;
import java.util.PriorityQueue;
import java.util.Queue;
/**
* Abstract animation thread.
* <p/>
* This does not actually start an animation, instead it fakes a looper that will play whatever
* animation is sending messages to its own {@link Handler}.
* <p/>
* Classes should implement {@link #preAnimation()} and {@link #postAnimation()}.
* <p/>
* If {@link #preAnimation()} does not start an animation somehow then the thread doesn't do
* anything.
*
*/
public abstract class AnimationThread extends Thread {
private static class MessageBundle implements Comparable<MessageBundle> {
final Handler mTarget;
final Message mMessage;
final long mUptimeMillis;
MessageBundle(Handler target, Message message, long uptimeMillis) {
mTarget = target;
mMessage = message;
mUptimeMillis = uptimeMillis;
}
public int compareTo(MessageBundle bundle) {
if (mUptimeMillis < bundle.mUptimeMillis) {
return -1;
}
return 1;
}
}
private final RenderSessionImpl mSession;
private Queue<MessageBundle> mQueue = new PriorityQueue<MessageBundle>();
private final IAnimationListener mListener;
public AnimationThread(RenderSessionImpl scene, String threadName,
IAnimationListener listener) {
super(threadName);
mSession = scene;
mListener = listener;
}
public abstract Result preAnimation();
public abstract void postAnimation();
@Override
public void run() {
Bridge.prepareThread();
try {
Handler_Delegate.setCallback(new IHandlerCallback() {
public void sendMessageAtTime(Handler handler, Message msg, long uptimeMillis) {
if (msg.what == ValueAnimator.ANIMATION_START ||
msg.what == ValueAnimator.ANIMATION_FRAME) {
mQueue.add(new MessageBundle(handler, msg, uptimeMillis));
} else {
// just ignore.
}
}
});
// call out to the pre-animation work, which should start an animation or more.
Result result = preAnimation();
if (result.isSuccess() == false) {
mListener.done(result);
}
// loop the animation
RenderSession session = mSession.getSession();
do {
// check early.
if (mListener.isCanceled()) {
break;
}
// get the next message.
MessageBundle bundle = mQueue.poll();
if (bundle == null) {
break;
}
// sleep enough for this bundle to be on time
long currentTime = System.currentTimeMillis();
if (currentTime < bundle.mUptimeMillis) {
try {
sleep(bundle.mUptimeMillis - currentTime);
} catch (InterruptedException e) {
// FIXME log/do something/sleep again?
e.printStackTrace();
}
}
// check after sleeping.
if (mListener.isCanceled()) {
break;
}
// ready to do the work, acquire the scene.
result = mSession.acquire(250);
if (result.isSuccess() == false) {
mListener.done(result);
return;
}
// process the bundle. If the animation is not finished, this will enqueue
// the next message, so mQueue will have another one.
try {
// check after acquiring in case it took a while.
if (mListener.isCanceled()) {
break;
}
bundle.mTarget.handleMessage(bundle.mMessage);
if (mSession.render(false /*freshRender*/).isSuccess()) {
mListener.onNewFrame(session);
}
} finally {
mSession.release();
}
} while (mListener.isCanceled() == false && mQueue.size() > 0);
mListener.done(Status.SUCCESS.createResult());
} catch (Throwable throwable) {
// can't use Bridge.getLog() as the exception might be thrown outside
// of an acquire/release block.
mListener.done(Status.ERROR_UNKNOWN.createResult("Error playing animation", throwable));
} finally {
postAnimation();
Handler_Delegate.setCallback(null);
Bridge.cleanupThread();
}
}
}

View File

@@ -166,12 +166,6 @@ public class GcSnapshot {
return mOriginalCopy;
}
void change() {
if (mBitmap != null) {
mBitmap.change();
}
}
/**
* Sets the clip for the graphics2D object associated with the layer.
* This should be used over the normal Graphics2D setClip method.
@@ -611,7 +605,6 @@ public class GcSnapshot {
try {
drawable.draw(configuredGraphics2D, paint);
layer.change();
} finally {
// dispose Graphics2D object
configuredGraphics2D.dispose();

View File

@@ -1,48 +0,0 @@
/*
* 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.ide.common.rendering.api.IAnimationListener;
import com.android.ide.common.rendering.api.Result;
import com.android.ide.common.rendering.api.Result.Status;
import android.animation.Animator;
public class PlayAnimationThread extends AnimationThread {
private final Animator mAnimator;
public PlayAnimationThread(Animator animator, RenderSessionImpl scene, String animName,
IAnimationListener listener) {
super(scene, animName, listener);
mAnimator = animator;
}
@Override
public Result preAnimation() {
// start the animation. This will send a message to the handler right away, so
// the queue is filled when this method returns.
mAnimator.start();
return Status.SUCCESS.createResult();
}
@Override
public void postAnimation() {
// nothing to be done.
}
}

View File

@@ -87,7 +87,6 @@ public class RenderDrawable extends RenderAction<DrawableParams> {
info.mHasWindowFocus = true;
info.mWindowVisibility = View.VISIBLE;
info.mInTouchMode = false; // this is so that we can display selections.
info.mHardwareAccelerated = false;
content.dispatchAttachedToWindow(info, 0);

View File

@@ -16,7 +16,6 @@
package com.android.layoutlib.bridge.impl;
import static com.android.ide.common.rendering.api.Result.Status.ERROR_ANIM_NOT_FOUND;
import static com.android.ide.common.rendering.api.Result.Status.ERROR_INFLATION;
import static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLATED;
import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN;
@@ -43,9 +42,7 @@ import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
import com.android.layoutlib.bridge.android.BridgeWindow;
import com.android.layoutlib.bridge.android.BridgeWindowSession;
import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
import com.android.layoutlib.bridge.bars.FakeActionBar;
import com.android.layoutlib.bridge.bars.PhoneSystemBar;
import com.android.layoutlib.bridge.bars.TabletSystemBar;
import com.android.layoutlib.bridge.bars.TitleBar;
import com.android.resources.ResourceType;
import com.android.resources.ScreenSize;
@@ -53,11 +50,6 @@ import com.android.util.Pair;
import org.xmlpull.v1.XmlPullParserException;
import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.LayoutTransition;
import android.animation.LayoutTransition.TransitionListener;
import android.app.Fragment_Delegate;
import android.graphics.Bitmap;
import android.graphics.Bitmap_Delegate;
import android.graphics.Canvas;
@@ -72,7 +64,6 @@ import android.view.View.MeasureSpec;
import android.view.ViewGroup.LayoutParams;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.QuickContactBadge;
import android.widget.TabHost;
import android.widget.TabWidget;
import android.widget.TabHost.TabSpec;
@@ -112,9 +103,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
private boolean mWindowIsFloating;
private int mStatusBarSize;
private int mSystemBarSize;
private int mTitleBarSize;
private int mActionBarSize;
// information being returned through the API
@@ -174,13 +163,11 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
findBackground(resources);
findStatusBar(resources, metrics);
findActionBar(resources, metrics);
findSystemBar(resources, metrics);
findTitleBar(resources, metrics);
// build the inflater and parser.
mInflater = new BridgeInflater(context, params.getProjectCallback());
context.setBridgeInflater(mInflater);
mInflater.setFactory2(context);
mBlockParser = new BridgeXmlBlockParser(
params.getLayoutDescription(), context, false /* platformResourceFlag */);
@@ -214,18 +201,16 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
* we're creating the following layout
*
+-------------------------------------------------+
| System bar (only in phone UI) |
| System bar |
+-------------------------------------------------+
| (Layout with background drawable) |
| +---------------------------------------------+ |
| | Title/Action bar (optional) | |
| | Title (optional) | |
| +---------------------------------------------+ |
| | Content, vertical extending | |
| | | |
| +---------------------------------------------+ |
+-------------------------------------------------+
| System bar (only in tablet UI) |
+-------------------------------------------------+
*/
@@ -257,20 +242,8 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
topLayout.addView(backgroundLayout);
// if the theme says no title/action bar, then the size will be 0
if (mActionBarSize > 0) {
try {
FakeActionBar actionBar = new FakeActionBar(context,
params.getDensity(),
params.getAppLabel(), params.getAppIcon());
actionBar.setLayoutParams(
new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, mActionBarSize));
backgroundLayout.addView(actionBar);
} catch (XmlPullParserException e) {
}
} else if (mTitleBarSize > 0) {
// if the theme says no title, then the size will be 0
if (mTitleBarSize > 0) {
try {
TitleBar titleBar = new TitleBar(context,
params.getDensity(), params.getAppLabel());
@@ -283,7 +256,6 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
}
}
// content frame
mContentRoot = new FrameLayout(context);
layoutParams = new LinearLayout.LayoutParams(
@@ -291,38 +263,17 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
layoutParams.weight = 1;
mContentRoot.setLayoutParams(layoutParams);
backgroundLayout.addView(mContentRoot);
if (mSystemBarSize > 0) {
// system bar
try {
TabletSystemBar systemBar = new TabletSystemBar(context,
params.getDensity());
systemBar.setLayoutParams(
new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, mSystemBarSize));
topLayout.addView(systemBar);
} catch (XmlPullParserException e) {
}
}
}
// Sets the project callback (custom view loader) to the fragment delegate so that
// it can instantiate the custom Fragment.
Fragment_Delegate.setProjectCallback(params.getProjectCallback());
View view = mInflater.inflate(mBlockParser, mContentRoot);
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.
info.mHardwareAccelerated = false;
mViewRoot.dispatchAttachedToWindow(info, 0);
// post-inflate process. For now this supports TabHost/TabWidget
@@ -493,64 +444,6 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
}
}
/**
* Animate an object
* <p>
* {@link #acquire(long)} must have been called before this.
*
* @throws IllegalStateException if the current context is different than the one owned by
* the scene, or if {@link #acquire(long)} was not called.
*
* @see RenderSession#animate(Object, String, boolean, IAnimationListener)
*/
public Result animate(Object targetObject, String animationName,
boolean isFrameworkAnimation, IAnimationListener listener) {
checkLock();
BridgeContext context = getContext();
// find the animation file.
ResourceValue animationResource = null;
int animationId = 0;
if (isFrameworkAnimation) {
animationResource = context.getRenderResources().getFrameworkResource(
ResourceType.ANIMATOR, animationName);
if (animationResource != null) {
animationId = Bridge.getResourceId(ResourceType.ANIMATOR, animationName);
}
} else {
animationResource = context.getRenderResources().getProjectResource(
ResourceType.ANIMATOR, animationName);
if (animationResource != null) {
animationId = context.getProjectCallback().getResourceId(
ResourceType.ANIMATOR, animationName);
}
}
if (animationResource != null) {
try {
Animator anim = AnimatorInflater.loadAnimator(context, animationId);
if (anim != null) {
anim.setTarget(targetObject);
new PlayAnimationThread(anim, this, animationName, listener).start();
return SUCCESS.createResult();
}
} catch (Exception e) {
// get the real cause of the exception.
Throwable t = e;
while (t.getCause() != null) {
t = t.getCause();
}
return ERROR_UNKNOWN.createResult(t.getMessage(), t);
}
}
return ERROR_ANIM_NOT_FOUND.createResult();
}
/**
* Insert a new child into an existing parent.
* <p>
@@ -562,7 +455,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
* @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener)
*/
public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml,
final int index, IAnimationListener listener) {
final int index, final IAnimationListener listener) {
checkLock();
BridgeContext context = getContext();
@@ -580,17 +473,33 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
invalidateRenderingSize();
if (listener != null) {
new AnimationThread(this, "insertChild", listener) {
// there is no support for animating views in this API level, so we fake the animation
// through a no animation thread.
new Thread("not animated insertChild") {
@Override
public Result preAnimation() {
parentView.setLayoutTransition(new LayoutTransition());
return addView(parentView, child, index);
}
public void run() {
Result result = addView(parentView, child, index);
if (result.isSuccess() == false) {
listener.done(result);
}
@Override
public void postAnimation() {
parentView.setLayoutTransition(null);
// ready to do the work, acquire the scene.
result = acquire(250);
if (result.isSuccess() == false) {
listener.done(result);
return;
}
try {
result = render(false /*freshRender*/);
if (result.isSuccess()) {
listener.onNewFrame(RenderSessionImpl.this.getSession());
}
} finally {
release();
}
listener.done(result);
}
}.start();
@@ -662,72 +571,36 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
if (listener != null) {
final LayoutParams params = layoutParams;
// there is no support for animating views across layouts, so in case the new and old
// parent views are different we fake the animation through a no animation thread.
if (previousParent != newParentView) {
new Thread("not animated moveChild") {
@Override
public void run() {
Result result = moveView(previousParent, newParentView, childView, index,
params);
if (result.isSuccess() == false) {
listener.done(result);
}
// ready to do the work, acquire the scene.
result = acquire(250);
if (result.isSuccess() == false) {
listener.done(result);
return;
}
try {
result = render(false /*freshRender*/);
if (result.isSuccess()) {
listener.onNewFrame(RenderSessionImpl.this.getSession());
}
} finally {
release();
}
// there is no support for animating views in this API level, so we fake the animation
// through a no animation thread.
new Thread("not animated moveChild") {
@Override
public void run() {
Result result = moveView(previousParent, newParentView, childView, index,
params);
if (result.isSuccess() == false) {
listener.done(result);
}
}.start();
} else {
new AnimationThread(this, "moveChild", listener) {
@Override
public Result preAnimation() {
// set up the transition for the parent.
LayoutTransition transition = new LayoutTransition();
previousParent.setLayoutTransition(transition);
// tweak the animation durations and start delays (to match the duration of
// animation playing just before).
// Note: Cannot user Animation.setDuration() directly. Have to set it
// on the LayoutTransition.
transition.setDuration(LayoutTransition.DISAPPEARING, 100);
// CHANGE_DISAPPEARING plays after DISAPPEARING
transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100);
transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100);
transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100);
// CHANGE_APPEARING plays after CHANGE_APPEARING
transition.setStartDelay(LayoutTransition.APPEARING, 100);
transition.setDuration(LayoutTransition.APPEARING, 100);
return moveView(previousParent, newParentView, childView, index, params);
// ready to do the work, acquire the scene.
result = acquire(250);
if (result.isSuccess() == false) {
listener.done(result);
return;
}
@Override
public void postAnimation() {
previousParent.setLayoutTransition(null);
newParentView.setLayoutTransition(null);
try {
result = render(false /*freshRender*/);
if (result.isSuccess()) {
listener.onNewFrame(RenderSessionImpl.this.getSession());
}
} finally {
release();
}
}.start();
}
listener.done(result);
}
}.start();
// always return success since the real status will come through the listener.
return SUCCESS.createResult(layoutParams);
@@ -763,66 +636,17 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
private Result moveView(ViewGroup previousParent, final ViewGroup newParent,
final View movedView, final int index, final LayoutParams params) {
try {
// check if there is a transition on the previousParent.
LayoutTransition previousTransition = previousParent.getLayoutTransition();
if (previousTransition != null) {
// in this case there is an animation. This means we have to wait for the child's
// parent reference to be null'ed out so that we can add it to the new parent.
// It is technically removed right before the DISAPPEARING animation is done (if
// the animation of this type is not null, otherwise it's after which is impossible
// to handle).
// Because there is no move animation, if the new parent is the same as the old
// parent, we need to wait until the CHANGE_DISAPPEARING animation is done before
// adding the child or the child will appear in its new location before the
// other children have made room for it.
// standard code with no animation. pretty simple.
previousParent.removeView(movedView);
// add a listener to the transition to be notified of the actual removal.
previousTransition.addTransitionListener(new TransitionListener() {
private int mChangeDisappearingCount = 0;
public void startTransition(LayoutTransition transition, ViewGroup container,
View view, int transitionType) {
if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
mChangeDisappearingCount++;
}
}
public void endTransition(LayoutTransition transition, ViewGroup container,
View view, int transitionType) {
if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
mChangeDisappearingCount--;
}
if (transitionType == LayoutTransition.CHANGE_DISAPPEARING &&
mChangeDisappearingCount == 0) {
// add it to the parentView in the correct location
if (params != null) {
newParent.addView(movedView, index, params);
} else {
newParent.addView(movedView, index);
}
}
}
});
// remove the view from the current parent.
previousParent.removeView(movedView);
// and return since adding the view to the new parent is done in the listener.
return SUCCESS.createResult();
// add it to the parentView in the correct location
if (params != null) {
newParent.addView(movedView, index, params);
} else {
// standard code with no animation. pretty simple.
previousParent.removeView(movedView);
// add it to the parentView in the correct location
if (params != null) {
newParent.addView(movedView, index, params);
} else {
newParent.addView(movedView, index);
}
return SUCCESS.createResult();
newParent.addView(movedView, index);
}
return SUCCESS.createResult();
} catch (UnsupportedOperationException e) {
// looks like this is a view class that doesn't support children manipulation!
return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
@@ -839,7 +663,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
*
* @see RenderSession#removeChild(Object, IAnimationListener)
*/
public Result removeChild(final View childView, IAnimationListener listener) {
public Result removeChild(final View childView, final IAnimationListener listener) {
checkLock();
invalidateRenderingSize();
@@ -847,17 +671,33 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
final ViewGroup parent = (ViewGroup) childView.getParent();
if (listener != null) {
new AnimationThread(this, "moveChild", listener) {
// there is no support for animating views in this API level, so we fake the animation
// through a no animation thread.
new Thread("not animated moveChild") {
@Override
public Result preAnimation() {
parent.setLayoutTransition(new LayoutTransition());
return removeView(parent, childView);
}
public void run() {
Result result = removeView(parent, childView);
if (result.isSuccess() == false) {
listener.done(result);
}
@Override
public void postAnimation() {
parent.setLayoutTransition(null);
// ready to do the work, acquire the scene.
result = acquire(250);
if (result.isSuccess() == false) {
listener.done(result);
return;
}
try {
result = render(false /*freshRender*/);
if (result.isSuccess()) {
listener.onNewFrame(RenderSessionImpl.this.getSession());
}
} finally {
release();
}
listener.done(result);
}
}.start();
@@ -902,96 +742,13 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
}
}
private boolean isTabletUi() {
return getParams().getConfigScreenSize() == ScreenSize.XLARGE;
}
private void findStatusBar(RenderResources resources, DisplayMetrics metrics) {
if (isTabletUi() == false) {
boolean windowFullscreen = getBooleanThemeValue(resources,
"windowFullscreen", false /*defaultValue*/);
if (windowFullscreen == false && mWindowIsFloating == false) {
// default value
mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT;
// get the real value
ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
"status_bar_height");
if (value != null) {
TypedValue typedValue = ResourceHelper.getValue(value.getValue());
if (typedValue != null) {
// compute the pixel value based on the display metrics
mStatusBarSize = (int)typedValue.getDimension(metrics);
}
}
}
}
}
private void findActionBar(RenderResources resources, DisplayMetrics metrics) {
if (mWindowIsFloating) {
return;
}
boolean windowActionBar = getBooleanThemeValue(resources,
"windowActionBar", true /*defaultValue*/);
// if there's a value and it's false (default is true)
if (windowActionBar) {
// default size of the window title bar
mActionBarSize = DEFAULT_TITLE_BAR_HEIGHT;
// get value from the theme.
ResourceValue value = resources.findItemInTheme("actionBarSize");
// resolve it
value = resources.resolveResValue(value);
if (value != null) {
// get the numerical value, if available
TypedValue typedValue = ResourceHelper.getValue(value.getValue());
if (typedValue != null) {
// compute the pixel value based on the display metrics
mActionBarSize = (int)typedValue.getDimension(metrics);
}
}
} else {
// action bar overrides title bar so only look for this one if action bar is hidden
boolean windowNoTitle = getBooleanThemeValue(resources,
"windowNoTitle", false /*defaultValue*/);
if (windowNoTitle == false) {
// default size of the window title bar
mTitleBarSize = DEFAULT_TITLE_BAR_HEIGHT;
// get value from the theme.
ResourceValue value = resources.findItemInTheme("windowTitleSize");
// resolve it
value = resources.resolveResValue(value);
if (value != null) {
// get the numerical value, if available
TypedValue typedValue = ResourceHelper.getValue(value.getValue());
if (typedValue != null) {
// compute the pixel value based on the display metrics
mTitleBarSize = (int)typedValue.getDimension(metrics);
}
}
}
}
}
private void findSystemBar(RenderResources resources, DisplayMetrics metrics) {
if (isTabletUi() && mWindowIsFloating == false) {
boolean windowFullscreen = getBooleanThemeValue(resources,
"windowFullscreen", false /*defaultValue*/);
if (windowFullscreen == false && mWindowIsFloating == false) {
// default value
mSystemBarSize = 48; // ??
mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT;
// get the real value
ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
@@ -1001,7 +758,37 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
TypedValue typedValue = ResourceHelper.getValue(value.getValue());
if (typedValue != null) {
// compute the pixel value based on the display metrics
mSystemBarSize = (int)typedValue.getDimension(metrics);
mStatusBarSize = (int)typedValue.getDimension(metrics);
}
}
}
}
private void findTitleBar(RenderResources resources, DisplayMetrics metrics) {
if (mWindowIsFloating) {
return;
}
boolean windowNoTitle = getBooleanThemeValue(resources,
"windowNoTitle", false /*defaultValue*/);
if (windowNoTitle == false) {
// default size of the window title bar
mTitleBarSize = DEFAULT_TITLE_BAR_HEIGHT;
// get value from the theme.
ResourceValue value = resources.findItemInTheme("windowTitleSize");
// resolve it
value = resources.resolveResValue(value);
if (value != null) {
// get the numerical value, if available
TypedValue typedValue = ResourceHelper.getValue(value.getValue());
if (typedValue != null) {
// compute the pixel value based on the display metrics
mTitleBarSize = (int)typedValue.getDimension(metrics);
}
}
}
@@ -1036,9 +823,6 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
throws PostInflateException {
if (view instanceof TabHost) {
setupTabHost((TabHost)view, projectCallback);
} else if (view instanceof QuickContactBadge) {
QuickContactBadge badge = (QuickContactBadge) view;
badge.setImageToDefault();
} else if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup)view;
final int count = group.getChildCount();

View File

@@ -1,186 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package libcore.icu;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import java.util.Locale;
/**
* Delegate implementing the native methods of libcore.icu.ICU
*
* Through the layoutlib_create tool, the original native methods of ICU have been replaced
* by calls to methods of the same name in this delegate class.
*
*/
public class ICU_Delegate {
// --- Java delegates
@LayoutlibDelegate
/*package*/ static String toLowerCase(String s, String localeName) {
return s.toLowerCase();
}
@LayoutlibDelegate
/*package*/ static String toUpperCase(String s, String localeName) {
return s.toUpperCase();
}
// --- Native methods accessing ICU's database.
@LayoutlibDelegate
/*package*/ static String[] getAvailableBreakIteratorLocalesNative() {
return new String[0];
}
@LayoutlibDelegate
/*package*/ static String[] getAvailableCalendarLocalesNative() {
return new String[0];
}
@LayoutlibDelegate
/*package*/ static String[] getAvailableCollatorLocalesNative() {
return new String[0];
}
@LayoutlibDelegate
/*package*/ static String[] getAvailableDateFormatLocalesNative() {
return new String[0];
}
@LayoutlibDelegate
/*package*/ static String[] getAvailableLocalesNative() {
return new String[0];
}
@LayoutlibDelegate
/*package*/ static String[] getAvailableNumberFormatLocalesNative() {
return new String[0];
}
@LayoutlibDelegate
/*package*/ static String getCurrencyCodeNative(String locale) {
return "";
}
@LayoutlibDelegate
/*package*/ static int getCurrencyFractionDigitsNative(String currencyCode) {
return 0;
}
@LayoutlibDelegate
/*package*/ static String getCurrencySymbolNative(String locale, String currencyCode) {
return "";
}
@LayoutlibDelegate
/*package*/ static String getDisplayCountryNative(String countryCode, String locale) {
return "";
}
@LayoutlibDelegate
/*package*/ static String getDisplayLanguageNative(String languageCode, String locale) {
return "";
}
@LayoutlibDelegate
/*package*/ static String getDisplayVariantNative(String variantCode, String locale) {
return "";
}
@LayoutlibDelegate
/*package*/ static String getISO3CountryNative(String locale) {
return "";
}
@LayoutlibDelegate
/*package*/ static String getISO3LanguageNative(String locale) {
return "";
}
@LayoutlibDelegate
/*package*/ static String[] getISOLanguagesNative() {
return Locale.getISOLanguages();
}
@LayoutlibDelegate
/*package*/ static String[] getISOCountriesNative() {
return Locale.getISOCountries();
}
@LayoutlibDelegate
/*package*/ static boolean initLocaleDataImpl(String locale, LocaleData result) {
// Used by Calendar.
result.firstDayOfWeek = Integer.valueOf(1);
result.minimalDaysInFirstWeek = Integer.valueOf(1);
// Used by DateFormatSymbols.
result.amPm = new String[] { "AM", "PM" };
result.eras = new String[] { "BC", "AD" };
result.longMonthNames = new String[] { "January", "February", "March", "April", "May",
"June", "July", "August", "September", "October", "November", "December" };
result.shortMonthNames = new String[] { "Jan", "Feb", "Mar", "Apr", "May",
"Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
result.longStandAloneMonthNames = result.longMonthNames;
result.shortStandAloneMonthNames = result.shortMonthNames;
result.longWeekdayNames = new String[] {
"Monday" ,"Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
result.shortWeekdayNames = new String[] {
"Mon" ,"Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
result.longStandAloneWeekdayNames = result.longWeekdayNames;
result.shortStandAloneWeekdayNames = result.shortWeekdayNames;
result.fullTimeFormat = "";
result.longTimeFormat = "";
result.mediumTimeFormat = "";
result.shortTimeFormat = "";
result.fullDateFormat = "";
result.longDateFormat = "";
result.mediumDateFormat = "";
result.shortDateFormat = "";
// Used by DecimalFormatSymbols.
result.zeroDigit = '0';
result.digit = '0';
result.decimalSeparator = '.';
result.groupingSeparator = ',';
result.patternSeparator = ' ';
result.percent = '%';
result.perMill = '\u2030';
result.monetarySeparator = ' ';
result.minusSign = '-';
result.exponentSeparator = "e";
result.infinity = "\u221E";
result.NaN = "NaN";
// Also used by Currency.
result.currencySymbol = "$";
result.internationalCurrencySymbol = "USD";
// Used by DecimalFormat and NumberFormat.
result.numberPattern = "%f";
result.integerPattern = "%d";
result.currencyPattern = "%s";
result.percentPattern = "%f";
return true;
}
}

View File

@@ -94,13 +94,12 @@ public final class CreateInfo implements ICreateInfo {
* The list of methods to rewrite as delegates.
*/
private final static String[] DELEGATE_METHODS = new String[] {
"android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;",
"android.content.res.Resources$Theme#obtainStyledAttributes",
"android.content.res.Resources$Theme#resolveAttribute",
"android.graphics.BitmapFactory#finishDecode",
"android.os.Handler#sendMessageAtTime",
"android.os.Build#getString",
"android.view.LayoutInflater#rInflate",
"android.view.LayoutInflater#parseInclude",
"android.view.View#isInEditMode",
"com.android.internal.util.XmlUtils#convertValueToInt",
// TODO: comment out once DelegateClass is working
@@ -110,7 +109,6 @@ public final class CreateInfo implements ICreateInfo {
* The list of classes on which to delegate all native methods.
*/
private final static String[] DELEGATE_CLASS_NATIVES = new String[] {
"android.animation.PropertyValuesHolder",
"android.graphics.AvoidXfermode",
"android.graphics.Bitmap",
"android.graphics.BitmapFactory",
@@ -150,7 +148,6 @@ public final class CreateInfo implements ICreateInfo {
"android.graphics.Xfermode",
"android.os.SystemClock",
"android.util.FloatMath",
"libcore.icu.ICU",
};
/**

View File

@@ -68,7 +68,6 @@ public class Main {
AsmAnalyzer aa = new AsmAnalyzer(log, osJarPath, agen,
new String[] { // derived from
"android.view.View",
"android.app.Fragment"
},
new String[] { // include classes
"android.*", // for android.R