diff options
Diffstat (limited to 'tools/layoutlib/bridge/src/android')
16 files changed, 899 insertions, 74 deletions
diff --git a/tools/layoutlib/bridge/src/android/animation/AnimationThread.java b/tools/layoutlib/bridge/src/android/animation/AnimationThread.java new file mode 100644 index 0000000..2b5e4fa --- /dev/null +++ b/tools/layoutlib/bridge/src/android/animation/AnimationThread.java @@ -0,0 +1,171 @@ +/* + * 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.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 com.android.layoutlib.bridge.impl.RenderSessionImpl; + +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(); + } + } +} diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java b/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java new file mode 100644 index 0000000..a953918 --- /dev/null +++ b/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.content.res; + +import com.android.layoutlib.bridge.Bridge; + +import android.content.res.AssetManager; + +public class BridgeAssetManager extends AssetManager { + + /** + * This initializes the static field {@link AssetManager#mSystem} which is used + * by methods who get a global asset manager using {@link AssetManager#getSystem()}. + * <p/> + * They will end up using our bridge asset manager. + * <p/> + * {@link Bridge} calls this method after setting up a new bridge. + */ + public static AssetManager initSystem() { + if (!(AssetManager.sSystem instanceof BridgeAssetManager)) { + // Note that AssetManager() creates a system AssetManager and we override it + // with our BridgeAssetManager. + AssetManager.sSystem = new BridgeAssetManager(); + AssetManager.sSystem.makeStringBlocks(false); + } + return AssetManager.sSystem; + } + + /** + * Clears the static {@link AssetManager#sSystem} to make sure we don't leave objects + * around that would prevent us from unloading the library. + */ + public static void clearSystem() { + AssetManager.sSystem = null; + } + + private BridgeAssetManager() { + } +} diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java index 0928ec5..7b672da 100644 --- a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java +++ b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java @@ -214,7 +214,15 @@ public final class BridgeResources extends Resources { Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); if (value != null) { - return value.getSecond().getValue(); + ResourceValue resValue = value.getSecond(); + + assert resValue != null; + if (resValue != null) { + String v = resValue.getValue(); + if (v != null) { + return v; + } + } } // id was not found or not resolved. Throw a NotFoundException. @@ -318,20 +326,24 @@ public final class BridgeResources extends Resources { Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); if (value != null) { - String v = value.getSecond().getValue(); - - if (v != null) { - if (v.equals(BridgeConstants.MATCH_PARENT) || - v.equals(BridgeConstants.FILL_PARENT)) { - return LayoutParams.MATCH_PARENT; - } else if (v.equals(BridgeConstants.WRAP_CONTENT)) { - return LayoutParams.WRAP_CONTENT; - } + ResourceValue resValue = value.getSecond(); + + assert resValue != null; + if (resValue != null) { + String v = resValue.getValue(); + if (v != null) { + if (v.equals(BridgeConstants.MATCH_PARENT) || + v.equals(BridgeConstants.FILL_PARENT)) { + return LayoutParams.MATCH_PARENT; + } else if (v.equals(BridgeConstants.WRAP_CONTENT)) { + return LayoutParams.WRAP_CONTENT; + } - if (ResourceHelper.parseFloatAttribute( - value.getFirst(), v, mTmpValue, true /*requireUnit*/) && - mTmpValue.type == TypedValue.TYPE_DIMENSION) { - return mTmpValue.getDimension(getDisplayMetrics()); + if (ResourceHelper.parseFloatAttribute( + value.getFirst(), v, mTmpValue, true /*requireUnit*/) && + mTmpValue.type == TypedValue.TYPE_DIMENSION) { + return mTmpValue.getDimension(getDisplayMetrics()); + } } } } @@ -348,14 +360,18 @@ public final class BridgeResources extends Resources { Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); if (value != null) { - String v = value.getSecond().getValue(); - - if (v != null) { - if (ResourceHelper.parseFloatAttribute( - value.getFirst(), v, mTmpValue, true /*requireUnit*/) && - mTmpValue.type == TypedValue.TYPE_DIMENSION) { - return TypedValue.complexToDimensionPixelOffset(mTmpValue.data, - getDisplayMetrics()); + ResourceValue resValue = value.getSecond(); + + assert resValue != null; + if (resValue != null) { + String v = resValue.getValue(); + if (v != null) { + if (ResourceHelper.parseFloatAttribute( + value.getFirst(), v, mTmpValue, true /*requireUnit*/) && + mTmpValue.type == TypedValue.TYPE_DIMENSION) { + return TypedValue.complexToDimensionPixelOffset(mTmpValue.data, + getDisplayMetrics()); + } } } } @@ -372,14 +388,18 @@ public final class BridgeResources extends Resources { Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); if (value != null) { - String v = value.getSecond().getValue(); - - if (v != null) { - if (ResourceHelper.parseFloatAttribute( - value.getFirst(), v, mTmpValue, true /*requireUnit*/) && - mTmpValue.type == TypedValue.TYPE_DIMENSION) { - return TypedValue.complexToDimensionPixelSize(mTmpValue.data, - getDisplayMetrics()); + ResourceValue resValue = value.getSecond(); + + assert resValue != null; + if (resValue != null) { + String v = resValue.getValue(); + if (v != null) { + if (ResourceHelper.parseFloatAttribute( + value.getFirst(), v, mTmpValue, true /*requireUnit*/) && + mTmpValue.type == TypedValue.TYPE_DIMENSION) { + return TypedValue.complexToDimensionPixelSize(mTmpValue.data, + getDisplayMetrics()); + } } } } @@ -395,17 +415,24 @@ public final class BridgeResources extends Resources { public int getInteger(int id) throws NotFoundException { Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); - if (value != null && value.getSecond().getValue() != null) { - String v = value.getSecond().getValue(); - int radix = 10; - if (v.startsWith("0x")) { - v = v.substring(2); - radix = 16; - } - try { - return Integer.parseInt(v, radix); - } catch (NumberFormatException e) { - // return exception below + if (value != null) { + ResourceValue resValue = value.getSecond(); + + assert resValue != null; + if (resValue != null) { + String v = resValue.getValue(); + if (v != null) { + int radix = 10; + if (v.startsWith("0x")) { + v = v.substring(2); + radix = 16; + } + try { + return Integer.parseInt(v, radix); + } catch (NumberFormatException e) { + // return exception below + } + } } } @@ -420,9 +447,16 @@ public final class BridgeResources extends Resources { public boolean getBoolean(int id) throws NotFoundException { Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); - if (value != null && value.getSecond().getValue() != null) { - String v = value.getSecond().getValue(); - return Boolean.parseBoolean(v); + if (value != null) { + ResourceValue resValue = value.getSecond(); + + assert resValue != null; + if (resValue != null) { + String v = resValue.getValue(); + if (v != null) { + return Boolean.parseBoolean(v); + } + } } // id was not found or not resolved. Throw a NotFoundException. diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java index 9deed32..8fdac02 100644 --- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java +++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java @@ -33,9 +33,6 @@ import com.android.resources.ResourceType; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; -import android.content.res.ColorStateList; -import android.content.res.Resources; -import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.util.DisplayMetrics; import android.util.TypedValue; @@ -897,12 +894,6 @@ public final class BridgeTypedArray extends TypedArray { } @Override - public boolean getValueAt(int index, TypedValue outValue) { - // pass - return false; - } - - @Override public String toString() { return Arrays.toString(mResourceData); } diff --git a/tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java new file mode 100644 index 0000000..0a7899a --- /dev/null +++ b/tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java @@ -0,0 +1,30 @@ +/* + * 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 android.content.res; + +import com.android.tools.layoutlib.annotations.LayoutlibDelegate; + +import android.util.TypedValue; + +public class TypedArray_Delegate { + + @LayoutlibDelegate + public static boolean getValueAt(TypedArray theTypedArray, int index, TypedValue outValue) { + // pass + return false; + } +} diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java index 66e59d8..eadec02 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java @@ -22,7 +22,6 @@ import com.android.layoutlib.bridge.impl.DelegateManager; import com.android.resources.Density; import com.android.tools.layoutlib.annotations.LayoutlibDelegate; -import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.os.Parcel; @@ -149,7 +148,7 @@ public final class Bitmap_Delegate { } public static int getBufferedImageType(int nativeBitmapConfig) { - switch (Config.sConfigs[nativeBitmapConfig]) { + switch (Config.nativeToConfig(nativeBitmapConfig)) { case ALPHA_8: return BufferedImage.TYPE_INT_ARGB; case RGB_565: @@ -210,7 +209,7 @@ public final class Bitmap_Delegate { } // create a delegate with the content of the stream. - Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.sConfigs[nativeConfig]); + Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig)); return createBitmap(delegate, mutable, Bitmap.getDefaultDensity()); } @@ -238,7 +237,7 @@ public final class Bitmap_Delegate { image.setRGB(0, 0, width, height, argb, 0, width); // create a delegate with the content of the stream. - Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.sConfigs[nativeConfig]); + Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig)); return createBitmap(delegate, isMutable, Bitmap.getDefaultDensity()); } diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java new file mode 100644 index 0000000..2745770 --- /dev/null +++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java @@ -0,0 +1,24 @@ +/* + * 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 android.graphics; + +public class Typeface_Accessor { + + public static void resetDefaults() { + Typeface.sDefaults = null; + } +} diff --git a/tools/layoutlib/bridge/src/android/os/Looper_Accessor.java b/tools/layoutlib/bridge/src/android/os/Looper_Accessor.java new file mode 100644 index 0000000..ad95fcc --- /dev/null +++ b/tools/layoutlib/bridge/src/android/os/Looper_Accessor.java @@ -0,0 +1,24 @@ +/* + * 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 android.os; + +public class Looper_Accessor { + + public static void cleanupThread() { + // clean up the looper + Looper.sThreadLocal.remove(); + } +} diff --git a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java b/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java index 63711a7..bd332a6 100644 --- a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java +++ b/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java @@ -68,4 +68,28 @@ public class SystemClock_Delegate { /*package*/ static long currentThreadTimeMillis() { return System.currentTimeMillis(); } + + /** + * Returns microseconds running in the current thread. + * + * @return elapsed microseconds in the thread + * + * @hide + */ + @LayoutlibDelegate + /*package*/ static long currentThreadTimeMicro() { + return System.currentTimeMillis() * 1000; + } + + /** + * Returns current wall time in microseconds. + * + * @return elapsed microseconds in wall time + * + * @hide + */ + @LayoutlibDelegate + /*package*/ static long currentTimeMicro() { + return elapsedRealtime() * 1000; + } } diff --git a/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java b/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java new file mode 100644 index 0000000..0a3cdc6 --- /dev/null +++ b/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.util; + +import com.android.ide.common.rendering.api.RenderResources; +import com.android.ide.common.rendering.api.ResourceValue; +import com.android.layoutlib.bridge.Bridge; +import com.android.layoutlib.bridge.BridgeConstants; +import com.android.layoutlib.bridge.android.BridgeContext; +import com.android.resources.ResourceType; + +import org.xmlpull.v1.XmlPullParser; + +import android.util.AttributeSet; +import android.util.XmlPullAttributes; + +/** + * A correct implementation of the {@link AttributeSet} interface on top of a XmlPullParser + */ +public class BridgeXmlPullAttributes extends XmlPullAttributes { + + private final BridgeContext mContext; + private final boolean mPlatformFile; + + public BridgeXmlPullAttributes(XmlPullParser parser, BridgeContext context, + boolean platformFile) { + super(parser); + mContext = context; + mPlatformFile = platformFile; + } + + /* + * (non-Javadoc) + * @see android.util.XmlPullAttributes#getAttributeNameResource(int) + * + * This methods must return com.android.internal.R.attr.<name> matching + * the name of the attribute. + * It returns 0 if it doesn't find anything. + */ + @Override + public int getAttributeNameResource(int index) { + // get the attribute name. + String name = getAttributeName(index); + + // get the attribute namespace + String ns = mParser.getAttributeNamespace(index); + + if (BridgeConstants.NS_RESOURCES.equals(ns)) { + Integer v = Bridge.getResourceId(ResourceType.ATTR, name); + if (v != null) { + return v.intValue(); + } + + return 0; + } + + // this is not an attribute in the android namespace, we query the customviewloader, if + // the namespaces match. + if (mContext.getProjectCallback().getNamespace().equals(ns)) { + Integer v = mContext.getProjectCallback().getResourceId(ResourceType.ATTR, name); + if (v != null) { + return v.intValue(); + } + } + + return 0; + } + + /* + * (non-Javadoc) + * @see android.util.XmlPullAttributes#getAttributeResourceValue(int, int) + */ + @Override + public int getAttributeResourceValue(int index, int defaultValue) { + String value = getAttributeValue(index); + + return resolveResourceValue(value, defaultValue); + } + + /* + * (non-Javadoc) + * @see android.util.XmlPullAttributes#getAttributeResourceValue(java.lang.String, java.lang.String, int) + */ + @Override + public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) { + String value = getAttributeValue(namespace, attribute); + + return resolveResourceValue(value, defaultValue); + } + + private int resolveResourceValue(String value, int defaultValue) { + // now look for this particular value + RenderResources resources = mContext.getRenderResources(); + ResourceValue resource = resources.resolveResValue( + resources.findResValue(value, mPlatformFile)); + + if (resource != null) { + Integer id = null; + if (mPlatformFile || resource.isFramework()) { + id = Bridge.getResourceId(resource.getResourceType(), resource.getName()); + } else { + id = mContext.getProjectCallback().getResourceId( + resource.getResourceType(), resource.getName()); + } + + if (id != null) { + return id; + } + } + + return defaultValue; + } + +} diff --git a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java new file mode 100644 index 0000000..e3778b1 --- /dev/null +++ b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java @@ -0,0 +1,40 @@ +/* + * 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 android.view; + +import com.android.layoutlib.bridge.android.BridgeWindow; +import com.android.layoutlib.bridge.android.BridgeWindowSession; + +import android.os.Handler; +import android.view.View.AttachInfo; + +public class AttachInfo_Accessor { + + public static void setAttachInfo(View 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; + view.dispatchAttachedToWindow(info, 0); + } + + public static void dispatchOnPreDraw(View view) { + view.mAttachInfo.mTreeObserver.dispatchOnPreDraw(); + } +} diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java new file mode 100644 index 0000000..941f1ce6 --- /dev/null +++ b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view; + +import com.android.ide.common.rendering.api.IProjectCallback; +import com.android.ide.common.rendering.api.LayoutLog; +import com.android.ide.common.rendering.api.MergeCookie; +import com.android.ide.common.rendering.api.ResourceReference; +import com.android.ide.common.rendering.api.ResourceValue; +import com.android.layoutlib.bridge.Bridge; +import com.android.layoutlib.bridge.android.BridgeContext; +import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; +import com.android.layoutlib.bridge.impl.ParserFactory; +import com.android.resources.ResourceType; +import com.android.util.Pair; + +import org.xmlpull.v1.XmlPullParser; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.InflateException; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import java.io.File; + +/** + * Custom implementation of {@link LayoutInflater} to handle custom views. + */ +public final class BridgeInflater extends LayoutInflater { + + private final IProjectCallback mProjectCallback; + private boolean mIsInMerge = false; + private ResourceReference mResourceReference; + + /** + * List of class prefixes which are tried first by default. + * <p/> + * This should match the list in com.android.internal.policy.impl.PhoneLayoutInflater. + */ + private static final String[] sClassPrefixList = { + "android.widget.", + "android.webkit." + }; + + protected BridgeInflater(LayoutInflater original, Context newContext) { + super(original, newContext); + mProjectCallback = null; + } + + /** + * Instantiate a new BridgeInflater with an {@link IProjectCallback} object. + * + * @param context The Android application context. + * @param projectCallback the {@link IProjectCallback} object. + */ + public BridgeInflater(Context context, IProjectCallback projectCallback) { + super(context); + mProjectCallback = projectCallback; + mConstructorArgs[0] = context; + } + + @Override + public View onCreateView(String name, AttributeSet attrs) throws ClassNotFoundException { + View view = null; + + try { + // First try to find a class using the default Android prefixes + for (String prefix : sClassPrefixList) { + try { + view = createView(name, prefix, attrs); + if (view != null) { + break; + } + } catch (ClassNotFoundException e) { + // Ignore. We'll try again using the base class below. + } + } + + // Next try using the parent loader. This will most likely only work for + // fully-qualified class names. + try { + if (view == null) { + view = super.onCreateView(name, attrs); + } + } catch (ClassNotFoundException e) { + // Ignore. We'll try again using the custom view loader below. + } + + // Finally try again using the custom view loader + try { + if (view == null) { + view = loadCustomView(name, attrs); + } + } catch (ClassNotFoundException e) { + // If the class was not found, we throw the exception directly, because this + // method is already expected to throw it. + throw e; + } + } catch (Exception e) { + // Wrap the real exception in a ClassNotFoundException, so that the calling method + // can deal with it. + ClassNotFoundException exception = new ClassNotFoundException("onCreateView", e); + throw exception; + } + + setupViewInContext(view, attrs); + + return view; + } + + @Override + public View createViewFromTag(View parent, String name, AttributeSet attrs) { + View view = null; + try { + view = super.createViewFromTag(parent, name, attrs); + } catch (InflateException e) { + // try to load the class from using the custom view loader + try { + view = loadCustomView(name, attrs); + } catch (Exception e2) { + // Wrap the real exception in an InflateException so that the calling + // method can deal with it. + InflateException exception = new InflateException(); + if (e2.getClass().equals(ClassNotFoundException.class) == false) { + exception.initCause(e2); + } else { + exception.initCause(e); + } + throw exception; + } + } + + setupViewInContext(view, attrs); + + return view; + } + + @Override + public View inflate(int resource, ViewGroup root) { + Context context = getContext(); + if (context instanceof BridgeContext) { + BridgeContext bridgeContext = (BridgeContext)context; + + ResourceValue value = null; + + Pair<ResourceType, String> layoutInfo = Bridge.resolveResourceId(resource); + if (layoutInfo != null) { + value = bridgeContext.getRenderResources().getFrameworkResource( + ResourceType.LAYOUT, layoutInfo.getSecond()); + } else { + layoutInfo = mProjectCallback.resolveResourceId(resource); + + if (layoutInfo != null) { + value = bridgeContext.getRenderResources().getProjectResource( + ResourceType.LAYOUT, layoutInfo.getSecond()); + } + } + + if (value != null) { + File f = new File(value.getValue()); + if (f.isFile()) { + try { + XmlPullParser parser = ParserFactory.create(f); + + BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser( + parser, bridgeContext, false); + + return inflate(bridgeParser, root); + } catch (Exception e) { + Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, + "Failed to parse file " + f.getAbsolutePath(), e, null /*data*/); + + return null; + } + } + } + } + return null; + } + + private View loadCustomView(String name, AttributeSet attrs) throws ClassNotFoundException, + Exception{ + if (mProjectCallback != null) { + // first get the classname in case it's not the node name + if (name.equals("view")) { + name = attrs.getAttributeValue(null, "class"); + } + + mConstructorArgs[1] = attrs; + + Object customView = mProjectCallback.loadView(name, mConstructorSignature, + mConstructorArgs); + + if (customView instanceof View) { + return (View)customView; + } + } + + return null; + } + + private void setupViewInContext(View view, AttributeSet attrs) { + if (getContext() instanceof BridgeContext) { + BridgeContext bc = (BridgeContext) getContext(); + if (attrs instanceof BridgeXmlBlockParser) { + BridgeXmlBlockParser parser = (BridgeXmlBlockParser) attrs; + + // get the view key + Object viewKey = parser.getViewCookie(); + + if (viewKey == null) { + int currentDepth = parser.getDepth(); + + // test whether we are in an included file or in a adapter binding view. + BridgeXmlBlockParser previousParser = bc.getPreviousParser(); + if (previousParser != null) { + // looks like we inside an embedded layout. + // only apply the cookie of the calling node (<include>) if we are at the + // top level of the embedded layout. If there is a merge tag, then + // skip it and look for the 2nd level + int testDepth = mIsInMerge ? 2 : 1; + if (currentDepth == testDepth) { + viewKey = previousParser.getViewCookie(); + // if we are in a merge, wrap the cookie in a MergeCookie. + if (viewKey != null && mIsInMerge) { + viewKey = new MergeCookie(viewKey); + } + } + } else if (mResourceReference != null && currentDepth == 1) { + // else if there's a resource reference, this means we are in an adapter + // binding case. Set the resource ref as the view cookie only for the top + // level view. + viewKey = mResourceReference; + } + } + + if (viewKey != null) { + bc.addViewKey(view, viewKey); + } + } + } + } + + public void setIsInMerge(boolean isInMerge) { + mIsInMerge = isInMerge; + } + + public void setResourceReference(ResourceReference reference) { + mResourceReference = reference; + } + + @Override + public LayoutInflater cloneInContext(Context newContext) { + return new BridgeInflater(this, newContext); + } +} diff --git a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java index 83f9cc2..9732530 100644 --- a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java +++ b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java @@ -46,31 +46,17 @@ public class Display_Delegate { } @LayoutlibDelegate - /** @hide Returns the actual screen size, not including any decor. */ - /*package*/ static int getRealWidth(Display theDisplay) { - // always dynamically query for the current window manager - return RenderAction.getCurrentContext().getIWindowManager().getMetrics().widthPixels; - } - - @LayoutlibDelegate - /** @hide Returns the actual screen size, not including any decor. */ - /*package*/ static int getRealHeight(Display theDisplay) { - // always dynamically query for the current window manager - return RenderAction.getCurrentContext().getIWindowManager().getMetrics().heightPixels; - } - - @LayoutlibDelegate /** @hide special for when we are faking the screen size. */ /*package*/ static int getRawWidth(Display theDisplay) { // same as real since we're not faking compatibility mode. - return getRealWidth(theDisplay); + return RenderAction.getCurrentContext().getIWindowManager().getMetrics().widthPixels; } @LayoutlibDelegate /** @hide special for when we are faking the screen size. */ /*package*/ static int getRawHeight(Display theDisplay) { // same as real since we're not faking compatibility mode. - return getRealHeight(theDisplay); + return RenderAction.getCurrentContext().getIWindowManager().getMetrics().heightPixels; } @LayoutlibDelegate diff --git a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java b/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java index 64efa7e..3db3a1b 100644 --- a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java +++ b/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java @@ -16,7 +16,6 @@ package android.view; -import com.android.layoutlib.bridge.android.BridgeInflater; import com.android.tools.layoutlib.annotations.LayoutlibDelegate; import org.xmlpull.v1.XmlPullParser; diff --git a/tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java b/tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java new file mode 100644 index 0000000..01db34e --- /dev/null +++ b/tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java @@ -0,0 +1,26 @@ +/* + * 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 android.view; + +public class ViewConfiguration_Accessor { + + public static void clearConfigurations() { + // clear the stored ViewConfiguration since the map is per density and not per context. + ViewConfiguration.sConfigurations.clear(); + } + +} diff --git a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java new file mode 100644 index 0000000..875336a --- /dev/null +++ b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java @@ -0,0 +1,24 @@ +/* + * 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 android.view.inputmethod; + +public class InputMethodManager_Accessor { + + public static void resetInstance() { + InputMethodManager.mInstance = null; + } +} |