RenderSessionImpl.java revision 16584225125acba18b74920b902c798dfead0328
1c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet/* 2c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Copyright (C) 2010 The Android Open Source Project 3c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * 4c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License"); 5c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * you may not use this file except in compliance with the License. 6c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * You may obtain a copy of the License at 7c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * 8c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * http://www.apache.org/licenses/LICENSE-2.0 9c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * 10c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Unless required by applicable law or agreed to in writing, software 11c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS, 12c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * See the License for the specific language governing permissions and 14c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * limitations under the License. 15c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 16c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 17c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetpackage com.android.layoutlib.bridge.impl; 18c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_ANIM_NOT_FOUND; 2019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_INFLATION; 2119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_LOCK_INTERRUPTED; 2219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLATED; 2319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_TIMEOUT; 2419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; 2519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP_NO_CHILDREN; 2619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.SUCCESS; 2719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet 2819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.IAnimationListener; 2919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.ILayoutPullParser; 3019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.IProjectCallback; 31d7cc1244d7f0901688545c8535fa531fbb68669aXavier Ducrohetimport com.android.ide.common.rendering.api.LayoutLog; 3219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.Params; 3370552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderResources; 3419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderSession; 3519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.ResourceValue; 3619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.Result; 3719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.StyleResourceValue; 3819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.ViewInfo; 3919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.Params.RenderingMode; 4070552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderResources.FrameworkResourceIdProvider; 4119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.Result.Status; 42c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.internal.util.XmlUtils; 432eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohetimport com.android.layoutlib.bridge.Bridge; 44c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeContext; 45c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeInflater; 4601811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes; 47c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeWindow; 48c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeWindowSession; 49c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeXmlBlockParser; 5016584225125acba18b74920b902c798dfead0328Xavier Ducrohetimport com.android.resources.Density; 5116584225125acba18b74920b902c798dfead0328Xavier Ducrohetimport com.android.resources.ScreenSize; 52c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 53e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohetimport android.animation.Animator; 542eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohetimport android.animation.AnimatorInflater; 55e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohetimport android.animation.LayoutTransition; 562b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohetimport android.animation.LayoutTransition.TransitionListener; 57c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.app.Fragment_Delegate; 58c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Bitmap; 59c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Bitmap_Delegate; 60c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Canvas; 61c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.drawable.Drawable; 62c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.os.Handler; 63c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.util.DisplayMetrics; 64c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.util.TypedValue; 65c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.View; 66c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.ViewGroup; 67c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.View.AttachInfo; 68c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.View.MeasureSpec; 6901811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohetimport android.view.ViewGroup.LayoutParams; 70c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.widget.FrameLayout; 71796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbyeimport android.widget.LinearLayout; 7231fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohetimport android.widget.QuickContactBadge; 73c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.widget.TabHost; 74c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.widget.TabWidget; 75796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbyeimport android.widget.TabHost.TabSpec; 76c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 775a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohetimport java.awt.AlphaComposite; 78c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.Color; 79c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.Graphics2D; 80c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.image.BufferedImage; 81c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.ArrayList; 82c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.List; 83c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.Map; 842eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohetimport java.util.concurrent.TimeUnit; 852eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohetimport java.util.concurrent.locks.ReentrantLock; 86c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 87c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet/** 8819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * Class implementing the render session. 89c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * 9019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * A session is a stateful representation of a layout file. It is initialized with data coming 9119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then 92c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * be done on the layout. 93c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * 94c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 9570552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohetpublic class RenderSessionImpl extends FrameworkResourceIdProvider { 96c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 97c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private static final int DEFAULT_TITLE_BAR_HEIGHT = 25; 98c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private static final int DEFAULT_STATUS_BAR_HEIGHT = 25; 99c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1002eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet /** 1012eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * The current context being rendered. This is set through {@link #acquire(long)} and 1022eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #init(long)}, and unset in {@link #release()}. 1032eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet */ 1042eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet private static BridgeContext sCurrentContext = null; 1052eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 10619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private final Params mParams; 107c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 108c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // scene state 10919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private RenderSession mScene; 110c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private BridgeContext mContext; 111c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private BridgeXmlBlockParser mBlockParser; 112c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private BridgeInflater mInflater; 113ffb42f6c5043de226f02318a1311669d35a90711Xavier Ducrohet private ResourceValue mWindowBackground; 114c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private FrameLayout mViewRoot; 1159eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private Canvas mCanvas; 1169eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private int mMeasuredScreenWidth = -1; 1179eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private int mMeasuredScreenHeight = -1; 11816584225125acba18b74920b902c798dfead0328Xavier Ducrohet private boolean mIsAlphaChannelImage = true; 11916584225125acba18b74920b902c798dfead0328Xavier Ducrohet 12016584225125acba18b74920b902c798dfead0328Xavier Ducrohet private int mStatusBarSize; 12116584225125acba18b74920b902c798dfead0328Xavier Ducrohet private int mTopBarSize; 12216584225125acba18b74920b902c798dfead0328Xavier Ducrohet private int mSystemBarSize; 12316584225125acba18b74920b902c798dfead0328Xavier Ducrohet private int mTopOffset; 12416584225125acba18b74920b902c798dfead0328Xavier Ducrohet private int mTotalBarSize; 12516584225125acba18b74920b902c798dfead0328Xavier Ducrohet 126c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 127c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // information being returned through the API 128c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private BufferedImage mImage; 1297d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet private List<ViewInfo> mViewInfoList; 130c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 131c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private static final class PostInflateException extends Exception { 132c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private static final long serialVersionUID = 1L; 133c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 134c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet public PostInflateException(String message) { 135c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet super(message); 136c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 137c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 138c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 139c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 140c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Creates a layout scene with all the information coming from the layout bridge API. 141c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p> 14219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init()}, which act as a 14319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * call to {@link RenderSessionImpl#acquire(long)} 144c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * 145c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @see LayoutBridge#createScene(com.android.layoutlib.api.SceneParams) 146c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 14719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public RenderSessionImpl(Params params) { 148c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // copy the params. 14919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet mParams = new Params(params); 1502eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 1512eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 1522eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet /** 1532eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * Initializes and acquires the scene, creating various Android objects such as context, 1542eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * inflater, and parser. 1552eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 1562eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @param timeout the time to wait if another rendering is happening. 1572eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 1582eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @return whether the scene was prepared 1592eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 1602eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @see #acquire(long) 1612eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @see #release() 1622eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet */ 16319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result init(long timeout) { 1642eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet // acquire the lock. if the result is null, lock was just acquired, otherwise, return 1652eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet // the result. 16619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet Result result = acquireLock(timeout); 1672eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (result != null) { 1682eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet return result; 1692eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 170c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 171c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // setup the display Metrics. 172c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet DisplayMetrics metrics = new DisplayMetrics(); 173c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet metrics.densityDpi = mParams.getDensity(); 174c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet metrics.density = mParams.getDensity() / (float) DisplayMetrics.DENSITY_DEFAULT; 175c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet metrics.scaledDensity = metrics.density; 176c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet metrics.widthPixels = mParams.getScreenWidth(); 177c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet metrics.heightPixels = mParams.getScreenHeight(); 178c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet metrics.xdpi = mParams.getXdpi(); 179c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet metrics.ydpi = mParams.getYdpi(); 180c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 18170552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet RenderResources resources = mParams.getResources(); 182c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 183c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // build the context 18470552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet mContext = new BridgeContext(mParams.getProjectKey(), metrics, resources, 1859d0577ec0c285c055da4c910dcb597fdae5bc5e5Xavier Ducrohet mParams.getProjectCallback(), mParams.getTargetSdkVersion()); 186c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 18716584225125acba18b74920b902c798dfead0328Xavier Ducrohet // use default of true in case it's not found to use alpha by default 18816584225125acba18b74920b902c798dfead0328Xavier Ducrohet mIsAlphaChannelImage = getBooleanThemeValue(resources, 18916584225125acba18b74920b902c798dfead0328Xavier Ducrohet "windowIsFloating", true /*defaultValue*/); 19016584225125acba18b74920b902c798dfead0328Xavier Ducrohet 1912eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 19270552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet setUp(); 193c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 19416584225125acba18b74920b902c798dfead0328Xavier Ducrohet findBackground(resources); 19516584225125acba18b74920b902c798dfead0328Xavier Ducrohet findStatusBar(resources, metrics); 19616584225125acba18b74920b902c798dfead0328Xavier Ducrohet findTopBar(resources, metrics); 19716584225125acba18b74920b902c798dfead0328Xavier Ducrohet findSystemBar(resources, metrics); 198c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 19916584225125acba18b74920b902c798dfead0328Xavier Ducrohet mTopOffset = mStatusBarSize + mTopBarSize; 20016584225125acba18b74920b902c798dfead0328Xavier Ducrohet mTotalBarSize = mTopOffset + mSystemBarSize; 201c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 202c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // build the inflater and parser. 203c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet mInflater = new BridgeInflater(mContext, mParams.getProjectCallback()); 204c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet mContext.setBridgeInflater(mInflater); 205c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet mInflater.setFactory2(mContext); 206c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 207c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet mBlockParser = new BridgeXmlBlockParser(mParams.getLayoutDescription(), 208c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet mContext, false /* platformResourceFlag */); 2092eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 21019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 211c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 212c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 213c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 2142eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * Prepares the scene for action. 2152eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * <p> 2162eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * This call is blocking if another rendering/inflating is currently happening, and will return 2172eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * whether the preparation worked. 2182eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 2192eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * The preparation can fail if another rendering took too long and the timeout was elapsed. 2202eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 2212eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * More than one call to this from the same thread will have no effect and will return 22219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Result#SUCCESS}. 2232eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 2242eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * After scene actions have taken place, only one call to {@link #release()} must be 2252eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * done. 2262eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 2272eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @param timeout the time to wait if another rendering is happening. 2282eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 2292eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @return whether the scene was prepared 2302eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 2312eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @see #release() 2322eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 2332eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if {@link #init(long)} was never called. 2342eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet */ 23519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result acquire(long timeout) { 2362eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (mContext == null) { 2372eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet throw new IllegalStateException("After scene creation, #init() must be called"); 2382eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 2392eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 2402eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet // acquire the lock. if the result is null, lock was just acquired, otherwise, return 2412eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet // the result. 24219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet Result result = acquireLock(timeout); 2432eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (result != null) { 2442eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet return result; 2452eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 246c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 24770552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet setUp(); 2482eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 249168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet return SUCCESS.createResult(); 250c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 251c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 252c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 2532eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * Acquire the lock so that the scene can be acted upon. 254c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p> 2552eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * This returns null if the lock was just acquired, otherwise it returns 25619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Result#SUCCESS} if the lock already belonged to that thread, or another 25719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * instance (see {@link Result#getStatus()}) if an error occurred. 2582eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 2592eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @param timeout the time to wait if another rendering is happening. 2602eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @return null if the lock was just acquire or another result depending on the state. 2612eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 2622eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 2632eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene. 264c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 26519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private Result acquireLock(long timeout) { 2662eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet ReentrantLock lock = Bridge.getLock(); 2672eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (lock.isHeldByCurrentThread() == false) { 2682eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet try { 2692eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet boolean acquired = lock.tryLock(timeout, TimeUnit.MILLISECONDS); 2702eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 2712eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (acquired == false) { 272168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet return ERROR_TIMEOUT.createResult(); 2732eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 2742eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } catch (InterruptedException e) { 275168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet return ERROR_LOCK_INTERRUPTED.createResult(); 2762eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 2772eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } else { 2782eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet // This thread holds the lock already. Checks that this wasn't for a different context. 2792eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet // If this is called by init, mContext will be null and so should sCurrentContext 2802eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet // anyway 2812eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (mContext != sCurrentContext) { 2822eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet throw new IllegalStateException("Acquiring different scenes from same thread without releases"); 2832eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 284168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet return SUCCESS.createResult(); 2852eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 286c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 2872eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet return null; 2882eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 2892eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 2902eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet /** 2912eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * Cleans up the scene after an action. 2922eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet */ 2932eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet public void release() { 2942eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet ReentrantLock lock = Bridge.getLock(); 2952eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 2962eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet // with the use of finally blocks, it is possible to find ourself calling this 2972eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet // without a successful call to prepareScene. This test makes sure that unlock() will 2982eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet // not throw IllegalMonitorStateException. 2992eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (lock.isHeldByCurrentThread()) { 30070552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet tearDown(); 3012eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet lock.unlock(); 3022eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 303c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 304c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 305c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 30670552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet * Sets up the session for rendering. 30770552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet * <p/> 30870552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet * The counterpart is {@link #tearDown()}. 30970552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet */ 31070552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet private void setUp() { 31170552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet // make sure the Resources object references the context (and other objects) for this 31270552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet // scene 31370552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet mContext.initResources(); 31470552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet sCurrentContext = mContext; 31570552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet 31670552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet LayoutLog currentLog = mParams.getLog(); 31770552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet Bridge.setLog(currentLog); 31870552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet mContext.getRenderResources().setFrameworkResourceIdProvider(this); 31970552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet mContext.getRenderResources().setLogger(currentLog); 32070552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet } 32170552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet 32270552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet /** 32370552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet * Tear down the session after rendering. 32470552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet * <p/> 32570552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet * The counterpart is {@link #setUp()}. 32670552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet */ 32770552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet private void tearDown() { 32870552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet // Make sure to remove static references, otherwise we could not unload the lib 32970552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet mContext.disposeResources(); 33070552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet sCurrentContext = null; 33170552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet 33270552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet Bridge.setLog(null); 33370552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet mContext.getRenderResources().setFrameworkResourceIdProvider(null); 33470552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet mContext.getRenderResources().setLogger(null); 33570552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet 33670552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet } 33770552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet 33870552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet /** 339c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Inflates the layout. 340c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p> 3412eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 3422eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 3432eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 3442eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #init(long)} was not called. 345c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 34619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result inflate() { 3472eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet checkLock(); 3482eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 349c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet try { 350c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 351c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet mViewRoot = new FrameLayout(mContext); 352c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 353c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // Sets the project callback (custom view loader) to the fragment delegate so that 354c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // it can instantiate the custom Fragment. 355c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet Fragment_Delegate.setProjectCallback(mParams.getProjectCallback()); 356c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 357c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet View view = mInflater.inflate(mBlockParser, mViewRoot); 358c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 359c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // post-inflate process. For now this supports TabHost/TabWidget 360c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet postInflateProcess(view, mParams.getProjectCallback()); 361c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 362c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet Fragment_Delegate.setProjectCallback(null); 363c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 364c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // set the AttachInfo on the root view. 365c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet AttachInfo info = new AttachInfo(new BridgeWindowSession(), new BridgeWindow(), 366c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet new Handler(), null); 367c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet info.mHasWindowFocus = true; 368c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet info.mWindowVisibility = View.VISIBLE; 369c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet info.mInTouchMode = false; // this is so that we can display selections. 37046a329244db12b6f7afc3c9a6409d420241a1058Xavier Ducrohet info.mHardwareAccelerated = false; 371c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet mViewRoot.dispatchAttachedToWindow(info, 0); 372c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 373c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get the background drawable 374c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (mWindowBackground != null) { 375c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet Drawable d = ResourceHelper.getDrawable(mWindowBackground, 376c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet mContext, true /* isFramework */); 377c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet mViewRoot.setBackgroundDrawable(d); 378c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 379c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 38019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 381c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (PostInflateException e) { 38219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_INFLATION.createResult(e.getMessage(), e); 383c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (Throwable e) { 384c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get the real cause of the exception. 385c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet Throwable t = e; 386c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet while (t.getCause() != null) { 387c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet t = t.getCause(); 388c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 389c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 39019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_INFLATION.createResult(t.getMessage(), t); 391c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 392c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 393c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 394c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 395c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Renders the scene. 396c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p> 3972eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 3982eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 3995a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * @param freshRender whether the render is a new one and should erase the existing bitmap (in 4005a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * the case where bitmaps are reused). This is typically needed when not playing 4015a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * animations.) 4025a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * 4032eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 4042eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 4059eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet * 4069eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet * @see SceneParams#getRenderingMode() 407e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @see LayoutScene#render(long) 408c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 4095a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet public Result render(boolean freshRender) { 4102eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet checkLock(); 4112eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 412c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet try { 413c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (mViewRoot == null) { 41419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_NOT_INFLATED.createResult(); 415c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 416c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // measure the views 417c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet int w_spec, h_spec; 418c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 419fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet RenderingMode renderingMode = mParams.getRenderingMode(); 420fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet 4219eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // only do the screen measure when needed. 4229eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet boolean newRenderSize = false; 4239eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (mMeasuredScreenWidth == -1) { 4249eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet newRenderSize = true; 4259eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet mMeasuredScreenWidth = mParams.getScreenWidth(); 42616584225125acba18b74920b902c798dfead0328Xavier Ducrohet mMeasuredScreenHeight = mParams.getScreenHeight() - mTotalBarSize; 4279eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 4289eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (renderingMode != RenderingMode.NORMAL) { 4299eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // measure the full size needed by the layout. 4309eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet w_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenWidth, 4319eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet renderingMode.isHorizExpand() ? 4329eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet MeasureSpec.UNSPECIFIED // this lets us know the actual needed size 4339eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet : MeasureSpec.EXACTLY); 43416584225125acba18b74920b902c798dfead0328Xavier Ducrohet h_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenHeight, 4359eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet renderingMode.isVertExpand() ? 4369eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet MeasureSpec.UNSPECIFIED // this lets us know the actual needed size 4379eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet : MeasureSpec.EXACTLY); 4389eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet mViewRoot.measure(w_spec, h_spec); 4399eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 4409eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (renderingMode.isHorizExpand()) { 4419eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet int neededWidth = mViewRoot.getChildAt(0).getMeasuredWidth(); 4429eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (neededWidth > mMeasuredScreenWidth) { 4439eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet mMeasuredScreenWidth = neededWidth; 4449eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 445fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet } 446c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 4479eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (renderingMode.isVertExpand()) { 4489eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet int neededHeight = mViewRoot.getChildAt(0).getMeasuredHeight(); 44916584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (neededHeight > mMeasuredScreenHeight) { 45016584225125acba18b74920b902c798dfead0328Xavier Ducrohet mMeasuredScreenHeight = neededHeight; 4519eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 452fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet } 453c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 454c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 455c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 456c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // remeasure with the size we need 457c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // This must always be done before the call to layout 4589eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet w_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenWidth, MeasureSpec.EXACTLY); 45916584225125acba18b74920b902c798dfead0328Xavier Ducrohet h_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenHeight, 460c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet MeasureSpec.EXACTLY); 461c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet mViewRoot.measure(w_spec, h_spec); 462c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 463c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // now do the layout. 46416584225125acba18b74920b902c798dfead0328Xavier Ducrohet mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); 465c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 466c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // draw the views 467c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // create the BufferedImage into which the layout will be rendered. 4685a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet boolean newImage = false; 4699eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (newRenderSize || mCanvas == null) { 4709eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (mParams.getImageFactory() != null) { 47116584225125acba18b74920b902c798dfead0328Xavier Ducrohet mImage = mParams.getImageFactory().getImage( 47216584225125acba18b74920b902c798dfead0328Xavier Ducrohet mMeasuredScreenWidth, 47316584225125acba18b74920b902c798dfead0328Xavier Ducrohet mMeasuredScreenHeight + mTotalBarSize); 4749eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } else { 47516584225125acba18b74920b902c798dfead0328Xavier Ducrohet mImage = new BufferedImage( 47616584225125acba18b74920b902c798dfead0328Xavier Ducrohet mMeasuredScreenWidth, 47716584225125acba18b74920b902c798dfead0328Xavier Ducrohet mMeasuredScreenHeight + mTotalBarSize, 47816584225125acba18b74920b902c798dfead0328Xavier Ducrohet BufferedImage.TYPE_INT_ARGB); 4795a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet newImage = true; 4809eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 481c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 48219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet if (mParams.isBgColorOverridden()) { 4835a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet // since we override the content, it's the same as if it was a new image. 4845a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet newImage = true; 4859eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet Graphics2D gc = mImage.createGraphics(); 48619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet gc.setColor(new Color(mParams.getOverrideBgColor(), true)); 4875a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet gc.setComposite(AlphaComposite.Src); 48816584225125acba18b74920b902c798dfead0328Xavier Ducrohet gc.fillRect(0, 0, mMeasuredScreenWidth, 48916584225125acba18b74920b902c798dfead0328Xavier Ducrohet mMeasuredScreenHeight + mTotalBarSize); 4909eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet gc.dispose(); 4919eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 492c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 4939eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // create an Android bitmap around the BufferedImage 4949eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage, 4959eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet true /*isMutable*/, 49616584225125acba18b74920b902c798dfead0328Xavier Ducrohet Density.getEnum(mParams.getDensity())); 497c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 4989eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // create a Canvas around the Android bitmap 4999eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet mCanvas = new Canvas(bitmap); 5009eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet mCanvas.setDensity(mParams.getDensity()); 50116584225125acba18b74920b902c798dfead0328Xavier Ducrohet mCanvas.translate(0, mTopOffset); 5029eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 503c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 5045a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet if (freshRender && newImage == false) { 5055a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet Graphics2D gc = mImage.createGraphics(); 5065a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet gc.setComposite(AlphaComposite.Src); 50716584225125acba18b74920b902c798dfead0328Xavier Ducrohet 50816584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (mStatusBarSize > 0) { 50916584225125acba18b74920b902c798dfead0328Xavier Ducrohet gc.setColor(new Color(0xFF3C3C3C, true)); 51016584225125acba18b74920b902c798dfead0328Xavier Ducrohet gc.fillRect(0, 0, mMeasuredScreenWidth, mStatusBarSize); 51116584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 51216584225125acba18b74920b902c798dfead0328Xavier Ducrohet 51316584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (mTopBarSize > 0) { 51416584225125acba18b74920b902c798dfead0328Xavier Ducrohet gc.setColor(new Color(0xFF7F7F7F, true)); 51516584225125acba18b74920b902c798dfead0328Xavier Ducrohet gc.fillRect(0, mStatusBarSize, mMeasuredScreenWidth, mTopOffset); 51616584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 51716584225125acba18b74920b902c798dfead0328Xavier Ducrohet 51816584225125acba18b74920b902c798dfead0328Xavier Ducrohet // erase the rest 51916584225125acba18b74920b902c798dfead0328Xavier Ducrohet gc.setColor(new Color(0x00000000, true)); 52016584225125acba18b74920b902c798dfead0328Xavier Ducrohet gc.fillRect(0, mTopOffset, 52116584225125acba18b74920b902c798dfead0328Xavier Ducrohet mMeasuredScreenWidth, mMeasuredScreenHeight + mTopOffset); 52216584225125acba18b74920b902c798dfead0328Xavier Ducrohet 52316584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (mSystemBarSize > 0) { 52416584225125acba18b74920b902c798dfead0328Xavier Ducrohet gc.setColor(new Color(0xFF3C3C3C, true)); 52516584225125acba18b74920b902c798dfead0328Xavier Ducrohet gc.fillRect(0, mMeasuredScreenHeight + mTopOffset, 52616584225125acba18b74920b902c798dfead0328Xavier Ducrohet mMeasuredScreenWidth, mMeasuredScreenHeight + mTotalBarSize); 52716584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 52816584225125acba18b74920b902c798dfead0328Xavier Ducrohet 52916584225125acba18b74920b902c798dfead0328Xavier Ducrohet // done 5305a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet gc.dispose(); 5315a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet } 5325a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet 5339eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet mViewRoot.draw(mCanvas); 5349eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 53516584225125acba18b74920b902c798dfead0328Xavier Ducrohet mViewInfoList = visitAllChildren((ViewGroup)mViewRoot, mContext, mTopOffset); 536c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 537c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // success! 53819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 539c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (Throwable e) { 540c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get the real cause of the exception. 541c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet Throwable t = e; 542c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet while (t.getCause() != null) { 543c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet t = t.getCause(); 544c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 545c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 54619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_UNKNOWN.createResult(t.getMessage(), t); 547c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 548c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 549c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 550c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 5512eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * Animate an object 5522eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * <p> 5532eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 5542eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 5552eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 5562eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 557e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 558e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @see LayoutScene#animate(Object, String, boolean, IAnimationListener) 5592eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet */ 56019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result animate(Object targetObject, String animationName, 5612eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet boolean isFrameworkAnimation, IAnimationListener listener) { 5622eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet checkLock(); 5632eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 5642eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet // find the animation file. 565ffb42f6c5043de226f02318a1311669d35a90711Xavier Ducrohet ResourceValue animationResource = null; 5662eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet int animationId = 0; 5672eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (isFrameworkAnimation) { 56870552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet animationResource = mContext.getRenderResources().getFrameworkResource( 56970552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet RenderResources.RES_ANIMATOR, animationName); 5702eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 57170552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet animationId = Bridge.getResourceValue(RenderResources.RES_ANIMATOR, 572eb87b3bb53a8a9e9a246b4b70ea40172e2229c85Xavier Ducrohet animationName); 5732eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5742eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } else { 57570552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet animationResource = mContext.getRenderResources().getProjectResource( 57670552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet RenderResources.RES_ANIMATOR, animationName); 5772eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 578eb87b3bb53a8a9e9a246b4b70ea40172e2229c85Xavier Ducrohet animationId = mContext.getProjectCallback().getResourceValue( 57970552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet RenderResources.RES_ANIMATOR, animationName); 5802eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5812eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5822eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 5832eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 5842eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet try { 585e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet Animator anim = AnimatorInflater.loadAnimator(mContext, animationId); 5862eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (anim != null) { 5872eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet anim.setTarget(targetObject); 5882eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 589e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new PlayAnimationThread(anim, this, animationName, listener).start(); 5902eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 59119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 5922eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5932eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } catch (Exception e) { 594c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // get the real cause of the exception. 595c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet Throwable t = e; 596c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet while (t.getCause() != null) { 597c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet t = t.getCause(); 598c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 599c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 60019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_UNKNOWN.createResult(t.getMessage(), t); 6012eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 6022eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 6032eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 60419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_ANIM_NOT_FOUND.createResult(); 605c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 606c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 607e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 608e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Insert a new child into an existing parent. 609e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 610e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 611e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 612e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 613e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 614e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 61519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @see LayoutScene#insertChild(Object, ILayoutPullParser, int, IAnimationListener) 616e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 61719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml, 618e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final int index, IAnimationListener listener) { 619c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet checkLock(); 620c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 621c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // create a block parser for the XML 622c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(childXml, mContext, 623c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet false /* platformResourceFlag */); 624c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 625c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // inflate the child without adding it to the root since we want to control where it'll 626c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // get added. We do pass the parentView however to ensure that the layoutParams will 627c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // be created correctly. 628e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/); 629c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 630e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet invalidateRenderingSize(); 631e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 632e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 633e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new AnimationThread(this, "insertChild", listener) { 634e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 635e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 63619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result preAnimation() { 637e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parentView.setLayoutTransition(new LayoutTransition()); 638e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return addView(parentView, child, index); 639e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 640e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 641e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 642e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet public void postAnimation() { 643e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parentView.setLayoutTransition(null); 644e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 645e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet }.start(); 646e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 647e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 64819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(child); 6499eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 6509eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 651e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // add it to the parentView in the correct location 65219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet Result result = addView(parentView, child, index); 653e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (result.isSuccess() == false) { 654e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 655e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 656c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 6575a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 658c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet if (result.isSuccess()) { 659e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet result = result.getCopyWithData(child); 660c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet } 661c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet 662c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet return result; 663c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 664c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 665e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 666e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Adds a given view to a given parent at a given index. 667e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 668e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param parent the parent to receive the view 669e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param view the view to add to the parent 670e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param index the index where to do the add. 671e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 67219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 67319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 674e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 675e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 67619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private Result addView(ViewGroup parent, View view, int index) { 677e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet try { 678e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.addView(view, index); 67919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 680e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } catch (UnsupportedOperationException e) { 681e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 68219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 683e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 684e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 685e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 686e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 687e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Moves a view to a new parent at a given location 688e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 689e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 690e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 691e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 692e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 693e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 694e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @see LayoutScene#moveChild(Object, Object, int, Map, IAnimationListener) 695e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 6962b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public Result moveChild(final ViewGroup newParentView, final View childView, final int index, 697479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet Map<String, String> layoutParamsMap, final IAnimationListener listener) { 698c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet checkLock(); 699c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 700e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet invalidateRenderingSize(); 701e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 70201811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet LayoutParams layoutParams = null; 703e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (layoutParamsMap != null) { 704e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // need to create a new LayoutParams object for the new parent. 7052b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet layoutParams = newParentView.generateLayoutParams( 706e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new BridgeLayoutParamsMapAttributes(layoutParamsMap)); 707e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 7089eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 7092b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // get the current parent of the view that needs to be moved. 7102b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet final ViewGroup previousParent = (ViewGroup) childView.getParent(); 7112b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 712e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 713e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final LayoutParams params = layoutParams; 71401811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 715479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // there is no support for animating views across layouts, so in case the new and old 716479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // parent views are different we fake the animation through a no animation thread. 717479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (previousParent != newParentView) { 718479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet new Thread("not animated moveChild") { 719479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 720479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public void run() { 721479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet Result result = moveView(previousParent, newParentView, childView, index, 722479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet params); 723479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (result.isSuccess() == false) { 724479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 725479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 726479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 727479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // ready to do the work, acquire the scene. 728479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet result = acquire(250); 729479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (result.isSuccess() == false) { 730479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 731479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet return; 732479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 733479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 734479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet try { 7355a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 736479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (result.isSuccess()) { 737479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.onNewFrame(RenderSessionImpl.this.getSession()); 738479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 739479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } finally { 740479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet release(); 741479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 742479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 743479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 7442b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 745479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet }.start(); 746479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } else { 747479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet new AnimationThread(this, "moveChild", listener) { 7482b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 749479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 750479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public Result preAnimation() { 751479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // set up the transition for the parent. 752479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet LayoutTransition transition = new LayoutTransition(); 753479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.setLayoutTransition(transition); 7547550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet 755479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // tweak the animation durations and start delays (to match the duration of 756479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // animation playing just before). 757479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // Note: Cannot user Animation.setDuration() directly. Have to set it 758479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // on the LayoutTransition. 759479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.DISAPPEARING, 100); 760479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // CHANGE_DISAPPEARING plays after DISAPPEARING 761479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100); 76201811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 763479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100); 764479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 765479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100); 766479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // CHANGE_APPEARING plays after CHANGE_APPEARING 767479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setStartDelay(LayoutTransition.APPEARING, 100); 768479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 769479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.APPEARING, 100); 770479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 771479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet return moveView(previousParent, newParentView, childView, index, params); 772479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 773479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 774479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 775479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public void postAnimation() { 776479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.setLayoutTransition(null); 777479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParentView.setLayoutTransition(null); 778479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 779479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet }.start(); 780479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 781e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 782e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 78319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(layoutParams); 784c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 785c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 7862b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet Result result = moveView(previousParent, newParentView, childView, index, layoutParams); 787e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (result.isSuccess() == false) { 788e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 789e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 790c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 7915a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 79201811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet if (layoutParams != null && result.isSuccess()) { 793e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet result = result.getCopyWithData(layoutParams); 79401811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet } 79501811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 79601811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet return result; 797c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 798c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 799e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 800e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Moves a View from its current parent to a new given parent at a new given location, with 801e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * an optional new {@link LayoutParams} instance 802e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 8032b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet * @param previousParent the previous parent, still owning the child at the time of the call. 8042b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet * @param newParent the new parent 805479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet * @param movedView the view to move 806e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param index the new location in the new parent 807e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param params an option (can be null) {@link LayoutParams} instance. 808e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 80919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 81019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 811e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 812e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 813479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet private Result moveView(ViewGroup previousParent, final ViewGroup newParent, 814479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet final View movedView, final int index, final LayoutParams params) { 8159eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet try { 8162b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // check if there is a transition on the previousParent. 817479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet LayoutTransition previousTransition = previousParent.getLayoutTransition(); 818479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (previousTransition != null) { 8197550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // in this case there is an animation. This means we have to wait for the child's 8207550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // parent reference to be null'ed out so that we can add it to the new parent. 8217550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // It is technically removed right before the DISAPPEARING animation is done (if 8227550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // the animation of this type is not null, otherwise it's after which is impossible 8237550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // to handle). 8247550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // Because there is no move animation, if the new parent is the same as the old 8257550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before 8267550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // adding the child or the child will appear in its new location before the 8277550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // other children have made room for it. 8282b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 8292b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add a listener to the transition to be notified of the actual removal. 830479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousTransition.addTransitionListener(new TransitionListener() { 831479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet private int mChangeDisappearingCount = 0; 8322b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 8332b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public void startTransition(LayoutTransition transition, ViewGroup container, 8342b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet View view, int transitionType) { 835479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { 836479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount++; 837479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 8382b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 839e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 8402b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public void endTransition(LayoutTransition transition, ViewGroup container, 8412b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet View view, int transitionType) { 842479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { 843479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount--; 844479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 845479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 846479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING && 847479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount == 0) { 8482b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add it to the parentView in the correct location 8492b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet if (params != null) { 850479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index, params); 8512b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } else { 852479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index); 8532b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8542b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8552b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8562b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet }); 8572b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 8582b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // remove the view from the current parent. 859479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.removeView(movedView); 8602b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 8612b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // and return since adding the view to the new parent is done in the listener. 8622b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet return SUCCESS.createResult(); 863e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } else { 8642b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // standard code with no animation. pretty simple. 865479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.removeView(movedView); 866e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 8672b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add it to the parentView in the correct location 8682b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet if (params != null) { 869479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index, params); 8702b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } else { 871479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index); 8722b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8732b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 8742b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet return SUCCESS.createResult(); 8752b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8769eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } catch (UnsupportedOperationException e) { 8779eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 87819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 879c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 880e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 881e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 882e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 883e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Removes a child from its current parent. 884e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 885e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 886e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 887e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 888e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 889e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 890e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @see LayoutScene#removeChild(Object, IAnimationListener) 891e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 89219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result removeChild(final View childView, IAnimationListener listener) { 893e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet checkLock(); 894c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 8959eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet invalidateRenderingSize(); 8969eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 897e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final ViewGroup parent = (ViewGroup) childView.getParent(); 898e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 899e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 900e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new AnimationThread(this, "moveChild", listener) { 901e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 902e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 90319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result preAnimation() { 904e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.setLayoutTransition(new LayoutTransition()); 905e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return removeView(parent, childView); 906e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 907e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 908e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 909e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet public void postAnimation() { 910e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.setLayoutTransition(null); 911e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 912e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet }.start(); 913e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 914e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 91519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 916e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 917e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 91819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet Result result = removeView(parent, childView); 919e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (result.isSuccess() == false) { 920e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 921e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 922e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 9235a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet return render(false /*freshRender*/); 9242eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 9252eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 9262eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet /** 927e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Removes a given view from its current parent. 928e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 929e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param view the view to remove from its parent 930e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 93119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 93219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 933e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 934e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 93519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private Result removeView(ViewGroup parent, View view) { 936e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet try { 937e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.removeView(view); 93819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 939e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } catch (UnsupportedOperationException e) { 940e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 94119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 942e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 943e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 944e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 945e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 946d7cc1244d7f0901688545c8535fa531fbb68669aXavier Ducrohet * Returns the log associated with the session. 947d7cc1244d7f0901688545c8535fa531fbb68669aXavier Ducrohet * @return the log or null if there are none. 948d7cc1244d7f0901688545c8535fa531fbb68669aXavier Ducrohet */ 949d7cc1244d7f0901688545c8535fa531fbb68669aXavier Ducrohet public LayoutLog getLog() { 950d7cc1244d7f0901688545c8535fa531fbb68669aXavier Ducrohet if (mParams != null) { 951d7cc1244d7f0901688545c8535fa531fbb68669aXavier Ducrohet return mParams.getLog(); 952d7cc1244d7f0901688545c8535fa531fbb68669aXavier Ducrohet } 953d7cc1244d7f0901688545c8535fa531fbb68669aXavier Ducrohet 954d7cc1244d7f0901688545c8535fa531fbb68669aXavier Ducrohet return null; 955d7cc1244d7f0901688545c8535fa531fbb68669aXavier Ducrohet } 956d7cc1244d7f0901688545c8535fa531fbb68669aXavier Ducrohet 957d7cc1244d7f0901688545c8535fa531fbb68669aXavier Ducrohet /** 9582eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * Checks that the lock is owned by the current thread and that the current context is the one 9592eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * from this scene. 9602eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 9612eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 9622eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 9632eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet */ 9642eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet private void checkLock() { 9652eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet ReentrantLock lock = Bridge.getLock(); 9662eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (lock.isHeldByCurrentThread() == false) { 9672eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet throw new IllegalStateException("scene must be acquired first. see #acquire(long)"); 9682eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 9692eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (sCurrentContext != mContext) { 9702eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet throw new IllegalStateException("Thread acquired a scene but is rendering a different one"); 9712eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 9722eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 9732eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 97416584225125acba18b74920b902c798dfead0328Xavier Ducrohet private void findBackground(RenderResources resources) { 97516584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (mParams.isBgColorOverridden() == false) { 97616584225125acba18b74920b902c798dfead0328Xavier Ducrohet mWindowBackground = resources.findItemInTheme("windowBackground"); 97716584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (mWindowBackground != null) { 97816584225125acba18b74920b902c798dfead0328Xavier Ducrohet mWindowBackground = resources.resolveResValue(mWindowBackground); 97916584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 98016584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 98116584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 982c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 98316584225125acba18b74920b902c798dfead0328Xavier Ducrohet private boolean isTabletUi() { 98416584225125acba18b74920b902c798dfead0328Xavier Ducrohet return mParams.getConfigScreenSize() == ScreenSize.XLARGE; 98516584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 986c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 98716584225125acba18b74920b902c798dfead0328Xavier Ducrohet private boolean isHCApp() { 98816584225125acba18b74920b902c798dfead0328Xavier Ducrohet RenderResources resources = mContext.getRenderResources(); 98916584225125acba18b74920b902c798dfead0328Xavier Ducrohet 99016584225125acba18b74920b902c798dfead0328Xavier Ducrohet // the app must say it targets 11+ and the theme name must extend Theme.Holo or 99116584225125acba18b74920b902c798dfead0328Xavier Ducrohet // Theme.Holo.Light (which does not extend Theme.Holo, but Theme.Light) 99216584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (mParams.getTargetSdkVersion() < 11) { 99316584225125acba18b74920b902c798dfead0328Xavier Ducrohet return false; 99416584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 99516584225125acba18b74920b902c798dfead0328Xavier Ducrohet 99616584225125acba18b74920b902c798dfead0328Xavier Ducrohet StyleResourceValue currentTheme = resources.getCurrentTheme(); 99716584225125acba18b74920b902c798dfead0328Xavier Ducrohet StyleResourceValue holoTheme = resources.getTheme("Theme.Holo", true /*frameworkTheme*/); 99816584225125acba18b74920b902c798dfead0328Xavier Ducrohet 99916584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (currentTheme == holoTheme || 100016584225125acba18b74920b902c798dfead0328Xavier Ducrohet resources.themeIsParentOf(holoTheme, currentTheme)) { 100116584225125acba18b74920b902c798dfead0328Xavier Ducrohet return true; 100216584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 100316584225125acba18b74920b902c798dfead0328Xavier Ducrohet 100416584225125acba18b74920b902c798dfead0328Xavier Ducrohet StyleResourceValue holoLightTheme = resources.getTheme("Theme.Holo.Light", 100516584225125acba18b74920b902c798dfead0328Xavier Ducrohet true /*frameworkTheme*/); 100616584225125acba18b74920b902c798dfead0328Xavier Ducrohet 100716584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (currentTheme == holoLightTheme || 100816584225125acba18b74920b902c798dfead0328Xavier Ducrohet resources.themeIsParentOf(holoLightTheme, currentTheme)) { 100916584225125acba18b74920b902c798dfead0328Xavier Ducrohet return true; 101016584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 101116584225125acba18b74920b902c798dfead0328Xavier Ducrohet 101216584225125acba18b74920b902c798dfead0328Xavier Ducrohet return false; 101316584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 101416584225125acba18b74920b902c798dfead0328Xavier Ducrohet 101516584225125acba18b74920b902c798dfead0328Xavier Ducrohet private void findStatusBar(RenderResources resources, DisplayMetrics metrics) { 101616584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (isTabletUi() == false) { 101716584225125acba18b74920b902c798dfead0328Xavier Ducrohet boolean windowFullscreen = getBooleanThemeValue(resources, 101816584225125acba18b74920b902c798dfead0328Xavier Ducrohet "windowFullscreen", false /*defaultValue*/); 101916584225125acba18b74920b902c798dfead0328Xavier Ducrohet 102016584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (windowFullscreen == false) { 102116584225125acba18b74920b902c798dfead0328Xavier Ducrohet // default value 102216584225125acba18b74920b902c798dfead0328Xavier Ducrohet mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT; 102316584225125acba18b74920b902c798dfead0328Xavier Ducrohet 102416584225125acba18b74920b902c798dfead0328Xavier Ducrohet // get the real value 102516584225125acba18b74920b902c798dfead0328Xavier Ducrohet ResourceValue value = resources.getFrameworkResource(RenderResources.RES_DIMEN, 102616584225125acba18b74920b902c798dfead0328Xavier Ducrohet "status_bar_height"); 102716584225125acba18b74920b902c798dfead0328Xavier Ducrohet 102816584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (value != null) { 102916584225125acba18b74920b902c798dfead0328Xavier Ducrohet TypedValue typedValue = ResourceHelper.getValue(value.getValue()); 103016584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (typedValue != null) { 103116584225125acba18b74920b902c798dfead0328Xavier Ducrohet // compute the pixel value based on the display metrics 103216584225125acba18b74920b902c798dfead0328Xavier Ducrohet mStatusBarSize = (int)typedValue.getDimension(metrics); 103316584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 103416584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 103516584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 103616584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 103716584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 103816584225125acba18b74920b902c798dfead0328Xavier Ducrohet 103916584225125acba18b74920b902c798dfead0328Xavier Ducrohet private void findTopBar(RenderResources resources, DisplayMetrics metrics) { 104016584225125acba18b74920b902c798dfead0328Xavier Ducrohet boolean windowIsFloating = getBooleanThemeValue(resources, 104116584225125acba18b74920b902c798dfead0328Xavier Ducrohet "windowIsFloating", true /*defaultValue*/); 104216584225125acba18b74920b902c798dfead0328Xavier Ducrohet 104316584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (windowIsFloating == false) { 104416584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (isHCApp()) { 104516584225125acba18b74920b902c798dfead0328Xavier Ducrohet findActionBar(resources, metrics); 104616584225125acba18b74920b902c798dfead0328Xavier Ducrohet } else { 104716584225125acba18b74920b902c798dfead0328Xavier Ducrohet findTitleBar(resources, metrics); 104816584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 104916584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 105016584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 105116584225125acba18b74920b902c798dfead0328Xavier Ducrohet 105216584225125acba18b74920b902c798dfead0328Xavier Ducrohet private void findActionBar(RenderResources resources, DisplayMetrics metrics) { 105316584225125acba18b74920b902c798dfead0328Xavier Ducrohet boolean windowActionBar = getBooleanThemeValue(resources, 105416584225125acba18b74920b902c798dfead0328Xavier Ducrohet "windowActionBar", true /*defaultValue*/); 105516584225125acba18b74920b902c798dfead0328Xavier Ducrohet 105616584225125acba18b74920b902c798dfead0328Xavier Ducrohet // if there's a value and it's false (default is true) 105716584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (windowActionBar) { 1058c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1059c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // default size of the window title bar 106016584225125acba18b74920b902c798dfead0328Xavier Ducrohet mTopBarSize = DEFAULT_TITLE_BAR_HEIGHT; 1061c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1062c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get value from the theme. 106316584225125acba18b74920b902c798dfead0328Xavier Ducrohet ResourceValue value = resources.findItemInTheme("actionBarSize"); 1064c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1065c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // resolve it 106616584225125acba18b74920b902c798dfead0328Xavier Ducrohet value = resources.resolveResValue(value); 1067c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1068c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (value != null) { 1069c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get the numerical value, if available 1070c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet TypedValue typedValue = ResourceHelper.getValue(value.getValue()); 1071c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (typedValue != null) { 1072c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // compute the pixel value based on the display metrics 107316584225125acba18b74920b902c798dfead0328Xavier Ducrohet mTopBarSize = (int)typedValue.getDimension(metrics); 1074c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1075c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1076c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 107716584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 1078c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 107916584225125acba18b74920b902c798dfead0328Xavier Ducrohet private void findTitleBar(RenderResources resources, DisplayMetrics metrics) { 108016584225125acba18b74920b902c798dfead0328Xavier Ducrohet boolean windowNoTitle = getBooleanThemeValue(resources, 108116584225125acba18b74920b902c798dfead0328Xavier Ducrohet "windowNoTitle", false /*defaultValue*/); 1082c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 108316584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (windowNoTitle == false) { 108416584225125acba18b74920b902c798dfead0328Xavier Ducrohet 108516584225125acba18b74920b902c798dfead0328Xavier Ducrohet // default size of the window title bar 108616584225125acba18b74920b902c798dfead0328Xavier Ducrohet mTopBarSize = DEFAULT_TITLE_BAR_HEIGHT; 108716584225125acba18b74920b902c798dfead0328Xavier Ducrohet 108816584225125acba18b74920b902c798dfead0328Xavier Ducrohet // get value from the theme. 108916584225125acba18b74920b902c798dfead0328Xavier Ducrohet ResourceValue value = resources.findItemInTheme("windowTitleSize"); 109016584225125acba18b74920b902c798dfead0328Xavier Ducrohet 109116584225125acba18b74920b902c798dfead0328Xavier Ducrohet // resolve it 109216584225125acba18b74920b902c798dfead0328Xavier Ducrohet value = resources.resolveResValue(value); 1093c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 109416584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (value != null) { 109516584225125acba18b74920b902c798dfead0328Xavier Ducrohet // get the numerical value, if available 109616584225125acba18b74920b902c798dfead0328Xavier Ducrohet TypedValue typedValue = ResourceHelper.getValue(value.getValue()); 109716584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (typedValue != null) { 109816584225125acba18b74920b902c798dfead0328Xavier Ducrohet // compute the pixel value based on the display metrics 109916584225125acba18b74920b902c798dfead0328Xavier Ducrohet mTopBarSize = (int)typedValue.getDimension(metrics); 110016584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 110116584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 110216584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 110316584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 110416584225125acba18b74920b902c798dfead0328Xavier Ducrohet 110516584225125acba18b74920b902c798dfead0328Xavier Ducrohet private void findSystemBar(RenderResources resources, DisplayMetrics metrics) { 110616584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (isTabletUi() && getBooleanThemeValue( 110716584225125acba18b74920b902c798dfead0328Xavier Ducrohet resources, "windowIsFloating", true /*defaultValue*/) == false) { 1108c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1109c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // default value 111016584225125acba18b74920b902c798dfead0328Xavier Ducrohet mSystemBarSize = 56; // ?? 1111c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1112d1d6fafc7fc63543b10552dadf202dd6fa40fe6bXavier Ducrohet // get the real value 111316584225125acba18b74920b902c798dfead0328Xavier Ducrohet ResourceValue value = resources.getFrameworkResource(RenderResources.RES_DIMEN, 111416584225125acba18b74920b902c798dfead0328Xavier Ducrohet "status_bar_height"); 111516584225125acba18b74920b902c798dfead0328Xavier Ducrohet 1116c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (value != null) { 1117c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet TypedValue typedValue = ResourceHelper.getValue(value.getValue()); 1118c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (typedValue != null) { 1119c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // compute the pixel value based on the display metrics 112016584225125acba18b74920b902c798dfead0328Xavier Ducrohet mSystemBarSize = (int)typedValue.getDimension(metrics); 1121c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1122c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 112316584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 112416584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 112516584225125acba18b74920b902c798dfead0328Xavier Ducrohet 112616584225125acba18b74920b902c798dfead0328Xavier Ducrohet private boolean getBooleanThemeValue(RenderResources resources, 112716584225125acba18b74920b902c798dfead0328Xavier Ducrohet String name, boolean defaultValue) { 112816584225125acba18b74920b902c798dfead0328Xavier Ducrohet 112916584225125acba18b74920b902c798dfead0328Xavier Ducrohet // get the title bar flag from the current theme. 113016584225125acba18b74920b902c798dfead0328Xavier Ducrohet ResourceValue value = resources.findItemInTheme(name); 113116584225125acba18b74920b902c798dfead0328Xavier Ducrohet 113216584225125acba18b74920b902c798dfead0328Xavier Ducrohet // because it may reference something else, we resolve it. 113316584225125acba18b74920b902c798dfead0328Xavier Ducrohet value = resources.resolveResValue(value); 1134c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 113516584225125acba18b74920b902c798dfead0328Xavier Ducrohet // if there's no value, return the default. 113616584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (value == null || value.getValue() == null) { 113716584225125acba18b74920b902c798dfead0328Xavier Ducrohet return defaultValue; 1138c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1139c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 114016584225125acba18b74920b902c798dfead0328Xavier Ducrohet return XmlUtils.convertValueToBoolean(value.getValue(), defaultValue); 1141c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1142c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1143c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 1144c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Post process on a view hierachy that was just inflated. 1145c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p/>At the moment this only support TabHost: If {@link TabHost} is detected, look for the 1146c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically 1147c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * based on the content of the {@link FrameLayout}. 1148c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param view the root view to process. 1149c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param projectCallback callback to the project. 1150c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 1151c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private void postInflateProcess(View view, IProjectCallback projectCallback) 1152c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throws PostInflateException { 1153c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (view instanceof TabHost) { 1154c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet setupTabHost((TabHost)view, projectCallback); 115531fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet } else if (view instanceof QuickContactBadge) { 115631fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet QuickContactBadge badge = (QuickContactBadge) view; 115731fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet badge.setImageToDefault(); 1158c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } else if (view instanceof ViewGroup) { 1159c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet ViewGroup group = (ViewGroup)view; 1160c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet final int count = group.getChildCount(); 1161c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet for (int c = 0 ; c < count ; c++) { 1162c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet View child = group.getChildAt(c); 1163c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet postInflateProcess(child, projectCallback); 1164c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1165c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1166c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1167c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1168c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 1169c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Sets up a {@link TabHost} object. 1170c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param tabHost the TabHost to setup. 1171c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param projectCallback The project callback object to access the project R class. 1172c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @throws PostInflateException 1173c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 1174c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private void setupTabHost(TabHost tabHost, IProjectCallback projectCallback) 1175c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throws PostInflateException { 1176c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // look for the TabWidget, and the FrameLayout. They have their own specific names 1177c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet View v = tabHost.findViewById(android.R.id.tabs); 1178c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1179c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (v == null) { 1180c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException( 1181c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a TabWidget with id \"android:id/tabs\".\n"); 1182c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1183c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1184c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if ((v instanceof TabWidget) == false) { 1185c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException(String.format( 1186c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a TabWidget with id \"android:id/tabs\".\n" + 1187c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName())); 1188c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1189c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1190c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet v = tabHost.findViewById(android.R.id.tabcontent); 1191c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1192c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (v == null) { 1193c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // TODO: see if we can fake tabs even without the FrameLayout (same below when the framelayout is empty) 1194c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException( 1195c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a FrameLayout with id \"android:id/tabcontent\"."); 1196c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1197c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1198c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if ((v instanceof FrameLayout) == false) { 1199c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException(String.format( 1200c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" + 1201c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName())); 1202c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1203c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1204c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet FrameLayout content = (FrameLayout)v; 1205c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1206c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // now process the content of the framelayout and dynamically create tabs for it. 1207c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet final int count = content.getChildCount(); 1208c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1209c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // this must be called before addTab() so that the TabHost searches its TabWidget 1210c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // and FrameLayout. 1211c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet tabHost.setup(); 1212c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1213796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye if (count == 0) { 1214796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye // Create a dummy child to get a single tab 1215796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye TabSpec spec = tabHost.newTabSpec("tag").setIndicator("Tab Label", 1216796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye tabHost.getResources().getDrawable(android.R.drawable.ic_menu_info_details)) 1217796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye .setContent(new TabHost.TabContentFactory() { 1218796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye public View createTabContent(String tag) { 1219796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye return new LinearLayout(mContext); 1220796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } 1221796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye }); 1222796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye tabHost.addTab(spec); 1223796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye return; 1224796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } else { 1225796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye // for each child of the framelayout, add a new TabSpec 1226796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye for (int i = 0 ; i < count ; i++) { 1227796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye View child = content.getChildAt(i); 1228796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye String tabSpec = String.format("tab_spec%d", i+1); 1229796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye int id = child.getId(); 1230796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye String[] resource = projectCallback.resolveResourceValue(id); 1231796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye String name; 1232796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye if (resource != null) { 1233796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye name = resource[0]; // 0 is resource name, 1 is resource type. 1234796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } else { 1235796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye name = String.format("Tab %d", i+1); // default name if id is unresolved. 1236796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } 1237796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id)); 1238c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1239c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1240c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1241c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1242c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1243c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 1244c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Visits a View and its children and generate a {@link ViewInfo} containing the 1245c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * bounds of all the views. 1246c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param view the root View 1247c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param context the context. 1248c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 124916584225125acba18b74920b902c798dfead0328Xavier Ducrohet private ViewInfo visit(View view, BridgeContext context, int offset) { 1250c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (view == null) { 1251c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return null; 1252c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1253c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1254c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet ViewInfo result = new ViewInfo(view.getClass().getName(), 1255c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet context.getViewKey(view), 125616584225125acba18b74920b902c798dfead0328Xavier Ducrohet view.getLeft(), view.getTop() + offset, view.getRight(), view.getBottom() + offset, 1257cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet view, view.getLayoutParams()); 1258c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1259c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (view instanceof ViewGroup) { 1260c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet ViewGroup group = ((ViewGroup) view); 126116584225125acba18b74920b902c798dfead0328Xavier Ducrohet result.setChildren(visitAllChildren(group, context, 0 /*offset*/)); 1262c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1263c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1264c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return result; 1265c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1266c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 126716584225125acba18b74920b902c798dfead0328Xavier Ducrohet private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, BridgeContext context, 126816584225125acba18b74920b902c798dfead0328Xavier Ducrohet int offset) { 12697d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet if (viewGroup == null) { 12707d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet return null; 12717d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet } 12727d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet 12737d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet List<ViewInfo> children = new ArrayList<ViewInfo>(); 12747d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet for (int i = 0; i < viewGroup.getChildCount(); i++) { 127516584225125acba18b74920b902c798dfead0328Xavier Ducrohet children.add(visit(viewGroup.getChildAt(i), context, offset)); 12767d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet } 12777d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet return children; 12787d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet } 12797d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet 12807d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet 12819eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private void invalidateRenderingSize() { 12829eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet mMeasuredScreenWidth = mMeasuredScreenHeight = -1; 12839eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 12849eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 1285c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet public BufferedImage getImage() { 1286c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return mImage; 1287c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1288c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 128916584225125acba18b74920b902c798dfead0328Xavier Ducrohet public boolean isAlphaChannelImage() { 129016584225125acba18b74920b902c798dfead0328Xavier Ducrohet return mIsAlphaChannelImage; 129116584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 129216584225125acba18b74920b902c798dfead0328Xavier Ducrohet 12937d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet public List<ViewInfo> getViewInfos() { 12947d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet return mViewInfoList; 1295c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1296cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet 129719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Map<String, String> getDefaultProperties(Object viewObject) { 1298cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet return mContext.getDefaultPropMap(viewObject); 1299cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet } 1300c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 130119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public void setScene(RenderSession session) { 130219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet mScene = session; 1303c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 1304c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 130519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public RenderSession getSession() { 1306c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet return mScene; 1307c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 130870552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet 130970552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet // --- FrameworkResourceIdProvider methods 131070552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet 131170552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet @Override 131270552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet public Integer getId(String resType, String resName) { 131370552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet return Bridge.getResourceValue(resType, resName); 131470552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohet } 1315c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet} 1316