RenderSessionImpl.java revision b0d34f9c99cbd43e8238c5952b19d032f02dd168
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_NOT_INFLATED; 2219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; 2319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP_NO_CHILDREN; 2419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.SUCCESS; 2519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet 2619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.IAnimationListener; 2719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.ILayoutPullParser; 2819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.IProjectCallback; 29bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderParams; 3070552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderResources; 3119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderSession; 3219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.ResourceValue; 3319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.Result; 341126422ee1f532d8582a4e3b56dbfe505c15e775Xavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams; 3519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.ViewInfo; 3619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.Result.Status; 371126422ee1f532d8582a4e3b56dbfe505c15e775Xavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams.RenderingMode; 38c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.internal.util.XmlUtils; 392eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohetimport com.android.layoutlib.bridge.Bridge; 40c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeContext; 41c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeInflater; 4201811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes; 43c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeWindow; 44c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeWindowSession; 45c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeXmlBlockParser; 46bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohetimport com.android.layoutlib.bridge.bars.FakeActionBar; 47bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohetimport com.android.layoutlib.bridge.bars.PhoneSystemBar; 48bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohetimport com.android.layoutlib.bridge.bars.TabletSystemBar; 49bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohetimport com.android.layoutlib.bridge.bars.TitleBar; 5035ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohetimport com.android.resources.ResourceType; 5116584225125acba18b74920b902c798dfead0328Xavier Ducrohetimport com.android.resources.ScreenSize; 52b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohetimport com.android.util.Pair; 53c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 54bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohetimport org.xmlpull.v1.XmlPullParserException; 55bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 56e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohetimport android.animation.Animator; 572eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohetimport android.animation.AnimatorInflater; 58e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohetimport android.animation.LayoutTransition; 592b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohetimport android.animation.LayoutTransition.TransitionListener; 60c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.app.Fragment_Delegate; 61c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Bitmap; 62c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Bitmap_Delegate; 63c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Canvas; 64c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.drawable.Drawable; 65c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.os.Handler; 66c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.util.DisplayMetrics; 67c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.util.TypedValue; 68c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.View; 69c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.ViewGroup; 70c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.View.AttachInfo; 71c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.View.MeasureSpec; 7201811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohetimport android.view.ViewGroup.LayoutParams; 73c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.widget.FrameLayout; 74796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbyeimport android.widget.LinearLayout; 7531fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohetimport android.widget.QuickContactBadge; 76c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.widget.TabHost; 77c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.widget.TabWidget; 78796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbyeimport android.widget.TabHost.TabSpec; 79c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 805a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohetimport java.awt.AlphaComposite; 81c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.Color; 82c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.Graphics2D; 83c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.image.BufferedImage; 84c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.ArrayList; 85c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.List; 86c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.Map; 87c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 88c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet/** 8919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * Class implementing the render session. 90c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * 9119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * A session is a stateful representation of a layout file. It is initialized with data coming 9219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then 93c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * be done on the layout. 94c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * 95c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 96b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetpublic class RenderSessionImpl extends RenderAction<SessionParams> { 97c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 98c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private static final int DEFAULT_TITLE_BAR_HEIGHT = 25; 99c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private static final int DEFAULT_STATUS_BAR_HEIGHT = 25; 100c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 101c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // scene state 10219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private RenderSession mScene; 103c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private BridgeXmlBlockParser mBlockParser; 104c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private BridgeInflater mInflater; 105ffb42f6c5043de226f02318a1311669d35a90711Xavier Ducrohet private ResourceValue mWindowBackground; 106bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private ViewGroup mViewRoot; 107bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private FrameLayout mContentRoot; 1089eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private Canvas mCanvas; 1099eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private int mMeasuredScreenWidth = -1; 1109eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private int mMeasuredScreenHeight = -1; 111bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private boolean mIsAlphaChannelImage; 112bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private boolean mWindowIsFloating; 11316584225125acba18b74920b902c798dfead0328Xavier Ducrohet 11416584225125acba18b74920b902c798dfead0328Xavier Ducrohet private int mStatusBarSize; 11516584225125acba18b74920b902c798dfead0328Xavier Ducrohet private int mSystemBarSize; 116bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private int mTitleBarSize; 117bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private int mActionBarSize; 11816584225125acba18b74920b902c798dfead0328Xavier Ducrohet 119c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 120c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // information being returned through the API 121c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private BufferedImage mImage; 1227d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet private List<ViewInfo> mViewInfoList; 123c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 124c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private static final class PostInflateException extends Exception { 125c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private static final long serialVersionUID = 1L; 126c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 127c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet public PostInflateException(String message) { 128c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet super(message); 129c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 130c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 131c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 132c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 133c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Creates a layout scene with all the information coming from the layout bridge API. 134c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p> 13519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init()}, which act as a 13619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * call to {@link RenderSessionImpl#acquire(long)} 137c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * 138c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @see LayoutBridge#createScene(com.android.layoutlib.api.SceneParams) 139c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 1401126422ee1f532d8582a4e3b56dbfe505c15e775Xavier Ducrohet public RenderSessionImpl(SessionParams params) { 141b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet super(new SessionParams(params)); 1422eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 1432eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 1442eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet /** 1452eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * Initializes and acquires the scene, creating various Android objects such as context, 1462eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * inflater, and parser. 1472eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 1482eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @param timeout the time to wait if another rendering is happening. 1492eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 1502eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @return whether the scene was prepared 1512eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 1522eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @see #acquire(long) 1532eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @see #release() 1542eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet */ 155b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet @Override 15619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result init(long timeout) { 157b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet Result result = super.init(timeout); 158b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet if (result.isSuccess() == false) { 1592eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet return result; 1602eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 161c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 162b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet SessionParams params = getParams(); 163b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 164c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 165b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet RenderResources resources = getParams().getResources(); 166b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet DisplayMetrics metrics = getContext().getMetrics(); 167c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 16816584225125acba18b74920b902c798dfead0328Xavier Ducrohet // use default of true in case it's not found to use alpha by default 16916584225125acba18b74920b902c798dfead0328Xavier Ducrohet mIsAlphaChannelImage = getBooleanThemeValue(resources, 17016584225125acba18b74920b902c798dfead0328Xavier Ducrohet "windowIsFloating", true /*defaultValue*/); 17116584225125acba18b74920b902c798dfead0328Xavier Ducrohet 172bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet mWindowIsFloating = getBooleanThemeValue(resources, "windowIsFloating", 173bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet true /*defaultValue*/); 1742eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 17516584225125acba18b74920b902c798dfead0328Xavier Ducrohet findBackground(resources); 17616584225125acba18b74920b902c798dfead0328Xavier Ducrohet findStatusBar(resources, metrics); 177bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet findActionBar(resources, metrics); 17816584225125acba18b74920b902c798dfead0328Xavier Ducrohet findSystemBar(resources, metrics); 179c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 180c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // build the inflater and parser. 181b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet mInflater = new BridgeInflater(context, params.getProjectCallback()); 182b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet context.setBridgeInflater(mInflater); 183b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet mInflater.setFactory2(context); 1842eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 185b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet mBlockParser = new BridgeXmlBlockParser(params.getLayoutDescription(), 186b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet context, false /* platformResourceFlag */); 1872eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 188168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet return SUCCESS.createResult(); 189c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 190c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 191c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 192c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Inflates the layout. 193c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p> 1942eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 1952eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 1962eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 1972eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #init(long)} was not called. 198c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 19919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result inflate() { 2002eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet checkLock(); 2012eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 202c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet try { 203c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 204b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet SessionParams params = getParams(); 205b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 206b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet 207b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet if (mWindowIsFloating || params.isForceNoDecor()) { 208b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet mViewRoot = mContentRoot = new FrameLayout(context); 209bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } else { 210bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet /* 211bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * we're creating the following layout 212bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * 213bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet +-------------------------------------------------+ 214bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet | System bar (only in phone UI) | 215bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet +-------------------------------------------------+ 216bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet | Title/Action bar (optional) | 217bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet +-------------------------------------------------+ 218bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet | Content, vertical extending | 219bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet | | 220bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet +-------------------------------------------------+ 221bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet | System bar (only in tablet UI) | 222bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet +-------------------------------------------------+ 223bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 224bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet */ 225bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 226b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet LinearLayout topLayout = new LinearLayout(context); 227bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet mViewRoot = topLayout; 228bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet topLayout.setOrientation(LinearLayout.VERTICAL); 229bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 230bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (mStatusBarSize > 0) { 231bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // system bar 232bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet try { 233b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet PhoneSystemBar systemBar = new PhoneSystemBar(context, 234b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet params.getDensity()); 235bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet systemBar.setLayoutParams( 236bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet new LinearLayout.LayoutParams( 237bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet LayoutParams.MATCH_PARENT, mStatusBarSize)); 238bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet topLayout.addView(systemBar); 239bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } catch (XmlPullParserException e) { 240bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 241bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 242bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 243bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 244bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // if the theme says no title/action bar, then the size will be 0 245bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (mActionBarSize > 0) { 246bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet try { 247b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet FakeActionBar actionBar = new FakeActionBar(context, 248b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet params.getDensity(), 249b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet params.getAppLabel(), params.getAppIcon()); 250bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet actionBar.setLayoutParams( 251bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet new LinearLayout.LayoutParams( 252bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet LayoutParams.MATCH_PARENT, mActionBarSize)); 253bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet topLayout.addView(actionBar); 254bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } catch (XmlPullParserException e) { 255bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 256bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 257bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } else if (mTitleBarSize > 0) { 258bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet try { 259b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet TitleBar titleBar = new TitleBar(context, 260b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet params.getDensity(), params.getAppLabel()); 261bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet titleBar.setLayoutParams( 262bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet new LinearLayout.LayoutParams( 263bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet LayoutParams.MATCH_PARENT, mTitleBarSize)); 264bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet topLayout.addView(titleBar); 265bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } catch (XmlPullParserException e) { 266bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 267bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 268bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 269bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 270bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 271bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // content frame 272b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet mContentRoot = new FrameLayout(context); 273b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( 274bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); 275b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet layoutParams.weight = 1; 276b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet mContentRoot.setLayoutParams(layoutParams); 277bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet topLayout.addView(mContentRoot); 278bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 279bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (mSystemBarSize > 0) { 280bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // system bar 281bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet try { 282b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet TabletSystemBar systemBar = new TabletSystemBar(context, 283b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet params.getDensity()); 284bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet systemBar.setLayoutParams( 285bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet new LinearLayout.LayoutParams( 286bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet LayoutParams.MATCH_PARENT, mSystemBarSize)); 287bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet topLayout.addView(systemBar); 288bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } catch (XmlPullParserException e) { 289bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 290bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 291bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 292bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 293bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 294bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 295c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 296c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // Sets the project callback (custom view loader) to the fragment delegate so that 297c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // it can instantiate the custom Fragment. 298b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet Fragment_Delegate.setProjectCallback(params.getProjectCallback()); 299c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 300bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet View view = mInflater.inflate(mBlockParser, mContentRoot); 301c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 302c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet Fragment_Delegate.setProjectCallback(null); 303c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 304c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // set the AttachInfo on the root view. 305c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet AttachInfo info = new AttachInfo(new BridgeWindowSession(), new BridgeWindow(), 306c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet new Handler(), null); 307c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet info.mHasWindowFocus = true; 308c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet info.mWindowVisibility = View.VISIBLE; 309c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet info.mInTouchMode = false; // this is so that we can display selections. 31046a329244db12b6f7afc3c9a6409d420241a1058Xavier Ducrohet info.mHardwareAccelerated = false; 311c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet mViewRoot.dispatchAttachedToWindow(info, 0); 312c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 31333758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet // post-inflate process. For now this supports TabHost/TabWidget 314b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet postInflateProcess(view, params.getProjectCallback()); 31533758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet 316c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get the background drawable 317c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (mWindowBackground != null) { 318b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet Drawable d = ResourceHelper.getDrawable(mWindowBackground, context); 319bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet mContentRoot.setBackgroundDrawable(d); 320c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 321c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 32219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 323c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (PostInflateException e) { 32419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_INFLATION.createResult(e.getMessage(), e); 325c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (Throwable e) { 326c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get the real cause of the exception. 327c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet Throwable t = e; 328c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet while (t.getCause() != null) { 329c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet t = t.getCause(); 330c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 331c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 33219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_INFLATION.createResult(t.getMessage(), t); 333c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 334c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 335c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 336c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 337c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Renders the scene. 338c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p> 3392eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 3402eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 3415a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * @param freshRender whether the render is a new one and should erase the existing bitmap (in 3425a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * the case where bitmaps are reused). This is typically needed when not playing 3435a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * animations.) 3445a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * 3452eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 3462eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 3479eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet * 348bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderParams#getRenderingMode() 349bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#render(long) 350c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 3515a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet public Result render(boolean freshRender) { 3522eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet checkLock(); 3532eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 354b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet SessionParams params = getParams(); 355b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet 356c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet try { 357c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (mViewRoot == null) { 35819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_NOT_INFLATED.createResult(); 359c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 360c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // measure the views 361c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet int w_spec, h_spec; 362c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 363b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet RenderingMode renderingMode = params.getRenderingMode(); 364fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet 3659eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // only do the screen measure when needed. 3669eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet boolean newRenderSize = false; 3679eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (mMeasuredScreenWidth == -1) { 3689eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet newRenderSize = true; 369b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet mMeasuredScreenWidth = params.getScreenWidth(); 370b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet mMeasuredScreenHeight = params.getScreenHeight(); 3719eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 3729eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (renderingMode != RenderingMode.NORMAL) { 3739eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // measure the full size needed by the layout. 3749eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet w_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenWidth, 3759eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet renderingMode.isHorizExpand() ? 3769eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet MeasureSpec.UNSPECIFIED // this lets us know the actual needed size 3779eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet : MeasureSpec.EXACTLY); 37816584225125acba18b74920b902c798dfead0328Xavier Ducrohet h_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenHeight, 3799eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet renderingMode.isVertExpand() ? 3809eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet MeasureSpec.UNSPECIFIED // this lets us know the actual needed size 3819eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet : MeasureSpec.EXACTLY); 3829eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet mViewRoot.measure(w_spec, h_spec); 3839eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 3849eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (renderingMode.isHorizExpand()) { 3859eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet int neededWidth = mViewRoot.getChildAt(0).getMeasuredWidth(); 3869eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (neededWidth > mMeasuredScreenWidth) { 3879eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet mMeasuredScreenWidth = neededWidth; 3889eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 389fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet } 390c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 3919eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (renderingMode.isVertExpand()) { 3929eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet int neededHeight = mViewRoot.getChildAt(0).getMeasuredHeight(); 39316584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (neededHeight > mMeasuredScreenHeight) { 39416584225125acba18b74920b902c798dfead0328Xavier Ducrohet mMeasuredScreenHeight = neededHeight; 3959eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 396fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet } 397c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 398c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 399c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 400c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // remeasure with the size we need 401c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // This must always be done before the call to layout 4029eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet w_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenWidth, MeasureSpec.EXACTLY); 40333758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet h_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenHeight, MeasureSpec.EXACTLY); 404c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet mViewRoot.measure(w_spec, h_spec); 405c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 406c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // now do the layout. 40716584225125acba18b74920b902c798dfead0328Xavier Ducrohet mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); 408c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 40933758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet mViewRoot.mAttachInfo.mTreeObserver.dispatchOnPreDraw(); 41033758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet 411c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // draw the views 412c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // create the BufferedImage into which the layout will be rendered. 4135a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet boolean newImage = false; 4149eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (newRenderSize || mCanvas == null) { 415b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet if (params.getImageFactory() != null) { 416b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet mImage = params.getImageFactory().getImage( 41716584225125acba18b74920b902c798dfead0328Xavier Ducrohet mMeasuredScreenWidth, 418bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet mMeasuredScreenHeight); 4199eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } else { 42016584225125acba18b74920b902c798dfead0328Xavier Ducrohet mImage = new BufferedImage( 42116584225125acba18b74920b902c798dfead0328Xavier Ducrohet mMeasuredScreenWidth, 422bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet mMeasuredScreenHeight, 42316584225125acba18b74920b902c798dfead0328Xavier Ducrohet BufferedImage.TYPE_INT_ARGB); 4245a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet newImage = true; 4259eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 426c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 427b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet if (params.isBgColorOverridden()) { 4285a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet // since we override the content, it's the same as if it was a new image. 4295a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet newImage = true; 4309eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet Graphics2D gc = mImage.createGraphics(); 431b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet gc.setColor(new Color(params.getOverrideBgColor(), true)); 4325a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet gc.setComposite(AlphaComposite.Src); 433bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); 4349eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet gc.dispose(); 4359eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 436c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 4379eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // create an Android bitmap around the BufferedImage 4389eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage, 439b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet true /*isMutable*/, params.getDensity()); 440c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 4419eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // create a Canvas around the Android bitmap 4429eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet mCanvas = new Canvas(bitmap); 443b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet mCanvas.setDensity(params.getDensity().getDpiValue()); 4449eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 445c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 4465a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet if (freshRender && newImage == false) { 4475a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet Graphics2D gc = mImage.createGraphics(); 4485a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet gc.setComposite(AlphaComposite.Src); 44916584225125acba18b74920b902c798dfead0328Xavier Ducrohet 45016584225125acba18b74920b902c798dfead0328Xavier Ducrohet gc.setColor(new Color(0x00000000, true)); 451bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet gc.fillRect(0, 0, 452bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet mMeasuredScreenWidth, mMeasuredScreenHeight); 45316584225125acba18b74920b902c798dfead0328Xavier Ducrohet 45416584225125acba18b74920b902c798dfead0328Xavier Ducrohet // done 4555a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet gc.dispose(); 4565a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet } 4575a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet 4589eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet mViewRoot.draw(mCanvas); 4599eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 460bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet mViewInfoList = startVisitingViews(mViewRoot, 0); 461c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 462c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // success! 46319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 464c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (Throwable e) { 465c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get the real cause of the exception. 466c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet Throwable t = e; 467c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet while (t.getCause() != null) { 468c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet t = t.getCause(); 469c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 470c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 47119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_UNKNOWN.createResult(t.getMessage(), t); 472c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 473c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 474c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 475c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 4762eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * Animate an object 4772eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * <p> 4782eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 4792eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 4802eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 4812eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 482e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 483bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#animate(Object, String, boolean, IAnimationListener) 4842eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet */ 48519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result animate(Object targetObject, String animationName, 4862eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet boolean isFrameworkAnimation, IAnimationListener listener) { 4872eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet checkLock(); 4882eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 489b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 490b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet 4912eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet // find the animation file. 492ffb42f6c5043de226f02318a1311669d35a90711Xavier Ducrohet ResourceValue animationResource = null; 4932eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet int animationId = 0; 4942eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (isFrameworkAnimation) { 495b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet animationResource = context.getRenderResources().getFrameworkResource( 49635ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceType.ANIMATOR, animationName); 4972eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 498b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet animationId = Bridge.getResourceId(ResourceType.ANIMATOR, animationName); 4992eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5002eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } else { 501b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet animationResource = context.getRenderResources().getProjectResource( 50235ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceType.ANIMATOR, animationName); 5032eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 504b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet animationId = context.getProjectCallback().getResourceId( 50535ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceType.ANIMATOR, animationName); 5062eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5072eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5082eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 5092eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 5102eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet try { 511b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet Animator anim = AnimatorInflater.loadAnimator(context, animationId); 5122eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (anim != null) { 5132eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet anim.setTarget(targetObject); 5142eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 515e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new PlayAnimationThread(anim, this, animationName, listener).start(); 5162eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 51719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 5182eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5192eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } catch (Exception e) { 520c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // get the real cause of the exception. 521c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet Throwable t = e; 522c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet while (t.getCause() != null) { 523c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet t = t.getCause(); 524c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 525c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 52619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_UNKNOWN.createResult(t.getMessage(), t); 5272eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5282eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5292eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 53019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_ANIM_NOT_FOUND.createResult(); 531c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 532c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 533e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 534e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Insert a new child into an existing parent. 535e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 536e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 537e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 538e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 539e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 540e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 541bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener) 542e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 54319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml, 544e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final int index, IAnimationListener listener) { 545c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet checkLock(); 546c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 547b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 548b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet 549c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // create a block parser for the XML 550b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(childXml, context, 551c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet false /* platformResourceFlag */); 552c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 553c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // inflate the child without adding it to the root since we want to control where it'll 554c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // get added. We do pass the parentView however to ensure that the layoutParams will 555c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // be created correctly. 556e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/); 557c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 558e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet invalidateRenderingSize(); 559e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 560e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 561e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new AnimationThread(this, "insertChild", listener) { 562e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 563e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 56419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result preAnimation() { 565e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parentView.setLayoutTransition(new LayoutTransition()); 566e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return addView(parentView, child, index); 567e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 568e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 569e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 570e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet public void postAnimation() { 571e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parentView.setLayoutTransition(null); 572e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 573e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet }.start(); 574e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 575e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 57619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(child); 5779eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 5789eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 579e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // add it to the parentView in the correct location 58019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet Result result = addView(parentView, child, index); 581e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (result.isSuccess() == false) { 582e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 583e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 584c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 5855a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 586c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet if (result.isSuccess()) { 587e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet result = result.getCopyWithData(child); 588c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet } 589c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet 590c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet return result; 591c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 592c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 593e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 594e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Adds a given view to a given parent at a given index. 595e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 596e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param parent the parent to receive the view 597e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param view the view to add to the parent 598e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param index the index where to do the add. 599e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 60019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 60119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 602e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 603e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 60419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private Result addView(ViewGroup parent, View view, int index) { 605e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet try { 606e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.addView(view, index); 60719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 608e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } catch (UnsupportedOperationException e) { 609e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 61019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 611e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 612e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 613e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 614e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 615e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Moves a view to a new parent at a given location 616e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 617e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 618e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 619e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 620e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 621e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 622bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener) 623e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 6242b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public Result moveChild(final ViewGroup newParentView, final View childView, final int index, 625479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet Map<String, String> layoutParamsMap, final IAnimationListener listener) { 626c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet checkLock(); 627c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 628e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet invalidateRenderingSize(); 629e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 63001811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet LayoutParams layoutParams = null; 631e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (layoutParamsMap != null) { 632e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // need to create a new LayoutParams object for the new parent. 6332b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet layoutParams = newParentView.generateLayoutParams( 634e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new BridgeLayoutParamsMapAttributes(layoutParamsMap)); 635e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 6369eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 6372b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // get the current parent of the view that needs to be moved. 6382b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet final ViewGroup previousParent = (ViewGroup) childView.getParent(); 6392b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 640e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 641e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final LayoutParams params = layoutParams; 64201811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 643479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // there is no support for animating views across layouts, so in case the new and old 644479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // parent views are different we fake the animation through a no animation thread. 645479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (previousParent != newParentView) { 646479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet new Thread("not animated moveChild") { 647479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 648479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public void run() { 649479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet Result result = moveView(previousParent, newParentView, childView, index, 650479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet params); 651479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (result.isSuccess() == false) { 652479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 653479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 654479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 655479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // ready to do the work, acquire the scene. 656479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet result = acquire(250); 657479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (result.isSuccess() == false) { 658479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 659479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet return; 660479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 661479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 662479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet try { 6635a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 664479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (result.isSuccess()) { 665479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.onNewFrame(RenderSessionImpl.this.getSession()); 666479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 667479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } finally { 668479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet release(); 669479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 670479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 671479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 6722b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 673479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet }.start(); 674479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } else { 675479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet new AnimationThread(this, "moveChild", listener) { 6762b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 677479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 678479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public Result preAnimation() { 679479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // set up the transition for the parent. 680479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet LayoutTransition transition = new LayoutTransition(); 681479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.setLayoutTransition(transition); 6827550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet 683479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // tweak the animation durations and start delays (to match the duration of 684479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // animation playing just before). 685479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // Note: Cannot user Animation.setDuration() directly. Have to set it 686479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // on the LayoutTransition. 687479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.DISAPPEARING, 100); 688479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // CHANGE_DISAPPEARING plays after DISAPPEARING 689479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100); 69001811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 691479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100); 692479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 693479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100); 694479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // CHANGE_APPEARING plays after CHANGE_APPEARING 695479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setStartDelay(LayoutTransition.APPEARING, 100); 696479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 697479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.APPEARING, 100); 698479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 699479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet return moveView(previousParent, newParentView, childView, index, params); 700479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 701479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 702479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 703479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public void postAnimation() { 704479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.setLayoutTransition(null); 705479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParentView.setLayoutTransition(null); 706479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 707479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet }.start(); 708479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 709e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 710e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 71119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(layoutParams); 712c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 713c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 7142b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet Result result = moveView(previousParent, newParentView, childView, index, layoutParams); 715e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (result.isSuccess() == false) { 716e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 717e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 718c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 7195a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 72001811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet if (layoutParams != null && result.isSuccess()) { 721e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet result = result.getCopyWithData(layoutParams); 72201811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet } 72301811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 72401811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet return result; 725c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 726c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 727e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 728e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Moves a View from its current parent to a new given parent at a new given location, with 729e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * an optional new {@link LayoutParams} instance 730e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 7312b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet * @param previousParent the previous parent, still owning the child at the time of the call. 7322b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet * @param newParent the new parent 733479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet * @param movedView the view to move 734e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param index the new location in the new parent 735e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param params an option (can be null) {@link LayoutParams} instance. 736e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 73719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 73819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 739e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 740e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 741479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet private Result moveView(ViewGroup previousParent, final ViewGroup newParent, 742479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet final View movedView, final int index, final LayoutParams params) { 7439eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet try { 7442b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // check if there is a transition on the previousParent. 745479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet LayoutTransition previousTransition = previousParent.getLayoutTransition(); 746479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (previousTransition != null) { 7477550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // in this case there is an animation. This means we have to wait for the child's 7487550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // parent reference to be null'ed out so that we can add it to the new parent. 7497550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // It is technically removed right before the DISAPPEARING animation is done (if 7507550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // the animation of this type is not null, otherwise it's after which is impossible 7517550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // to handle). 7527550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // Because there is no move animation, if the new parent is the same as the old 7537550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before 7547550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // adding the child or the child will appear in its new location before the 7557550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // other children have made room for it. 7562b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 7572b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add a listener to the transition to be notified of the actual removal. 758479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousTransition.addTransitionListener(new TransitionListener() { 759479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet private int mChangeDisappearingCount = 0; 7602b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 7612b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public void startTransition(LayoutTransition transition, ViewGroup container, 7622b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet View view, int transitionType) { 763479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { 764479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount++; 765479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 7662b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 767e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 7682b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public void endTransition(LayoutTransition transition, ViewGroup container, 7692b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet View view, int transitionType) { 770479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { 771479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount--; 772479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 773479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 774479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING && 775479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount == 0) { 7762b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add it to the parentView in the correct location 7772b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet if (params != null) { 778479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index, params); 7792b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } else { 780479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index); 7812b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 7822b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 7832b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 7842b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet }); 7852b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 7862b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // remove the view from the current parent. 787479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.removeView(movedView); 7882b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 7892b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // and return since adding the view to the new parent is done in the listener. 7902b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet return SUCCESS.createResult(); 791e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } else { 7922b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // standard code with no animation. pretty simple. 793479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.removeView(movedView); 794e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 7952b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add it to the parentView in the correct location 7962b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet if (params != null) { 797479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index, params); 7982b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } else { 799479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index); 8002b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8012b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 8022b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet return SUCCESS.createResult(); 8032b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8049eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } catch (UnsupportedOperationException e) { 8059eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 80619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 807c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 808e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 809e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 810e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 811e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Removes a child from its current parent. 812e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 813e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 814e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 815e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 816e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 817e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 818bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#removeChild(Object, IAnimationListener) 819e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 82019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result removeChild(final View childView, IAnimationListener listener) { 821e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet checkLock(); 822c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 8239eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet invalidateRenderingSize(); 8249eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 825e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final ViewGroup parent = (ViewGroup) childView.getParent(); 826e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 827e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 828e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new AnimationThread(this, "moveChild", listener) { 829e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 830e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 83119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result preAnimation() { 832e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.setLayoutTransition(new LayoutTransition()); 833e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return removeView(parent, childView); 834e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 835e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 836e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 837e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet public void postAnimation() { 838e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.setLayoutTransition(null); 839e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 840e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet }.start(); 841e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 842e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 84319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 844e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 845e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 84619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet Result result = removeView(parent, childView); 847e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (result.isSuccess() == false) { 848e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 849e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 850e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 8515a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet return render(false /*freshRender*/); 8522eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 8532eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 8542eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet /** 855e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Removes a given view from its current parent. 856e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 857e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param view the view to remove from its parent 858e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 85919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 86019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 861e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 862e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 86319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private Result removeView(ViewGroup parent, View view) { 864e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet try { 865e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.removeView(view); 86619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 867e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } catch (UnsupportedOperationException e) { 868e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 86919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 870e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 871e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 872e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 8732eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 87416584225125acba18b74920b902c798dfead0328Xavier Ducrohet private void findBackground(RenderResources resources) { 875b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet if (getParams().isBgColorOverridden() == false) { 87616584225125acba18b74920b902c798dfead0328Xavier Ducrohet mWindowBackground = resources.findItemInTheme("windowBackground"); 87716584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (mWindowBackground != null) { 87816584225125acba18b74920b902c798dfead0328Xavier Ducrohet mWindowBackground = resources.resolveResValue(mWindowBackground); 87916584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 88016584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 88116584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 882c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 88316584225125acba18b74920b902c798dfead0328Xavier Ducrohet private boolean isTabletUi() { 884b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet return getParams().getConfigScreenSize() == ScreenSize.XLARGE; 88516584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 886c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 88716584225125acba18b74920b902c798dfead0328Xavier Ducrohet private void findStatusBar(RenderResources resources, DisplayMetrics metrics) { 88816584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (isTabletUi() == false) { 88916584225125acba18b74920b902c798dfead0328Xavier Ducrohet boolean windowFullscreen = getBooleanThemeValue(resources, 89016584225125acba18b74920b902c798dfead0328Xavier Ducrohet "windowFullscreen", false /*defaultValue*/); 89116584225125acba18b74920b902c798dfead0328Xavier Ducrohet 892bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (windowFullscreen == false && mWindowIsFloating == false) { 89316584225125acba18b74920b902c798dfead0328Xavier Ducrohet // default value 89416584225125acba18b74920b902c798dfead0328Xavier Ducrohet mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT; 89516584225125acba18b74920b902c798dfead0328Xavier Ducrohet 89616584225125acba18b74920b902c798dfead0328Xavier Ducrohet // get the real value 89735ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN, 89816584225125acba18b74920b902c798dfead0328Xavier Ducrohet "status_bar_height"); 89916584225125acba18b74920b902c798dfead0328Xavier Ducrohet 90016584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (value != null) { 90116584225125acba18b74920b902c798dfead0328Xavier Ducrohet TypedValue typedValue = ResourceHelper.getValue(value.getValue()); 90216584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (typedValue != null) { 90316584225125acba18b74920b902c798dfead0328Xavier Ducrohet // compute the pixel value based on the display metrics 90416584225125acba18b74920b902c798dfead0328Xavier Ducrohet mStatusBarSize = (int)typedValue.getDimension(metrics); 90516584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 90616584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 90716584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 90816584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 90916584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 91016584225125acba18b74920b902c798dfead0328Xavier Ducrohet 911bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private void findActionBar(RenderResources resources, DisplayMetrics metrics) { 912bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (mWindowIsFloating) { 913bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet return; 91416584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 91516584225125acba18b74920b902c798dfead0328Xavier Ducrohet 91616584225125acba18b74920b902c798dfead0328Xavier Ducrohet boolean windowActionBar = getBooleanThemeValue(resources, 91716584225125acba18b74920b902c798dfead0328Xavier Ducrohet "windowActionBar", true /*defaultValue*/); 91816584225125acba18b74920b902c798dfead0328Xavier Ducrohet 91916584225125acba18b74920b902c798dfead0328Xavier Ducrohet // if there's a value and it's false (default is true) 92016584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (windowActionBar) { 921c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 922c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // default size of the window title bar 923bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet mActionBarSize = DEFAULT_TITLE_BAR_HEIGHT; 924c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 925c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get value from the theme. 92616584225125acba18b74920b902c798dfead0328Xavier Ducrohet ResourceValue value = resources.findItemInTheme("actionBarSize"); 927c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 928c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // resolve it 92916584225125acba18b74920b902c798dfead0328Xavier Ducrohet value = resources.resolveResValue(value); 930c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 931c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (value != null) { 932c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get the numerical value, if available 933c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet TypedValue typedValue = ResourceHelper.getValue(value.getValue()); 934c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (typedValue != null) { 935c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // compute the pixel value based on the display metrics 936bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet mActionBarSize = (int)typedValue.getDimension(metrics); 937c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 938c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 939bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } else { 940bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // action bar overrides title bar so only look for this one if action bar is hidden 941bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet boolean windowNoTitle = getBooleanThemeValue(resources, 942bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet "windowNoTitle", false /*defaultValue*/); 943c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 944bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (windowNoTitle == false) { 94516584225125acba18b74920b902c798dfead0328Xavier Ducrohet 946bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // default size of the window title bar 947bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet mTitleBarSize = DEFAULT_TITLE_BAR_HEIGHT; 94816584225125acba18b74920b902c798dfead0328Xavier Ducrohet 949bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // get value from the theme. 950bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet ResourceValue value = resources.findItemInTheme("windowTitleSize"); 95116584225125acba18b74920b902c798dfead0328Xavier Ducrohet 952bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // resolve it 953bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet value = resources.resolveResValue(value); 954c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 955bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (value != null) { 956bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // get the numerical value, if available 957bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet TypedValue typedValue = ResourceHelper.getValue(value.getValue()); 958bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (typedValue != null) { 959bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // compute the pixel value based on the display metrics 960bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet mTitleBarSize = (int)typedValue.getDimension(metrics); 961bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 96216584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 96316584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 964bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 96516584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 96616584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 96716584225125acba18b74920b902c798dfead0328Xavier Ducrohet 96816584225125acba18b74920b902c798dfead0328Xavier Ducrohet private void findSystemBar(RenderResources resources, DisplayMetrics metrics) { 969bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (isTabletUi() && mWindowIsFloating == false) { 970c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 971c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // default value 972bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet mSystemBarSize = 48; // ?? 973c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 974d1d6fafc7fc63543b10552dadf202dd6fa40fe6bXavier Ducrohet // get the real value 97535ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN, 97616584225125acba18b74920b902c798dfead0328Xavier Ducrohet "status_bar_height"); 97716584225125acba18b74920b902c798dfead0328Xavier Ducrohet 978c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (value != null) { 979c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet TypedValue typedValue = ResourceHelper.getValue(value.getValue()); 980c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (typedValue != null) { 981c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // compute the pixel value based on the display metrics 98216584225125acba18b74920b902c798dfead0328Xavier Ducrohet mSystemBarSize = (int)typedValue.getDimension(metrics); 983c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 984c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 98516584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 98616584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 98716584225125acba18b74920b902c798dfead0328Xavier Ducrohet 98816584225125acba18b74920b902c798dfead0328Xavier Ducrohet private boolean getBooleanThemeValue(RenderResources resources, 98916584225125acba18b74920b902c798dfead0328Xavier Ducrohet String name, boolean defaultValue) { 99016584225125acba18b74920b902c798dfead0328Xavier Ducrohet 99116584225125acba18b74920b902c798dfead0328Xavier Ducrohet // get the title bar flag from the current theme. 99216584225125acba18b74920b902c798dfead0328Xavier Ducrohet ResourceValue value = resources.findItemInTheme(name); 99316584225125acba18b74920b902c798dfead0328Xavier Ducrohet 99416584225125acba18b74920b902c798dfead0328Xavier Ducrohet // because it may reference something else, we resolve it. 99516584225125acba18b74920b902c798dfead0328Xavier Ducrohet value = resources.resolveResValue(value); 996c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 99716584225125acba18b74920b902c798dfead0328Xavier Ducrohet // if there's no value, return the default. 99816584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (value == null || value.getValue() == null) { 99916584225125acba18b74920b902c798dfead0328Xavier Ducrohet return defaultValue; 1000c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1001c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 100216584225125acba18b74920b902c798dfead0328Xavier Ducrohet return XmlUtils.convertValueToBoolean(value.getValue(), defaultValue); 1003c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1004c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1005c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 1006c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Post process on a view hierachy that was just inflated. 1007c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p/>At the moment this only support TabHost: If {@link TabHost} is detected, look for the 1008c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically 1009c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * based on the content of the {@link FrameLayout}. 1010c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param view the root view to process. 1011c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param projectCallback callback to the project. 1012c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 1013c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private void postInflateProcess(View view, IProjectCallback projectCallback) 1014c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throws PostInflateException { 1015c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (view instanceof TabHost) { 1016c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet setupTabHost((TabHost)view, projectCallback); 101731fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet } else if (view instanceof QuickContactBadge) { 101831fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet QuickContactBadge badge = (QuickContactBadge) view; 101931fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet badge.setImageToDefault(); 1020c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } else if (view instanceof ViewGroup) { 1021c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet ViewGroup group = (ViewGroup)view; 1022c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet final int count = group.getChildCount(); 1023c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet for (int c = 0 ; c < count ; c++) { 1024c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet View child = group.getChildAt(c); 1025c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet postInflateProcess(child, projectCallback); 1026c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1027c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1028c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1029c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1030c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 1031c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Sets up a {@link TabHost} object. 1032c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param tabHost the TabHost to setup. 1033c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param projectCallback The project callback object to access the project R class. 1034c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @throws PostInflateException 1035c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 1036c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private void setupTabHost(TabHost tabHost, IProjectCallback projectCallback) 1037c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throws PostInflateException { 1038c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // look for the TabWidget, and the FrameLayout. They have their own specific names 1039c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet View v = tabHost.findViewById(android.R.id.tabs); 1040c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1041c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (v == null) { 1042c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException( 1043c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a TabWidget with id \"android:id/tabs\".\n"); 1044c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1045c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1046c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if ((v instanceof TabWidget) == false) { 1047c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException(String.format( 1048c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a TabWidget with id \"android:id/tabs\".\n" + 1049c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName())); 1050c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1051c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1052c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet v = tabHost.findViewById(android.R.id.tabcontent); 1053c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1054c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (v == null) { 1055c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // TODO: see if we can fake tabs even without the FrameLayout (same below when the framelayout is empty) 1056c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException( 1057c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a FrameLayout with id \"android:id/tabcontent\"."); 1058c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1059c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1060c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if ((v instanceof FrameLayout) == false) { 1061c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException(String.format( 1062c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" + 1063c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName())); 1064c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1065c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1066c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet FrameLayout content = (FrameLayout)v; 1067c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1068c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // now process the content of the framelayout and dynamically create tabs for it. 1069c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet final int count = content.getChildCount(); 1070c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1071c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // this must be called before addTab() so that the TabHost searches its TabWidget 1072c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // and FrameLayout. 1073c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet tabHost.setup(); 1074c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1075796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye if (count == 0) { 1076796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye // Create a dummy child to get a single tab 1077796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye TabSpec spec = tabHost.newTabSpec("tag").setIndicator("Tab Label", 1078796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye tabHost.getResources().getDrawable(android.R.drawable.ic_menu_info_details)) 1079796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye .setContent(new TabHost.TabContentFactory() { 1080796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye public View createTabContent(String tag) { 1081b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet return new LinearLayout(getContext()); 1082796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } 1083796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye }); 1084796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye tabHost.addTab(spec); 1085796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye return; 1086796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } else { 1087796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye // for each child of the framelayout, add a new TabSpec 1088796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye for (int i = 0 ; i < count ; i++) { 1089796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye View child = content.getChildAt(i); 1090796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye String tabSpec = String.format("tab_spec%d", i+1); 1091796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye int id = child.getId(); 1092b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet Pair<ResourceType, String> resource = projectCallback.resolveResourceId(id); 1093796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye String name; 1094796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye if (resource != null) { 1095b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet name = resource.getSecond(); 1096796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } else { 1097796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye name = String.format("Tab %d", i+1); // default name if id is unresolved. 1098796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } 1099796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id)); 1100c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1101c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1102c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1103c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1104bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private List<ViewInfo> startVisitingViews(View view, int offset) { 1105bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (view == null) { 1106bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet return null; 1107bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 1108bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 1109bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // adjust the offset to this view. 1110bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet offset += view.getTop(); 1111bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 1112bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (view == mContentRoot) { 1113bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet return visitAllChildren(mContentRoot, offset); 1114bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 1115bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 1116bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // otherwise, look for mContentRoot in the children 1117bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (view instanceof ViewGroup) { 1118bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet ViewGroup group = ((ViewGroup) view); 1119bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 1120bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet for (int i = 0; i < group.getChildCount(); i++) { 1121bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet List<ViewInfo> list = startVisitingViews(group.getChildAt(i), offset); 1122bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (list != null) { 1123bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet return list; 1124bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 1125bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 1126bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 1127bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 1128bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet return null; 1129bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 1130c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1131c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 1132c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Visits a View and its children and generate a {@link ViewInfo} containing the 1133c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * bounds of all the views. 1134c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param view the root View 1135bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @param offset an offset for the view bounds. 1136c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 1137bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private ViewInfo visit(View view, int offset) { 1138c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (view == null) { 1139c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return null; 1140c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1141c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1142c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet ViewInfo result = new ViewInfo(view.getClass().getName(), 1143b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet getContext().getViewKey(view), 114416584225125acba18b74920b902c798dfead0328Xavier Ducrohet view.getLeft(), view.getTop() + offset, view.getRight(), view.getBottom() + offset, 1145cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet view, view.getLayoutParams()); 1146c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1147c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (view instanceof ViewGroup) { 1148c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet ViewGroup group = ((ViewGroup) view); 1149bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet result.setChildren(visitAllChildren(group, 0 /*offset*/)); 1150c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1151c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1152c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return result; 1153c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1154c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1155bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet /** 1156bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * Visits all the children of a given ViewGroup generate a list of {@link ViewInfo} 1157bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * containing the bounds of all the views. 1158bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @param view the root View 1159bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @param offset an offset for the view bounds. 1160bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet */ 1161bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset) { 11627d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet if (viewGroup == null) { 11637d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet return null; 11647d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet } 11657d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet 11667d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet List<ViewInfo> children = new ArrayList<ViewInfo>(); 11677d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet for (int i = 0; i < viewGroup.getChildCount(); i++) { 1168bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet children.add(visit(viewGroup.getChildAt(i), offset)); 11697d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet } 11707d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet return children; 11717d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet } 11727d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet 11737d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet 11749eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private void invalidateRenderingSize() { 11759eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet mMeasuredScreenWidth = mMeasuredScreenHeight = -1; 11769eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 11779eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 1178c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet public BufferedImage getImage() { 1179c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return mImage; 1180c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1181c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 118216584225125acba18b74920b902c798dfead0328Xavier Ducrohet public boolean isAlphaChannelImage() { 118316584225125acba18b74920b902c798dfead0328Xavier Ducrohet return mIsAlphaChannelImage; 118416584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 118516584225125acba18b74920b902c798dfead0328Xavier Ducrohet 11867d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet public List<ViewInfo> getViewInfos() { 11877d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet return mViewInfoList; 1188c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1189cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet 119019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Map<String, String> getDefaultProperties(Object viewObject) { 1191b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet return getContext().getDefaultPropMap(viewObject); 1192cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet } 1193c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 119419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public void setScene(RenderSession session) { 119519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet mScene = session; 1196c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 1197c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 119819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public RenderSession getSession() { 1199c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet return mScene; 1200c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 1201c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet} 1202