RenderSessionImpl.java revision a2378f55b81e7d29f451d7f65527de49417a3f0c
13bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet/* 23bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Copyright (C) 2010 The Android Open Source Project 33bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * 43bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License"); 53bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * you may not use this file except in compliance with the License. 63bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * You may obtain a copy of the License at 73bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * 83bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * http://www.apache.org/licenses/LICENSE-2.0 93bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * 103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Unless required by applicable law or agreed to in writing, software 113bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS, 123bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * See the License for the specific language governing permissions and 143bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * limitations under the License. 153bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 173bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetpackage com.android.layoutlib.bridge.impl; 183bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 19ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_ANIM_NOT_FOUND; 20ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_INFLATION; 21ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_LOCK_INTERRUPTED; 22ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLATED; 23ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_TIMEOUT; 24ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; 25ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP_NO_CHILDREN; 26ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.SUCCESS; 27ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet 28ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.IAnimationListener; 29ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.ILayoutPullParser; 30ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.IProjectCallback; 31907c716cce7b8fa785d9005081d25d3ecc2d5365Xavier Ducrohetimport com.android.ide.common.rendering.api.LayoutLog; 32ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.Params; 330d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohetimport com.android.ide.common.rendering.api.RenderResources; 34ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderSession; 35ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.ResourceValue; 36ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.Result; 37ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.StyleResourceValue; 38ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.ViewInfo; 39ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.Params.RenderingMode; 400d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohetimport com.android.ide.common.rendering.api.RenderResources.FrameworkResourceIdProvider; 41ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.Result.Status; 423bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport com.android.internal.util.XmlUtils; 43ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohetimport com.android.layoutlib.bridge.Bridge; 443bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeContext; 453bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeInflater; 46ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes; 473bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeWindow; 483bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeWindowSession; 493bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeXmlBlockParser; 50a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohetimport com.android.resources.Density; 511b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohetimport com.android.resources.ResourceType; 52a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohetimport com.android.resources.ScreenSize; 53947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohetimport com.android.util.Pair; 543bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 5533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohetimport android.animation.Animator; 56ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohetimport android.animation.AnimatorInflater; 5733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohetimport android.animation.LayoutTransition; 5862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohetimport android.animation.LayoutTransition.TransitionListener; 593bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.app.Fragment_Delegate; 603bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.Bitmap; 613bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.Bitmap_Delegate; 623bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.Canvas; 633bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.drawable.Drawable; 643bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.os.Handler; 653bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.util.DisplayMetrics; 663bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.util.TypedValue; 673bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.view.View; 683bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.view.ViewGroup; 693bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.view.View.AttachInfo; 703bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.view.View.MeasureSpec; 71ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohetimport android.view.ViewGroup.LayoutParams; 723bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.widget.FrameLayout; 73f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbyeimport android.widget.LinearLayout; 7462c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohetimport android.widget.QuickContactBadge; 753bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.widget.TabHost; 763bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.widget.TabWidget; 77f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbyeimport android.widget.TabHost.TabSpec; 783bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 794c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohetimport java.awt.AlphaComposite; 803bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.awt.Color; 813bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.awt.Graphics2D; 823bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.awt.image.BufferedImage; 833bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.util.ArrayList; 843bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.util.List; 853bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.util.Map; 86ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohetimport java.util.concurrent.TimeUnit; 87ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohetimport java.util.concurrent.locks.ReentrantLock; 883bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 893bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet/** 90ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * Class implementing the render session. 913bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * 92ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * A session is a stateful representation of a layout file. It is initialized with data coming 93ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then 943bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * be done on the layout. 953bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * 963bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 970d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohetpublic class RenderSessionImpl extends FrameworkResourceIdProvider { 983bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 993bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private static final int DEFAULT_TITLE_BAR_HEIGHT = 25; 1003bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private static final int DEFAULT_STATUS_BAR_HEIGHT = 25; 1013bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 102ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet /** 103ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * The current context being rendered. This is set through {@link #acquire(long)} and 104ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * {@link #init(long)}, and unset in {@link #release()}. 105ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet */ 106ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet private static BridgeContext sCurrentContext = null; 107ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 108ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet private final Params mParams; 1093bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // scene state 111ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet private RenderSession mScene; 1123bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private BridgeContext mContext; 1133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private BridgeXmlBlockParser mBlockParser; 1143bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private BridgeInflater mInflater; 1156a5b91fceb1913cab6416bef99d7b28530d16ecfXavier Ducrohet private ResourceValue mWindowBackground; 1163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private FrameLayout mViewRoot; 1171392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet private Canvas mCanvas; 1181392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet private int mMeasuredScreenWidth = -1; 1191392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet private int mMeasuredScreenHeight = -1; 120a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet private boolean mIsAlphaChannelImage = true; 121a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 122a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet private int mStatusBarSize; 123a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet private int mTopBarSize; 124a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet private int mSystemBarSize; 125a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet private int mTopOffset; 126a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet private int mTotalBarSize; 127a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1283bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1293bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // information being returned through the API 1303bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private BufferedImage mImage; 131e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet private List<ViewInfo> mViewInfoList; 1323bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1333bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private static final class PostInflateException extends Exception { 1343bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private static final long serialVersionUID = 1L; 1353bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1363bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet public PostInflateException(String message) { 1373bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet super(message); 1383bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 1393bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 1403bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1413bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 1423bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Creates a layout scene with all the information coming from the layout bridge API. 1433bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * <p> 144ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init()}, which act as a 145ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * call to {@link RenderSessionImpl#acquire(long)} 1463bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * 1473bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * @see LayoutBridge#createScene(com.android.layoutlib.api.SceneParams) 1483bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 149ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public RenderSessionImpl(Params params) { 1503bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // copy the params. 151ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet mParams = new Params(params); 152ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 153ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 154ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet /** 155ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * Initializes and acquires the scene, creating various Android objects such as context, 156ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * inflater, and parser. 157ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 158ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @param timeout the time to wait if another rendering is happening. 159ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 160ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @return whether the scene was prepared 161ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 162ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @see #acquire(long) 163ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @see #release() 164ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet */ 165ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result init(long timeout) { 166ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet // acquire the lock. if the result is null, lock was just acquired, otherwise, return 167ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet // the result. 168ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet Result result = acquireLock(timeout); 169ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (result != null) { 170ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet return result; 171ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 1723bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1733bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // setup the display Metrics. 1743bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet DisplayMetrics metrics = new DisplayMetrics(); 1753bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet metrics.densityDpi = mParams.getDensity(); 1763bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet metrics.density = mParams.getDensity() / (float) DisplayMetrics.DENSITY_DEFAULT; 1773bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet metrics.scaledDensity = metrics.density; 1783bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet metrics.widthPixels = mParams.getScreenWidth(); 1793bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet metrics.heightPixels = mParams.getScreenHeight(); 1803bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet metrics.xdpi = mParams.getXdpi(); 1813bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet metrics.ydpi = mParams.getYdpi(); 1823bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1830d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet RenderResources resources = mParams.getResources(); 1843bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1853bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // build the context 1860d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet mContext = new BridgeContext(mParams.getProjectKey(), metrics, resources, 1870d8c2a8b1c307453a54211fdcebb68b564344feaXavier Ducrohet mParams.getProjectCallback(), mParams.getTargetSdkVersion()); 1883bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 189a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet // use default of true in case it's not found to use alpha by default 190a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mIsAlphaChannelImage = getBooleanThemeValue(resources, 191a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet "windowIsFloating", true /*defaultValue*/); 192a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 193ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 1940d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet setUp(); 1953bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 196a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet findBackground(resources); 197a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet findStatusBar(resources, metrics); 198a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet findTopBar(resources, metrics); 199a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet findSystemBar(resources, metrics); 2003bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 201a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mTopOffset = mStatusBarSize + mTopBarSize; 202a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mTotalBarSize = mTopOffset + mSystemBarSize; 2033bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 2043bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // build the inflater and parser. 2053bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet mInflater = new BridgeInflater(mContext, mParams.getProjectCallback()); 2063bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet mContext.setBridgeInflater(mInflater); 2073bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet mInflater.setFactory2(mContext); 2083bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 2093bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet mBlockParser = new BridgeXmlBlockParser(mParams.getLayoutDescription(), 2103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet mContext, false /* platformResourceFlag */); 211ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 212ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(); 2133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 2143bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 2153bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 216ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * Prepares the scene for action. 217ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * <p> 218ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * This call is blocking if another rendering/inflating is currently happening, and will return 219ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * whether the preparation worked. 220ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 221ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * The preparation can fail if another rendering took too long and the timeout was elapsed. 222ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 223ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * More than one call to this from the same thread will have no effect and will return 224ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * {@link Result#SUCCESS}. 225ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 226ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * After scene actions have taken place, only one call to {@link #release()} must be 227ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * done. 228ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 229ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @param timeout the time to wait if another rendering is happening. 230ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 231ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @return whether the scene was prepared 232ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 233ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @see #release() 234ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 235ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @throws IllegalStateException if {@link #init(long)} was never called. 236ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet */ 237ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result acquire(long timeout) { 238ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (mContext == null) { 239ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet throw new IllegalStateException("After scene creation, #init() must be called"); 240ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 241ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 242ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet // acquire the lock. if the result is null, lock was just acquired, otherwise, return 243ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet // the result. 244ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet Result result = acquireLock(timeout); 245ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (result != null) { 246ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet return result; 247ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 2483bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 2490d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet setUp(); 250ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 2513054fe698a6be732e24128541a1db867ec606a59Xavier Ducrohet return SUCCESS.createResult(); 2523bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 2533bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 2543bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 255ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * Acquire the lock so that the scene can be acted upon. 2563bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * <p> 257ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * This returns null if the lock was just acquired, otherwise it returns 258ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * {@link Result#SUCCESS} if the lock already belonged to that thread, or another 259ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * instance (see {@link Result#getStatus()}) if an error occurred. 260ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 261ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @param timeout the time to wait if another rendering is happening. 262ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @return null if the lock was just acquire or another result depending on the state. 263ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 264ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 265ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * the scene. 2663bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 267ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet private Result acquireLock(long timeout) { 268ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet ReentrantLock lock = Bridge.getLock(); 269ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (lock.isHeldByCurrentThread() == false) { 270ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet try { 271ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet boolean acquired = lock.tryLock(timeout, TimeUnit.MILLISECONDS); 272ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 273ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (acquired == false) { 2743054fe698a6be732e24128541a1db867ec606a59Xavier Ducrohet return ERROR_TIMEOUT.createResult(); 275ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 276ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } catch (InterruptedException e) { 2773054fe698a6be732e24128541a1db867ec606a59Xavier Ducrohet return ERROR_LOCK_INTERRUPTED.createResult(); 278ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 279ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } else { 280ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet // This thread holds the lock already. Checks that this wasn't for a different context. 281ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet // If this is called by init, mContext will be null and so should sCurrentContext 282ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet // anyway 283ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (mContext != sCurrentContext) { 284ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet throw new IllegalStateException("Acquiring different scenes from same thread without releases"); 285ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 2863054fe698a6be732e24128541a1db867ec606a59Xavier Ducrohet return SUCCESS.createResult(); 287ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 2883bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 289ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet return null; 290ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 291ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 292ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet /** 293ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * Cleans up the scene after an action. 294ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet */ 295ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet public void release() { 296ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet ReentrantLock lock = Bridge.getLock(); 297ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 298ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet // with the use of finally blocks, it is possible to find ourself calling this 299ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet // without a successful call to prepareScene. This test makes sure that unlock() will 300ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet // not throw IllegalMonitorStateException. 301ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (lock.isHeldByCurrentThread()) { 3020d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet tearDown(); 303ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet lock.unlock(); 304ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 3053bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 3063bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 3073bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 3080d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet * Sets up the session for rendering. 3090d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet * <p/> 3100d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet * The counterpart is {@link #tearDown()}. 3110d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet */ 3120d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet private void setUp() { 3130d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet // make sure the Resources object references the context (and other objects) for this 3140d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet // scene 3150d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet mContext.initResources(); 3160d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet sCurrentContext = mContext; 3170d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet 3180d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet LayoutLog currentLog = mParams.getLog(); 3190d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet Bridge.setLog(currentLog); 3200d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet mContext.getRenderResources().setFrameworkResourceIdProvider(this); 3210d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet mContext.getRenderResources().setLogger(currentLog); 3220d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet } 3230d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet 3240d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet /** 3250d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet * Tear down the session after rendering. 3260d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet * <p/> 3270d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet * The counterpart is {@link #setUp()}. 3280d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet */ 3290d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet private void tearDown() { 3300d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet // Make sure to remove static references, otherwise we could not unload the lib 3310d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet mContext.disposeResources(); 3320d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet sCurrentContext = null; 3330d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet 3340d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet Bridge.setLog(null); 3350d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet mContext.getRenderResources().setFrameworkResourceIdProvider(null); 3360d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet mContext.getRenderResources().setLogger(null); 33788aa1f36d93e9e214c3c64864a8c692d6a733892Xavier Ducrohet } 3380d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet 33988aa1f36d93e9e214c3c64864a8c692d6a733892Xavier Ducrohet public static BridgeContext getCurrentContext() { 34088aa1f36d93e9e214c3c64864a8c692d6a733892Xavier Ducrohet return sCurrentContext; 3410d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet } 3420d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet 3430d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet /** 3443bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Inflates the layout. 3453bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * <p> 346ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 347ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 348ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 349ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * the scene, or if {@link #init(long)} was not called. 3503bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 351ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result inflate() { 352ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet checkLock(); 353ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 3543bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet try { 3553bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 3563bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet mViewRoot = new FrameLayout(mContext); 3573bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 3583bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // Sets the project callback (custom view loader) to the fragment delegate so that 3593bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // it can instantiate the custom Fragment. 3603bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet Fragment_Delegate.setProjectCallback(mParams.getProjectCallback()); 3613bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 3623bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet View view = mInflater.inflate(mBlockParser, mViewRoot); 3633bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 3643bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet Fragment_Delegate.setProjectCallback(null); 3653bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 3663bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // set the AttachInfo on the root view. 3673bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet AttachInfo info = new AttachInfo(new BridgeWindowSession(), new BridgeWindow(), 3683bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet new Handler(), null); 3693bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet info.mHasWindowFocus = true; 3703bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet info.mWindowVisibility = View.VISIBLE; 3713bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet info.mInTouchMode = false; // this is so that we can display selections. 37290f9956c17660c35ee6fe934815c16e97bf0d3f8Xavier Ducrohet info.mHardwareAccelerated = false; 3733bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet mViewRoot.dispatchAttachedToWindow(info, 0); 3743bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 375a2378f55b81e7d29f451d7f65527de49417a3f0cXavier Ducrohet // post-inflate process. For now this supports TabHost/TabWidget 376a2378f55b81e7d29f451d7f65527de49417a3f0cXavier Ducrohet postInflateProcess(view, mParams.getProjectCallback()); 377a2378f55b81e7d29f451d7f65527de49417a3f0cXavier Ducrohet 3783bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // get the background drawable 3793bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (mWindowBackground != null) { 3803bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet Drawable d = ResourceHelper.getDrawable(mWindowBackground, 3813bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet mContext, true /* isFramework */); 3823bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet mViewRoot.setBackgroundDrawable(d); 3833bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 3843bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 385ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(); 3863bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } catch (PostInflateException e) { 387ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_INFLATION.createResult(e.getMessage(), e); 3883bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } catch (Throwable e) { 3893bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // get the real cause of the exception. 3903bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet Throwable t = e; 3913bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet while (t.getCause() != null) { 3923bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet t = t.getCause(); 3933bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 3943bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 395ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_INFLATION.createResult(t.getMessage(), t); 3963bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 3973bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 3983bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 3993bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 4003bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Renders the scene. 4013bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * <p> 402ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 403ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 4044c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet * @param freshRender whether the render is a new one and should erase the existing bitmap (in 4054c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet * the case where bitmaps are reused). This is typically needed when not playing 4064c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet * animations.) 4074c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet * 408ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 409ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 4101392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet * 4111392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet * @see SceneParams#getRenderingMode() 41233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @see LayoutScene#render(long) 4133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 4144c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet public Result render(boolean freshRender) { 415ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet checkLock(); 416ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 4173bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet try { 4183bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (mViewRoot == null) { 419ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_NOT_INFLATED.createResult(); 4203bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 4213bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // measure the views 4223bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet int w_spec, h_spec; 4233bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 424e489a969de010782fcc0ab048c7357d42ada9400Xavier Ducrohet RenderingMode renderingMode = mParams.getRenderingMode(); 425e489a969de010782fcc0ab048c7357d42ada9400Xavier Ducrohet 4261392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet // only do the screen measure when needed. 4271392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet boolean newRenderSize = false; 4281392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet if (mMeasuredScreenWidth == -1) { 4291392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet newRenderSize = true; 4301392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet mMeasuredScreenWidth = mParams.getScreenWidth(); 431a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mMeasuredScreenHeight = mParams.getScreenHeight() - mTotalBarSize; 4321392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet 4331392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet if (renderingMode != RenderingMode.NORMAL) { 4341392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet // measure the full size needed by the layout. 4351392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet w_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenWidth, 4361392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet renderingMode.isHorizExpand() ? 4371392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet MeasureSpec.UNSPECIFIED // this lets us know the actual needed size 4381392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet : MeasureSpec.EXACTLY); 439a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet h_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenHeight, 4401392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet renderingMode.isVertExpand() ? 4411392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet MeasureSpec.UNSPECIFIED // this lets us know the actual needed size 4421392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet : MeasureSpec.EXACTLY); 4431392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet mViewRoot.measure(w_spec, h_spec); 4441392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet 4451392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet if (renderingMode.isHorizExpand()) { 4461392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet int neededWidth = mViewRoot.getChildAt(0).getMeasuredWidth(); 4471392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet if (neededWidth > mMeasuredScreenWidth) { 4481392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet mMeasuredScreenWidth = neededWidth; 4491392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet } 450e489a969de010782fcc0ab048c7357d42ada9400Xavier Ducrohet } 4513bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 4521392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet if (renderingMode.isVertExpand()) { 4531392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet int neededHeight = mViewRoot.getChildAt(0).getMeasuredHeight(); 454a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (neededHeight > mMeasuredScreenHeight) { 455a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mMeasuredScreenHeight = neededHeight; 4561392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet } 457e489a969de010782fcc0ab048c7357d42ada9400Xavier Ducrohet } 4583bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 4593bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 4603bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 4613bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // remeasure with the size we need 4623bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // This must always be done before the call to layout 4631392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet w_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenWidth, MeasureSpec.EXACTLY); 464a2378f55b81e7d29f451d7f65527de49417a3f0cXavier Ducrohet h_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenHeight, MeasureSpec.EXACTLY); 4653bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet mViewRoot.measure(w_spec, h_spec); 4663bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 4673bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // now do the layout. 468a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); 4693bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 470a2378f55b81e7d29f451d7f65527de49417a3f0cXavier Ducrohet mViewRoot.mAttachInfo.mTreeObserver.dispatchOnPreDraw(); 471a2378f55b81e7d29f451d7f65527de49417a3f0cXavier Ducrohet 4723bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // draw the views 4733bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // create the BufferedImage into which the layout will be rendered. 4744c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet boolean newImage = false; 4751392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet if (newRenderSize || mCanvas == null) { 4761392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet if (mParams.getImageFactory() != null) { 477a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mImage = mParams.getImageFactory().getImage( 478a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mMeasuredScreenWidth, 479a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mMeasuredScreenHeight + mTotalBarSize); 4801392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet } else { 481a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mImage = new BufferedImage( 482a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mMeasuredScreenWidth, 483a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mMeasuredScreenHeight + mTotalBarSize, 484a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet BufferedImage.TYPE_INT_ARGB); 4854c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet newImage = true; 4861392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet } 4873bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 488ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet if (mParams.isBgColorOverridden()) { 4894c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet // since we override the content, it's the same as if it was a new image. 4904c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet newImage = true; 4911392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet Graphics2D gc = mImage.createGraphics(); 492ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet gc.setColor(new Color(mParams.getOverrideBgColor(), true)); 4934c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet gc.setComposite(AlphaComposite.Src); 494a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet gc.fillRect(0, 0, mMeasuredScreenWidth, 495a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mMeasuredScreenHeight + mTotalBarSize); 4961392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet gc.dispose(); 4971392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet } 4983bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 4991392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet // create an Android bitmap around the BufferedImage 5001392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage, 5011392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet true /*isMutable*/, 502a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet Density.getEnum(mParams.getDensity())); 5033bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 5041392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet // create a Canvas around the Android bitmap 5051392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet mCanvas = new Canvas(bitmap); 5061392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet mCanvas.setDensity(mParams.getDensity()); 507a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mCanvas.translate(0, mTopOffset); 5081392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet } 5093bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 5104c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet if (freshRender && newImage == false) { 5114c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet Graphics2D gc = mImage.createGraphics(); 5124c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet gc.setComposite(AlphaComposite.Src); 513a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 514a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (mStatusBarSize > 0) { 515a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet gc.setColor(new Color(0xFF3C3C3C, true)); 516a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet gc.fillRect(0, 0, mMeasuredScreenWidth, mStatusBarSize); 517a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 518a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 519a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (mTopBarSize > 0) { 520a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet gc.setColor(new Color(0xFF7F7F7F, true)); 521a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet gc.fillRect(0, mStatusBarSize, mMeasuredScreenWidth, mTopOffset); 522a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 523a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 524a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet // erase the rest 525a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet gc.setColor(new Color(0x00000000, true)); 526a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet gc.fillRect(0, mTopOffset, 527a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mMeasuredScreenWidth, mMeasuredScreenHeight + mTopOffset); 528a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 529a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (mSystemBarSize > 0) { 530a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet gc.setColor(new Color(0xFF3C3C3C, true)); 531a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet gc.fillRect(0, mMeasuredScreenHeight + mTopOffset, 532a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mMeasuredScreenWidth, mMeasuredScreenHeight + mTotalBarSize); 533a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 534a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 535a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet // done 5364c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet gc.dispose(); 5374c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet } 5384c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet 5391392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet mViewRoot.draw(mCanvas); 5401392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet 541a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mViewInfoList = visitAllChildren((ViewGroup)mViewRoot, mContext, mTopOffset); 5423bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 5433bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // success! 544ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(); 5453bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } catch (Throwable e) { 5463bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // get the real cause of the exception. 5473bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet Throwable t = e; 5483bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet while (t.getCause() != null) { 5493bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet t = t.getCause(); 5503bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 5513bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 552ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_UNKNOWN.createResult(t.getMessage(), t); 5533bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 5543bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 5553bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 5563bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 557ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * Animate an object 558ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * <p> 559ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 560ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 561ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 562ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 56333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 56433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @see LayoutScene#animate(Object, String, boolean, IAnimationListener) 565ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet */ 566ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result animate(Object targetObject, String animationName, 567ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet boolean isFrameworkAnimation, IAnimationListener listener) { 568ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet checkLock(); 569ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 570ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet // find the animation file. 5716a5b91fceb1913cab6416bef99d7b28530d16ecfXavier Ducrohet ResourceValue animationResource = null; 572ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet int animationId = 0; 573ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (isFrameworkAnimation) { 5740d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet animationResource = mContext.getRenderResources().getFrameworkResource( 5751b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet ResourceType.ANIMATOR, animationName); 576ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (animationResource != null) { 577947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohet animationId = Bridge.getResourceId(ResourceType.ANIMATOR, animationName); 578ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 579ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } else { 5800d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet animationResource = mContext.getRenderResources().getProjectResource( 5811b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet ResourceType.ANIMATOR, animationName); 582ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (animationResource != null) { 583947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohet animationId = mContext.getProjectCallback().getResourceId( 5841b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet ResourceType.ANIMATOR, animationName); 585ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 586ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 587ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 588ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (animationResource != null) { 589ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet try { 59033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet Animator anim = AnimatorInflater.loadAnimator(mContext, animationId); 591ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (anim != null) { 592ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet anim.setTarget(targetObject); 593ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 59433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet new PlayAnimationThread(anim, this, animationName, listener).start(); 595ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 596ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(); 597ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 598ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } catch (Exception e) { 599b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet // get the real cause of the exception. 600b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet Throwable t = e; 601b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet while (t.getCause() != null) { 602b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet t = t.getCause(); 603b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 604b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 605ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_UNKNOWN.createResult(t.getMessage(), t); 606ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 607ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 608ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 609ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_ANIM_NOT_FOUND.createResult(); 610b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 611b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 61233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet /** 61333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * Insert a new child into an existing parent. 61433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * <p> 61533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 61633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 61733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 61833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 61933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 620ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * @see LayoutScene#insertChild(Object, ILayoutPullParser, int, IAnimationListener) 62133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet */ 622ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml, 62333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet final int index, IAnimationListener listener) { 624b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet checkLock(); 625b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 626b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet // create a block parser for the XML 627b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(childXml, mContext, 628b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet false /* platformResourceFlag */); 629b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 630b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet // inflate the child without adding it to the root since we want to control where it'll 631b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet // get added. We do pass the parentView however to ensure that the layoutParams will 632b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet // be created correctly. 63333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/); 634b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 63533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet invalidateRenderingSize(); 63633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 63733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet if (listener != null) { 63833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet new AnimationThread(this, "insertChild", listener) { 63933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 64033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet @Override 641ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result preAnimation() { 64233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet parentView.setLayoutTransition(new LayoutTransition()); 64333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet return addView(parentView, child, index); 64433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 64533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 64633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet @Override 64733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet public void postAnimation() { 64833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet parentView.setLayoutTransition(null); 64933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 65033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet }.start(); 65133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 65233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // always return success since the real status will come through the listener. 653ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(child); 6541392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet } 6551392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet 65633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // add it to the parentView in the correct location 657ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet Result result = addView(parentView, child, index); 65833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet if (result.isSuccess() == false) { 65933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet return result; 66033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 661b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 6624c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet result = render(false /*freshRender*/); 6631766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet if (result.isSuccess()) { 66433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet result = result.getCopyWithData(child); 6651766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet } 6661766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet 6671766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet return result; 668b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 669b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 67033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet /** 67133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * Adds a given view to a given parent at a given index. 67233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 67333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @param parent the parent to receive the view 67433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @param view the view to add to the parent 67533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @param index the index where to do the add. 67633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 677ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 678ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 67933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * adding views. 68033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet */ 681ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet private Result addView(ViewGroup parent, View view, int index) { 68233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet try { 68333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet parent.addView(view, index); 684ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(); 68533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } catch (UnsupportedOperationException e) { 68633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 687ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 68833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 68933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 69033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 69133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet /** 69233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * Moves a view to a new parent at a given location 69333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * <p> 69433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 69533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 69633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 69733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 69833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 69933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @see LayoutScene#moveChild(Object, Object, int, Map, IAnimationListener) 70033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet */ 70162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet public Result moveChild(final ViewGroup newParentView, final View childView, final int index, 70224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet Map<String, String> layoutParamsMap, final IAnimationListener listener) { 703b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet checkLock(); 704b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 70533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet invalidateRenderingSize(); 70633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 707ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet LayoutParams layoutParams = null; 70833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet if (layoutParamsMap != null) { 70933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // need to create a new LayoutParams object for the new parent. 71062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet layoutParams = newParentView.generateLayoutParams( 71133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet new BridgeLayoutParamsMapAttributes(layoutParamsMap)); 71233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 7131392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet 71462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // get the current parent of the view that needs to be moved. 71562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet final ViewGroup previousParent = (ViewGroup) childView.getParent(); 71662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 71733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet if (listener != null) { 71833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet final LayoutParams params = layoutParams; 719ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet 72024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // there is no support for animating views across layouts, so in case the new and old 72124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // parent views are different we fake the animation through a no animation thread. 72224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet if (previousParent != newParentView) { 72324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet new Thread("not animated moveChild") { 72424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet @Override 72524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet public void run() { 72624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet Result result = moveView(previousParent, newParentView, childView, index, 72724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet params); 72824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet if (result.isSuccess() == false) { 72924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet listener.done(result); 73024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 73124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 73224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // ready to do the work, acquire the scene. 73324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet result = acquire(250); 73424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet if (result.isSuccess() == false) { 73524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet listener.done(result); 73624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet return; 73724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 73824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 73924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet try { 7404c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet result = render(false /*freshRender*/); 74124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet if (result.isSuccess()) { 74224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet listener.onNewFrame(RenderSessionImpl.this.getSession()); 74324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 74424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } finally { 74524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet release(); 74624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 74724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 74824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet listener.done(result); 74962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 75024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet }.start(); 75124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } else { 75224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet new AnimationThread(this, "moveChild", listener) { 75362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 75424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet @Override 75524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet public Result preAnimation() { 75624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // set up the transition for the parent. 75724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet LayoutTransition transition = new LayoutTransition(); 75824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet previousParent.setLayoutTransition(transition); 7595562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet 76024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // tweak the animation durations and start delays (to match the duration of 76124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // animation playing just before). 76224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // Note: Cannot user Animation.setDuration() directly. Have to set it 76324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // on the LayoutTransition. 76424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet transition.setDuration(LayoutTransition.DISAPPEARING, 100); 76524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // CHANGE_DISAPPEARING plays after DISAPPEARING 76624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100); 767ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet 76824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100); 76924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 77024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100); 77124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet // CHANGE_APPEARING plays after CHANGE_APPEARING 77224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet transition.setStartDelay(LayoutTransition.APPEARING, 100); 77324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 77424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet transition.setDuration(LayoutTransition.APPEARING, 100); 77524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 77624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet return moveView(previousParent, newParentView, childView, index, params); 77724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 77824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 77924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet @Override 78024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet public void postAnimation() { 78124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet previousParent.setLayoutTransition(null); 78224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet newParentView.setLayoutTransition(null); 78324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 78424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet }.start(); 78524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 78633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 78733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // always return success since the real status will come through the listener. 788ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(layoutParams); 789b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 790b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 79162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet Result result = moveView(previousParent, newParentView, childView, index, layoutParams); 79233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet if (result.isSuccess() == false) { 79333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet return result; 79433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 795b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 7964c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet result = render(false /*freshRender*/); 797ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet if (layoutParams != null && result.isSuccess()) { 79833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet result = result.getCopyWithData(layoutParams); 799ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet } 800ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet 801ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet return result; 802b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 803b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 80433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet /** 80533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * Moves a View from its current parent to a new given parent at a new given location, with 80633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * an optional new {@link LayoutParams} instance 80733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 80862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet * @param previousParent the previous parent, still owning the child at the time of the call. 80962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet * @param newParent the new parent 81024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet * @param movedView the view to move 81133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @param index the new location in the new parent 81233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @param params an option (can be null) {@link LayoutParams} instance. 81333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 814ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 815ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 81633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * adding views. 81733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet */ 81824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet private Result moveView(ViewGroup previousParent, final ViewGroup newParent, 81924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet final View movedView, final int index, final LayoutParams params) { 8201392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet try { 82162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // check if there is a transition on the previousParent. 82224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet LayoutTransition previousTransition = previousParent.getLayoutTransition(); 82324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet if (previousTransition != null) { 8245562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // in this case there is an animation. This means we have to wait for the child's 8255562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // parent reference to be null'ed out so that we can add it to the new parent. 8265562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // It is technically removed right before the DISAPPEARING animation is done (if 8275562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // the animation of this type is not null, otherwise it's after which is impossible 8285562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // to handle). 8295562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // Because there is no move animation, if the new parent is the same as the old 8305562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before 8315562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // adding the child or the child will appear in its new location before the 8325562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet // other children have made room for it. 83362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 83462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // add a listener to the transition to be notified of the actual removal. 83524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet previousTransition.addTransitionListener(new TransitionListener() { 83624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet private int mChangeDisappearingCount = 0; 83762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 83862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet public void startTransition(LayoutTransition transition, ViewGroup container, 83962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet View view, int transitionType) { 84024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { 84124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet mChangeDisappearingCount++; 84224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 84362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 84433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 84562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet public void endTransition(LayoutTransition transition, ViewGroup container, 84662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet View view, int transitionType) { 84724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { 84824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet mChangeDisappearingCount--; 84924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet } 85024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet 85124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING && 85224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet mChangeDisappearingCount == 0) { 85362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // add it to the parentView in the correct location 85462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet if (params != null) { 85524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet newParent.addView(movedView, index, params); 85662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } else { 85724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet newParent.addView(movedView, index); 85862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 85962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 86062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 86162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet }); 86262039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 86362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // remove the view from the current parent. 86424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet previousParent.removeView(movedView); 86562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 86662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // and return since adding the view to the new parent is done in the listener. 86762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet return SUCCESS.createResult(); 86833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } else { 86962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // standard code with no animation. pretty simple. 87024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet previousParent.removeView(movedView); 87133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 87262039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet // add it to the parentView in the correct location 87362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet if (params != null) { 87424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet newParent.addView(movedView, index, params); 87562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } else { 87624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet newParent.addView(movedView, index); 87762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 87862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet 87962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet return SUCCESS.createResult(); 88062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet } 8811392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet } catch (UnsupportedOperationException e) { 8821392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 883ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 884b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 88533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 88633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 88733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet /** 88833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * Removes a child from its current parent. 88933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * <p> 89033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 89133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 89233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 89333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 89433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 89533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @see LayoutScene#removeChild(Object, IAnimationListener) 89633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet */ 897ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result removeChild(final View childView, IAnimationListener listener) { 89833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet checkLock(); 899b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 9001392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet invalidateRenderingSize(); 9011392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet 90233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet final ViewGroup parent = (ViewGroup) childView.getParent(); 90333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 90433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet if (listener != null) { 90533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet new AnimationThread(this, "moveChild", listener) { 90633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 90733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet @Override 908ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Result preAnimation() { 90933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet parent.setLayoutTransition(new LayoutTransition()); 91033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet return removeView(parent, childView); 91133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 91233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 91333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet @Override 91433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet public void postAnimation() { 91533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet parent.setLayoutTransition(null); 91633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 91733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet }.start(); 91833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 91933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // always return success since the real status will come through the listener. 920ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(); 92133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 92233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 923ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet Result result = removeView(parent, childView); 92433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet if (result.isSuccess() == false) { 92533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet return result; 92633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 92733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 9284c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet return render(false /*freshRender*/); 929ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 930ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 931ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet /** 93233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * Removes a given view from its current parent. 93333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 93433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * @param view the view to remove from its parent 93533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * 936ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 937ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 93833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet * adding views. 93933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet */ 940ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet private Result removeView(ViewGroup parent, View view) { 94133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet try { 94233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet parent.removeView(view); 943ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return SUCCESS.createResult(); 94433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } catch (UnsupportedOperationException e) { 94533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 946ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 94733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 94833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet } 94933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet 95033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet /** 951907c716cce7b8fa785d9005081d25d3ecc2d5365Xavier Ducrohet * Returns the log associated with the session. 952907c716cce7b8fa785d9005081d25d3ecc2d5365Xavier Ducrohet * @return the log or null if there are none. 953907c716cce7b8fa785d9005081d25d3ecc2d5365Xavier Ducrohet */ 954907c716cce7b8fa785d9005081d25d3ecc2d5365Xavier Ducrohet public LayoutLog getLog() { 955907c716cce7b8fa785d9005081d25d3ecc2d5365Xavier Ducrohet if (mParams != null) { 956907c716cce7b8fa785d9005081d25d3ecc2d5365Xavier Ducrohet return mParams.getLog(); 957907c716cce7b8fa785d9005081d25d3ecc2d5365Xavier Ducrohet } 958907c716cce7b8fa785d9005081d25d3ecc2d5365Xavier Ducrohet 959907c716cce7b8fa785d9005081d25d3ecc2d5365Xavier Ducrohet return null; 960907c716cce7b8fa785d9005081d25d3ecc2d5365Xavier Ducrohet } 961907c716cce7b8fa785d9005081d25d3ecc2d5365Xavier Ducrohet 962907c716cce7b8fa785d9005081d25d3ecc2d5365Xavier Ducrohet /** 963ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * Checks that the lock is owned by the current thread and that the current context is the one 964ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * from this scene. 965ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * 966ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 967ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 968ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet */ 969ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet private void checkLock() { 970ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet ReentrantLock lock = Bridge.getLock(); 971ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (lock.isHeldByCurrentThread() == false) { 972ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet throw new IllegalStateException("scene must be acquired first. see #acquire(long)"); 973ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 974ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet if (sCurrentContext != mContext) { 975ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet throw new IllegalStateException("Thread acquired a scene but is rendering a different one"); 976ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 977ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet } 978ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet 979a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet private void findBackground(RenderResources resources) { 980a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (mParams.isBgColorOverridden() == false) { 981a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mWindowBackground = resources.findItemInTheme("windowBackground"); 982a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (mWindowBackground != null) { 983a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mWindowBackground = resources.resolveResValue(mWindowBackground); 984a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 985a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 986a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 9873bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 988a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet private boolean isTabletUi() { 989a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet return mParams.getConfigScreenSize() == ScreenSize.XLARGE; 990a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 9913bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 992a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet private boolean isHCApp() { 993a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet RenderResources resources = mContext.getRenderResources(); 994a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 995a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet // the app must say it targets 11+ and the theme name must extend Theme.Holo or 996a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet // Theme.Holo.Light (which does not extend Theme.Holo, but Theme.Light) 997a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (mParams.getTargetSdkVersion() < 11) { 998a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet return false; 999a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1000a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1001a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet StyleResourceValue currentTheme = resources.getCurrentTheme(); 1002a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet StyleResourceValue holoTheme = resources.getTheme("Theme.Holo", true /*frameworkTheme*/); 1003a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1004a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (currentTheme == holoTheme || 1005a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet resources.themeIsParentOf(holoTheme, currentTheme)) { 1006a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet return true; 1007a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1008a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1009a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet StyleResourceValue holoLightTheme = resources.getTheme("Theme.Holo.Light", 1010a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet true /*frameworkTheme*/); 1011a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1012a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (currentTheme == holoLightTheme || 1013a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet resources.themeIsParentOf(holoLightTheme, currentTheme)) { 1014a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet return true; 1015a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1016a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1017a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet return false; 1018a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1019a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1020a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet private void findStatusBar(RenderResources resources, DisplayMetrics metrics) { 1021a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (isTabletUi() == false) { 1022a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet boolean windowFullscreen = getBooleanThemeValue(resources, 1023a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet "windowFullscreen", false /*defaultValue*/); 1024a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1025a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (windowFullscreen == false) { 1026a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet // default value 1027a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT; 1028a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1029a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet // get the real value 10301b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN, 1031a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet "status_bar_height"); 1032a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1033a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (value != null) { 1034a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet TypedValue typedValue = ResourceHelper.getValue(value.getValue()); 1035a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (typedValue != null) { 1036a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet // compute the pixel value based on the display metrics 1037a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mStatusBarSize = (int)typedValue.getDimension(metrics); 1038a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1039a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1040a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1041a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1042a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1043a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1044a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet private void findTopBar(RenderResources resources, DisplayMetrics metrics) { 1045a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet boolean windowIsFloating = getBooleanThemeValue(resources, 1046a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet "windowIsFloating", true /*defaultValue*/); 1047a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1048a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (windowIsFloating == false) { 1049a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (isHCApp()) { 1050a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet findActionBar(resources, metrics); 1051a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } else { 1052a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet findTitleBar(resources, metrics); 1053a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1054a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1055a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1056a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1057a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet private void findActionBar(RenderResources resources, DisplayMetrics metrics) { 1058a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet boolean windowActionBar = getBooleanThemeValue(resources, 1059a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet "windowActionBar", true /*defaultValue*/); 1060a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1061a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet // if there's a value and it's false (default is true) 1062a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (windowActionBar) { 10633bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 10643bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // default size of the window title bar 1065a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mTopBarSize = DEFAULT_TITLE_BAR_HEIGHT; 10663bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 10673bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // get value from the theme. 1068a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet ResourceValue value = resources.findItemInTheme("actionBarSize"); 10693bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 10703bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // resolve it 1071a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet value = resources.resolveResValue(value); 10723bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 10733bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (value != null) { 10743bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // get the numerical value, if available 10753bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet TypedValue typedValue = ResourceHelper.getValue(value.getValue()); 10763bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (typedValue != null) { 10773bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // compute the pixel value based on the display metrics 1078a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mTopBarSize = (int)typedValue.getDimension(metrics); 10793bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 10803bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 10813bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 1082a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 10833bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1084a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet private void findTitleBar(RenderResources resources, DisplayMetrics metrics) { 1085a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet boolean windowNoTitle = getBooleanThemeValue(resources, 1086a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet "windowNoTitle", false /*defaultValue*/); 10873bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1088a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (windowNoTitle == false) { 1089a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1090a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet // default size of the window title bar 1091a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mTopBarSize = DEFAULT_TITLE_BAR_HEIGHT; 1092a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1093a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet // get value from the theme. 1094a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet ResourceValue value = resources.findItemInTheme("windowTitleSize"); 1095a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1096a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet // resolve it 1097a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet value = resources.resolveResValue(value); 10983bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1099a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (value != null) { 1100a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet // get the numerical value, if available 1101a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet TypedValue typedValue = ResourceHelper.getValue(value.getValue()); 1102a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (typedValue != null) { 1103a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet // compute the pixel value based on the display metrics 1104a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mTopBarSize = (int)typedValue.getDimension(metrics); 1105a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1106a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1107a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1108a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1109a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1110a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet private void findSystemBar(RenderResources resources, DisplayMetrics metrics) { 1111a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (isTabletUi() && getBooleanThemeValue( 1112a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet resources, "windowIsFloating", true /*defaultValue*/) == false) { 11133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 11143bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // default value 1115a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mSystemBarSize = 56; // ?? 11163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1117089143ffed72bb47fd8d870f29caffb646138781Xavier Ducrohet // get the real value 11181b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN, 1119a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet "status_bar_height"); 1120a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 11213bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (value != null) { 11223bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet TypedValue typedValue = ResourceHelper.getValue(value.getValue()); 11233bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (typedValue != null) { 11243bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // compute the pixel value based on the display metrics 1125a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet mSystemBarSize = (int)typedValue.getDimension(metrics); 11263bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 11273bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 1128a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1129a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1130a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1131a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet private boolean getBooleanThemeValue(RenderResources resources, 1132a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet String name, boolean defaultValue) { 1133a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1134a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet // get the title bar flag from the current theme. 1135a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet ResourceValue value = resources.findItemInTheme(name); 1136a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1137a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet // because it may reference something else, we resolve it. 1138a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet value = resources.resolveResValue(value); 11393bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1140a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet // if there's no value, return the default. 1141a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet if (value == null || value.getValue() == null) { 1142a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet return defaultValue; 11433bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 11443bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1145a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet return XmlUtils.convertValueToBoolean(value.getValue(), defaultValue); 11463bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 11473bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 11483bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 11493bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Post process on a view hierachy that was just inflated. 11503bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * <p/>At the moment this only support TabHost: If {@link TabHost} is detected, look for the 11513bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically 11523bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * based on the content of the {@link FrameLayout}. 11533bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * @param view the root view to process. 11543bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * @param projectCallback callback to the project. 11553bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 11563bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private void postInflateProcess(View view, IProjectCallback projectCallback) 11573bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet throws PostInflateException { 11583bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (view instanceof TabHost) { 11593bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet setupTabHost((TabHost)view, projectCallback); 116062c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohet } else if (view instanceof QuickContactBadge) { 116162c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohet QuickContactBadge badge = (QuickContactBadge) view; 116262c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohet badge.setImageToDefault(); 11633bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } else if (view instanceof ViewGroup) { 11643bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet ViewGroup group = (ViewGroup)view; 11653bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet final int count = group.getChildCount(); 11663bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet for (int c = 0 ; c < count ; c++) { 11673bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet View child = group.getChildAt(c); 11683bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet postInflateProcess(child, projectCallback); 11693bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 11703bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 11713bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 11723bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 11733bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 11743bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Sets up a {@link TabHost} object. 11753bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * @param tabHost the TabHost to setup. 11763bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * @param projectCallback The project callback object to access the project R class. 11773bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * @throws PostInflateException 11783bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 11793bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet private void setupTabHost(TabHost tabHost, IProjectCallback projectCallback) 11803bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet throws PostInflateException { 11813bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // look for the TabWidget, and the FrameLayout. They have their own specific names 11823bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet View v = tabHost.findViewById(android.R.id.tabs); 11833bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 11843bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (v == null) { 11853bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet throw new PostInflateException( 11863bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet "TabHost requires a TabWidget with id \"android:id/tabs\".\n"); 11873bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 11883bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 11893bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if ((v instanceof TabWidget) == false) { 11903bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet throw new PostInflateException(String.format( 11913bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet "TabHost requires a TabWidget with id \"android:id/tabs\".\n" + 11923bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName())); 11933bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 11943bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 11953bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet v = tabHost.findViewById(android.R.id.tabcontent); 11963bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 11973bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (v == null) { 11983bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // TODO: see if we can fake tabs even without the FrameLayout (same below when the framelayout is empty) 11993bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet throw new PostInflateException( 12003bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet "TabHost requires a FrameLayout with id \"android:id/tabcontent\"."); 12013bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 12023bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 12033bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if ((v instanceof FrameLayout) == false) { 12043bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet throw new PostInflateException(String.format( 12053bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" + 12063bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName())); 12073bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 12083bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 12093bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet FrameLayout content = (FrameLayout)v; 12103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 12113bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // now process the content of the framelayout and dynamically create tabs for it. 12123bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet final int count = content.getChildCount(); 12133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 12143bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // this must be called before addTab() so that the TabHost searches its TabWidget 12153bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet // and FrameLayout. 12163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet tabHost.setup(); 12173bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1218f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye if (count == 0) { 1219f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye // Create a dummy child to get a single tab 1220f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye TabSpec spec = tabHost.newTabSpec("tag").setIndicator("Tab Label", 1221f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye tabHost.getResources().getDrawable(android.R.drawable.ic_menu_info_details)) 1222f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye .setContent(new TabHost.TabContentFactory() { 1223f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye public View createTabContent(String tag) { 1224f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye return new LinearLayout(mContext); 1225f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye } 1226f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye }); 1227f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye tabHost.addTab(spec); 1228f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye return; 1229f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye } else { 1230f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye // for each child of the framelayout, add a new TabSpec 1231f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye for (int i = 0 ; i < count ; i++) { 1232f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye View child = content.getChildAt(i); 1233f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye String tabSpec = String.format("tab_spec%d", i+1); 1234f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye int id = child.getId(); 1235947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohet Pair<ResourceType, String> resource = projectCallback.resolveResourceId(id); 1236f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye String name; 1237f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye if (resource != null) { 1238947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohet name = resource.getSecond(); 1239f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye } else { 1240f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye name = String.format("Tab %d", i+1); // default name if id is unresolved. 1241f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye } 1242f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id)); 12433bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 12443bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 12453bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 12463bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 12473bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 12483bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet /** 12493bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Visits a View and its children and generate a {@link ViewInfo} containing the 12503bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * bounds of all the views. 12513bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * @param view the root View 12523bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * @param context the context. 12533bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */ 1254a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet private ViewInfo visit(View view, BridgeContext context, int offset) { 12553bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (view == null) { 12563bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet return null; 12573bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 12583bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 12593bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet ViewInfo result = new ViewInfo(view.getClass().getName(), 12603bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet context.getViewKey(view), 1261a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet view.getLeft(), view.getTop() + offset, view.getRight(), view.getBottom() + offset, 12622d240967c9bc38cbf69967457b33f953f8826e96Xavier Ducrohet view, view.getLayoutParams()); 12633bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 12643bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet if (view instanceof ViewGroup) { 12653bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet ViewGroup group = ((ViewGroup) view); 1266a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet result.setChildren(visitAllChildren(group, context, 0 /*offset*/)); 12673bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 12683bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 12693bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet return result; 12703bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 12713bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1272a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, BridgeContext context, 1273a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet int offset) { 1274e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet if (viewGroup == null) { 1275e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet return null; 1276e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet } 1277e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet 1278e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet List<ViewInfo> children = new ArrayList<ViewInfo>(); 1279e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet for (int i = 0; i < viewGroup.getChildCount(); i++) { 1280a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet children.add(visit(viewGroup.getChildAt(i), context, offset)); 1281e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet } 1282e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet return children; 1283e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet } 1284e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet 1285e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet 12861392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet private void invalidateRenderingSize() { 12871392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet mMeasuredScreenWidth = mMeasuredScreenHeight = -1; 12881392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet } 12891392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet 12903bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet public BufferedImage getImage() { 12913bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet return mImage; 12923bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 12933bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet 1294a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet public boolean isAlphaChannelImage() { 1295a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet return mIsAlphaChannelImage; 1296a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet } 1297a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet 1298e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet public List<ViewInfo> getViewInfos() { 1299e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet return mViewInfoList; 13003bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet } 13012d240967c9bc38cbf69967457b33f953f8826e96Xavier Ducrohet 1302ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public Map<String, String> getDefaultProperties(Object viewObject) { 13032d240967c9bc38cbf69967457b33f953f8826e96Xavier Ducrohet return mContext.getDefaultPropMap(viewObject); 13042d240967c9bc38cbf69967457b33f953f8826e96Xavier Ducrohet } 1305b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 1306ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public void setScene(RenderSession session) { 1307ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet mScene = session; 1308b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 1309b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet 1310ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet public RenderSession getSession() { 1311b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet return mScene; 1312b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet } 13130d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet 13140d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet // --- FrameworkResourceIdProvider methods 13150d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet 13160d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet @Override 13171b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet public Integer getId(ResourceType resType, String resName) { 1318947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohet return Bridge.getResourceId(resType, resName); 13190d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohet } 13203bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet} 1321