RenderSessionImpl.java revision 10df650f0d4bdf086dae9ac29fafd8a1ded06c23
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 18502d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet mBlockParser = new BridgeXmlBlockParser( 18602d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet params.getLayoutDescription(), 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 207abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet // the view group that receives the window background. 208abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet ViewGroup backgroundView = null; 209abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet 210b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet if (mWindowIsFloating || params.isForceNoDecor()) { 211abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet backgroundView = mViewRoot = mContentRoot = new FrameLayout(context); 212bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } else { 213bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet /* 214bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * we're creating the following layout 215bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * 216bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet +-------------------------------------------------+ 217bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet | System bar (only in phone UI) | 218bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet +-------------------------------------------------+ 219abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet | (Layout with background drawable) | 220abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet | +---------------------------------------------+ | 221abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet | | Title/Action bar (optional) | | 222abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet | +---------------------------------------------+ | 223abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet | | Content, vertical extending | | 224abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet | | | | 225abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet | +---------------------------------------------+ | 226bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet +-------------------------------------------------+ 227bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet | System bar (only in tablet UI) | 228bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet +-------------------------------------------------+ 229bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 230bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet */ 231bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 232b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet LinearLayout topLayout = new LinearLayout(context); 233bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet mViewRoot = topLayout; 234bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet topLayout.setOrientation(LinearLayout.VERTICAL); 235bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 236bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (mStatusBarSize > 0) { 237bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // system bar 238bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet try { 239b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet PhoneSystemBar systemBar = new PhoneSystemBar(context, 240b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet params.getDensity()); 241bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet systemBar.setLayoutParams( 242bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet new LinearLayout.LayoutParams( 243bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet LayoutParams.MATCH_PARENT, mStatusBarSize)); 244bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet topLayout.addView(systemBar); 245bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } catch (XmlPullParserException e) { 246bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 247bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 248bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 249bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 250abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet LinearLayout backgroundLayout = new LinearLayout(context); 251abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet backgroundView = backgroundLayout; 252abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet backgroundLayout.setOrientation(LinearLayout.VERTICAL); 253abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( 254abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); 255abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet layoutParams.weight = 1; 256abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet backgroundLayout.setLayoutParams(layoutParams); 257abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet topLayout.addView(backgroundLayout); 258abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet 259abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet 260bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // if the theme says no title/action bar, then the size will be 0 261bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (mActionBarSize > 0) { 262bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet try { 263b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet FakeActionBar actionBar = new FakeActionBar(context, 264b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet params.getDensity(), 265b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet params.getAppLabel(), params.getAppIcon()); 266bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet actionBar.setLayoutParams( 267bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet new LinearLayout.LayoutParams( 268bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet LayoutParams.MATCH_PARENT, mActionBarSize)); 269abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet backgroundLayout.addView(actionBar); 270bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } catch (XmlPullParserException e) { 271bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 272bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 273bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } else if (mTitleBarSize > 0) { 274bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet try { 275b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet TitleBar titleBar = new TitleBar(context, 276b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet params.getDensity(), params.getAppLabel()); 277bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet titleBar.setLayoutParams( 278bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet new LinearLayout.LayoutParams( 279bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet LayoutParams.MATCH_PARENT, mTitleBarSize)); 280abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet backgroundLayout.addView(titleBar); 281bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } catch (XmlPullParserException e) { 282bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 283bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 284bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 285bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 286bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 287bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // content frame 288b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet mContentRoot = new FrameLayout(context); 289abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet layoutParams = new LinearLayout.LayoutParams( 290bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); 291b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet layoutParams.weight = 1; 292b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet mContentRoot.setLayoutParams(layoutParams); 293abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet backgroundLayout.addView(mContentRoot); 294bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 295bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (mSystemBarSize > 0) { 296bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // system bar 297bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet try { 298b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet TabletSystemBar systemBar = new TabletSystemBar(context, 299b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet params.getDensity()); 300bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet systemBar.setLayoutParams( 301bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet new LinearLayout.LayoutParams( 302bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet LayoutParams.MATCH_PARENT, mSystemBarSize)); 303bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet topLayout.addView(systemBar); 304bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } catch (XmlPullParserException e) { 305bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 306bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 307bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 308bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 309bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 310c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 311c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // Sets the project callback (custom view loader) to the fragment delegate so that 312c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // it can instantiate the custom Fragment. 313b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet Fragment_Delegate.setProjectCallback(params.getProjectCallback()); 314c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 315bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet View view = mInflater.inflate(mBlockParser, mContentRoot); 316c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 317c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet Fragment_Delegate.setProjectCallback(null); 318c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 319c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // set the AttachInfo on the root view. 320c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet AttachInfo info = new AttachInfo(new BridgeWindowSession(), new BridgeWindow(), 321c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet new Handler(), null); 322c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet info.mHasWindowFocus = true; 323c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet info.mWindowVisibility = View.VISIBLE; 324c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet info.mInTouchMode = false; // this is so that we can display selections. 32546a329244db12b6f7afc3c9a6409d420241a1058Xavier Ducrohet info.mHardwareAccelerated = false; 326c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet mViewRoot.dispatchAttachedToWindow(info, 0); 327c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 32833758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet // post-inflate process. For now this supports TabHost/TabWidget 329b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet postInflateProcess(view, params.getProjectCallback()); 33033758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet 331c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get the background drawable 332abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet if (mWindowBackground != null && backgroundView != null) { 333b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet Drawable d = ResourceHelper.getDrawable(mWindowBackground, context); 334abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet backgroundView.setBackgroundDrawable(d); 335c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 336c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 33719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 338c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (PostInflateException e) { 33919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_INFLATION.createResult(e.getMessage(), e); 340c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (Throwable e) { 341c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get the real cause of the exception. 342c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet Throwable t = e; 343c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet while (t.getCause() != null) { 344c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet t = t.getCause(); 345c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 346c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 34719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_INFLATION.createResult(t.getMessage(), t); 348c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 349c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 350c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 351c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 352c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Renders the scene. 353c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p> 3542eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 3552eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 3565a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * @param freshRender whether the render is a new one and should erase the existing bitmap (in 3575a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * the case where bitmaps are reused). This is typically needed when not playing 3585a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * animations.) 3595a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet * 3602eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 3612eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 3629eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet * 363bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderParams#getRenderingMode() 364bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#render(long) 365c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 3665a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet public Result render(boolean freshRender) { 3672eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet checkLock(); 3682eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 369b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet SessionParams params = getParams(); 370b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet 371c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet try { 372c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (mViewRoot == null) { 37319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_NOT_INFLATED.createResult(); 374c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 375c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // measure the views 376c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet int w_spec, h_spec; 377c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 378b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet RenderingMode renderingMode = params.getRenderingMode(); 379fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet 3809eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // only do the screen measure when needed. 3819eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet boolean newRenderSize = false; 3829eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (mMeasuredScreenWidth == -1) { 3839eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet newRenderSize = true; 384b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet mMeasuredScreenWidth = params.getScreenWidth(); 385b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet mMeasuredScreenHeight = params.getScreenHeight(); 3869eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 3879eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (renderingMode != RenderingMode.NORMAL) { 3889eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // measure the full size needed by the layout. 3899eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet w_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenWidth, 3909eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet renderingMode.isHorizExpand() ? 3919eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet MeasureSpec.UNSPECIFIED // this lets us know the actual needed size 3929eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet : MeasureSpec.EXACTLY); 39316584225125acba18b74920b902c798dfead0328Xavier Ducrohet h_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenHeight, 3949eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet renderingMode.isVertExpand() ? 3959eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet MeasureSpec.UNSPECIFIED // this lets us know the actual needed size 3969eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet : MeasureSpec.EXACTLY); 3979eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet mViewRoot.measure(w_spec, h_spec); 3989eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 3999eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (renderingMode.isHorizExpand()) { 4009eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet int neededWidth = mViewRoot.getChildAt(0).getMeasuredWidth(); 4019eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (neededWidth > mMeasuredScreenWidth) { 4029eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet mMeasuredScreenWidth = neededWidth; 4039eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 404fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet } 405c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 4069eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet if (renderingMode.isVertExpand()) { 4079eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet int neededHeight = mViewRoot.getChildAt(0).getMeasuredHeight(); 40816584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (neededHeight > mMeasuredScreenHeight) { 40916584225125acba18b74920b902c798dfead0328Xavier Ducrohet mMeasuredScreenHeight = neededHeight; 4109eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 411fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet } 412c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 413c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 414c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 415c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // remeasure with the size we need 416c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // This must always be done before the call to layout 4179eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet w_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenWidth, MeasureSpec.EXACTLY); 41833758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet h_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenHeight, MeasureSpec.EXACTLY); 419c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet mViewRoot.measure(w_spec, h_spec); 420c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 421c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // now do the layout. 42216584225125acba18b74920b902c798dfead0328Xavier Ducrohet mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); 423c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 42410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet if (params.isLayoutOnly()) { 42510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // delete the canvas and image to reset them on the next full rendering 42610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mImage = null; 42710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mCanvas = null; 42810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } else { 42910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mViewRoot.mAttachInfo.mTreeObserver.dispatchOnPreDraw(); 43010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet 43110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // draw the views 43210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // create the BufferedImage into which the layout will be rendered. 43310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet boolean newImage = false; 43410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet if (newRenderSize || mCanvas == null) { 43510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet if (params.getImageFactory() != null) { 43610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mImage = params.getImageFactory().getImage( 43710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenWidth, 43810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenHeight); 43910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } else { 44010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mImage = new BufferedImage( 44110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenWidth, 44210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenHeight, 44310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet BufferedImage.TYPE_INT_ARGB); 44410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet newImage = true; 44510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } 44610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet 44710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet if (params.isBgColorOverridden()) { 44810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // since we override the content, it's the same as if it was a new image. 44910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet newImage = true; 45010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet Graphics2D gc = mImage.createGraphics(); 45110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.setColor(new Color(params.getOverrideBgColor(), true)); 45210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.setComposite(AlphaComposite.Src); 45310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight); 45410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.dispose(); 45510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } 45610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet 45710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // create an Android bitmap around the BufferedImage 45810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage, 45910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet true /*isMutable*/, params.getDensity()); 46010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet 46110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // create a Canvas around the Android bitmap 46210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mCanvas = new Canvas(bitmap); 46310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mCanvas.setDensity(params.getDensity().getDpiValue()); 4649eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 465c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 46610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet if (freshRender && newImage == false) { 4679eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet Graphics2D gc = mImage.createGraphics(); 4685a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet gc.setComposite(AlphaComposite.Src); 469c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 47010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.setColor(new Color(0x00000000, true)); 47110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.fillRect(0, 0, 47210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mMeasuredScreenWidth, mMeasuredScreenHeight); 47316584225125acba18b74920b902c798dfead0328Xavier Ducrohet 47410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet // done 47510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet gc.dispose(); 47610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet } 47716584225125acba18b74920b902c798dfead0328Xavier Ducrohet 47810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet mViewRoot.draw(mCanvas); 4795a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet } 4805a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet 481bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet mViewInfoList = startVisitingViews(mViewRoot, 0); 482c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 483c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // success! 48419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 485c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } catch (Throwable e) { 486c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get the real cause of the exception. 487c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet Throwable t = e; 488c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet while (t.getCause() != null) { 489c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet t = t.getCause(); 490c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 491c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 49219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_UNKNOWN.createResult(t.getMessage(), t); 493c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 494c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 495c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 496c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 4972eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * Animate an object 4982eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * <p> 4992eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 5002eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * 5012eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 5022eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 503e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 504bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#animate(Object, String, boolean, IAnimationListener) 5052eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet */ 50619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result animate(Object targetObject, String animationName, 5072eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet boolean isFrameworkAnimation, IAnimationListener listener) { 5082eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet checkLock(); 5092eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 510b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 511b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet 5122eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet // find the animation file. 513ffb42f6c5043de226f02318a1311669d35a90711Xavier Ducrohet ResourceValue animationResource = null; 5142eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet int animationId = 0; 5152eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (isFrameworkAnimation) { 516b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet animationResource = context.getRenderResources().getFrameworkResource( 51735ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceType.ANIMATOR, animationName); 5182eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 519b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet animationId = Bridge.getResourceId(ResourceType.ANIMATOR, animationName); 5202eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5212eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } else { 522b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet animationResource = context.getRenderResources().getProjectResource( 52335ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceType.ANIMATOR, animationName); 5242eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 525b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet animationId = context.getProjectCallback().getResourceId( 52635ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceType.ANIMATOR, animationName); 5272eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5282eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5292eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 5302eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (animationResource != null) { 5312eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet try { 532b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet Animator anim = AnimatorInflater.loadAnimator(context, animationId); 5332eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet if (anim != null) { 5342eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet anim.setTarget(targetObject); 5352eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 536e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new PlayAnimationThread(anim, this, animationName, listener).start(); 5372eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 53819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 5392eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5402eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } catch (Exception e) { 541c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // get the real cause of the exception. 542c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet Throwable t = e; 543c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet while (t.getCause() != null) { 544c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet t = t.getCause(); 545c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 546c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 54719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_UNKNOWN.createResult(t.getMessage(), t); 5482eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5492eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 5502eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 55119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_ANIM_NOT_FOUND.createResult(); 552c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 553c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 554e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 555e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Insert a new child into an existing parent. 556e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 557e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 558e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 559e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 560e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 561e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 562bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener) 563e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 56419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml, 565e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final int index, IAnimationListener listener) { 566c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet checkLock(); 567c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 568b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet BridgeContext context = getContext(); 569b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet 570c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // create a block parser for the XML 57102d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( 57202d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet childXml, context, false /* platformResourceFlag */); 573c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 574c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // inflate the child without adding it to the root since we want to control where it'll 575c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // get added. We do pass the parentView however to ensure that the layoutParams will 576c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet // be created correctly. 577e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/); 57802d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet blockParser.ensurePopped(); 579c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 580e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet invalidateRenderingSize(); 581e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 582e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 583e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new AnimationThread(this, "insertChild", listener) { 584e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 585e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 58619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result preAnimation() { 587e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parentView.setLayoutTransition(new LayoutTransition()); 588e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return addView(parentView, child, index); 589e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 590e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 591e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 592e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet public void postAnimation() { 593e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parentView.setLayoutTransition(null); 594e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 595e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet }.start(); 596e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 597e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 59819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(child); 5999eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 6009eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 601e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // add it to the parentView in the correct location 60219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet Result result = addView(parentView, child, index); 603e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (result.isSuccess() == false) { 604e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 605e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 606c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 6075a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 608c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet if (result.isSuccess()) { 609e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet result = result.getCopyWithData(child); 610c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet } 611c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet 612c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet return result; 613c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 614c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 615e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 616e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Adds a given view to a given parent at a given index. 617e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 618e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param parent the parent to receive the view 619e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param view the view to add to the parent 620e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param index the index where to do the add. 621e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 62219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 62319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 624e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 625e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 62619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private Result addView(ViewGroup parent, View view, int index) { 627e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet try { 628e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.addView(view, index); 62919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 630e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } catch (UnsupportedOperationException e) { 631e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 63219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 633e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 634e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 635e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 636e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 637e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Moves a view to a new parent at a given location 638e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 639e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 640e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 641e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 642e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 643e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 644bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener) 645e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 6462b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public Result moveChild(final ViewGroup newParentView, final View childView, final int index, 647479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet Map<String, String> layoutParamsMap, final IAnimationListener listener) { 648c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet checkLock(); 649c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 650e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet invalidateRenderingSize(); 651e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 65201811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet LayoutParams layoutParams = null; 653e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (layoutParamsMap != null) { 654e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // need to create a new LayoutParams object for the new parent. 6552b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet layoutParams = newParentView.generateLayoutParams( 656e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new BridgeLayoutParamsMapAttributes(layoutParamsMap)); 657e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 6589eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 6592b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // get the current parent of the view that needs to be moved. 6602b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet final ViewGroup previousParent = (ViewGroup) childView.getParent(); 6612b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 662e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 663e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final LayoutParams params = layoutParams; 66401811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 665479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // there is no support for animating views across layouts, so in case the new and old 666479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // parent views are different we fake the animation through a no animation thread. 667479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (previousParent != newParentView) { 668479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet new Thread("not animated moveChild") { 669479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 670479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public void run() { 671479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet Result result = moveView(previousParent, newParentView, childView, index, 672479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet params); 673479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (result.isSuccess() == false) { 674479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 675479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 676479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 677479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // ready to do the work, acquire the scene. 678479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet result = acquire(250); 679479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (result.isSuccess() == false) { 680479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 681479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet return; 682479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 683479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 684479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet try { 6855a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 686479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (result.isSuccess()) { 687479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.onNewFrame(RenderSessionImpl.this.getSession()); 688479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 689479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } finally { 690479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet release(); 691479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 692479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 693479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet listener.done(result); 6942b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 695479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet }.start(); 696479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } else { 697479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet new AnimationThread(this, "moveChild", listener) { 6982b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 699479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 700479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public Result preAnimation() { 701479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // set up the transition for the parent. 702479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet LayoutTransition transition = new LayoutTransition(); 703479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.setLayoutTransition(transition); 7047550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet 705479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // tweak the animation durations and start delays (to match the duration of 706479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // animation playing just before). 707479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // Note: Cannot user Animation.setDuration() directly. Have to set it 708479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // on the LayoutTransition. 709479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.DISAPPEARING, 100); 710479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // CHANGE_DISAPPEARING plays after DISAPPEARING 711479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100); 71201811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 713479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100); 714479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 715479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100); 716479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet // CHANGE_APPEARING plays after CHANGE_APPEARING 717479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setStartDelay(LayoutTransition.APPEARING, 100); 718479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 719479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet transition.setDuration(LayoutTransition.APPEARING, 100); 720479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 721479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet return moveView(previousParent, newParentView, childView, index, params); 722479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 723479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 724479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet @Override 725479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet public void postAnimation() { 726479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.setLayoutTransition(null); 727479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParentView.setLayoutTransition(null); 728479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 729479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet }.start(); 730479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 731e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 732e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 73319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(layoutParams); 734c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 735c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 7362b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet Result result = moveView(previousParent, newParentView, childView, index, layoutParams); 737e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (result.isSuccess() == false) { 738e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 739e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 740c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 7415a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet result = render(false /*freshRender*/); 74201811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet if (layoutParams != null && result.isSuccess()) { 743e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet result = result.getCopyWithData(layoutParams); 74401811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet } 74501811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet 74601811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet return result; 747c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 748c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 749e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 750e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Moves a View from its current parent to a new given parent at a new given location, with 751e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * an optional new {@link LayoutParams} instance 752e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 7532b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet * @param previousParent the previous parent, still owning the child at the time of the call. 7542b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet * @param newParent the new parent 755479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet * @param movedView the view to move 756e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param index the new location in the new parent 757e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param params an option (can be null) {@link LayoutParams} instance. 758e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 75919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 76019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 761e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 762e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 763479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet private Result moveView(ViewGroup previousParent, final ViewGroup newParent, 764479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet final View movedView, final int index, final LayoutParams params) { 7659eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet try { 7662b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // check if there is a transition on the previousParent. 767479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet LayoutTransition previousTransition = previousParent.getLayoutTransition(); 768479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (previousTransition != null) { 7697550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // in this case there is an animation. This means we have to wait for the child's 7707550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // parent reference to be null'ed out so that we can add it to the new parent. 7717550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // It is technically removed right before the DISAPPEARING animation is done (if 7727550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // the animation of this type is not null, otherwise it's after which is impossible 7737550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // to handle). 7747550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // Because there is no move animation, if the new parent is the same as the old 7757550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before 7767550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // adding the child or the child will appear in its new location before the 7777550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet // other children have made room for it. 7782b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 7792b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add a listener to the transition to be notified of the actual removal. 780479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousTransition.addTransitionListener(new TransitionListener() { 781479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet private int mChangeDisappearingCount = 0; 7822b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 7832b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public void startTransition(LayoutTransition transition, ViewGroup container, 7842b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet View view, int transitionType) { 785479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { 786479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount++; 787479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 7882b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 789e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 7902b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet public void endTransition(LayoutTransition transition, ViewGroup container, 7912b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet View view, int transitionType) { 792479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) { 793479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount--; 794479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet } 795479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet 796479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet if (transitionType == LayoutTransition.CHANGE_DISAPPEARING && 797479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet mChangeDisappearingCount == 0) { 7982b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add it to the parentView in the correct location 7992b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet if (params != null) { 800479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index, params); 8012b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } else { 802479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index); 8032b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8042b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8052b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8062b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet }); 8072b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 8082b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // remove the view from the current parent. 809479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.removeView(movedView); 8102b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 8112b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // and return since adding the view to the new parent is done in the listener. 8122b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet return SUCCESS.createResult(); 813e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } else { 8142b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // standard code with no animation. pretty simple. 815479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet previousParent.removeView(movedView); 816e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 8172b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet // add it to the parentView in the correct location 8182b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet if (params != null) { 819479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index, params); 8202b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } else { 821479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet newParent.addView(movedView, index); 8222b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8232b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet 8242b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet return SUCCESS.createResult(); 8252b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet } 8269eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } catch (UnsupportedOperationException e) { 8279eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 82819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 829c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 830e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 831e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 832e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet /** 833e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Removes a child from its current parent. 834e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * <p> 835e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * {@link #acquire(long)} must have been called before this. 836e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 837e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @throws IllegalStateException if the current context is different than the one owned by 838e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * the scene, or if {@link #acquire(long)} was not called. 839e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 840bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @see RenderSession#removeChild(Object, IAnimationListener) 841e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 84219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result removeChild(final View childView, IAnimationListener listener) { 843e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet checkLock(); 844c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 8459eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet invalidateRenderingSize(); 8469eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 847e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet final ViewGroup parent = (ViewGroup) childView.getParent(); 848e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 849e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (listener != null) { 850e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet new AnimationThread(this, "moveChild", listener) { 851e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 852e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 85319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Result preAnimation() { 854e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.setLayoutTransition(new LayoutTransition()); 855e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return removeView(parent, childView); 856e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 857e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 858e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet @Override 859e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet public void postAnimation() { 860e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.setLayoutTransition(null); 861e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 862e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet }.start(); 863e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 864e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // always return success since the real status will come through the listener. 86519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 866e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 867e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 86819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet Result result = removeView(parent, childView); 869e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet if (result.isSuccess() == false) { 870e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet return result; 871e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 872e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 8735a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet return render(false /*freshRender*/); 8742eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet } 8752eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 8762eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet /** 877e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * Removes a given view from its current parent. 878e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 879e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * @param view the view to remove from its parent 880e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * 88119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * @return a Result with {@link Status#SUCCESS} or 88219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support 883e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet * adding views. 884e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet */ 88519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet private Result removeView(ViewGroup parent, View view) { 886e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet try { 887e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet parent.removeView(view); 88819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return SUCCESS.createResult(); 889e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } catch (UnsupportedOperationException e) { 890e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet // looks like this is a view class that doesn't support children manipulation! 89119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet return ERROR_VIEWGROUP_NO_CHILDREN.createResult(); 892e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 893e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet } 894e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet 8952eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet 89616584225125acba18b74920b902c798dfead0328Xavier Ducrohet private void findBackground(RenderResources resources) { 897b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet if (getParams().isBgColorOverridden() == false) { 89816584225125acba18b74920b902c798dfead0328Xavier Ducrohet mWindowBackground = resources.findItemInTheme("windowBackground"); 89916584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (mWindowBackground != null) { 90016584225125acba18b74920b902c798dfead0328Xavier Ducrohet mWindowBackground = resources.resolveResValue(mWindowBackground); 90116584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 90216584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 90316584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 904c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 90516584225125acba18b74920b902c798dfead0328Xavier Ducrohet private boolean isTabletUi() { 906b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet return getParams().getConfigScreenSize() == ScreenSize.XLARGE; 90716584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 908c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 90916584225125acba18b74920b902c798dfead0328Xavier Ducrohet private void findStatusBar(RenderResources resources, DisplayMetrics metrics) { 91016584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (isTabletUi() == false) { 91116584225125acba18b74920b902c798dfead0328Xavier Ducrohet boolean windowFullscreen = getBooleanThemeValue(resources, 91216584225125acba18b74920b902c798dfead0328Xavier Ducrohet "windowFullscreen", false /*defaultValue*/); 91316584225125acba18b74920b902c798dfead0328Xavier Ducrohet 914bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (windowFullscreen == false && mWindowIsFloating == false) { 91516584225125acba18b74920b902c798dfead0328Xavier Ducrohet // default value 91616584225125acba18b74920b902c798dfead0328Xavier Ducrohet mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT; 91716584225125acba18b74920b902c798dfead0328Xavier Ducrohet 91816584225125acba18b74920b902c798dfead0328Xavier Ducrohet // get the real value 91935ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN, 92016584225125acba18b74920b902c798dfead0328Xavier Ducrohet "status_bar_height"); 92116584225125acba18b74920b902c798dfead0328Xavier Ducrohet 92216584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (value != null) { 92316584225125acba18b74920b902c798dfead0328Xavier Ducrohet TypedValue typedValue = ResourceHelper.getValue(value.getValue()); 92416584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (typedValue != null) { 92516584225125acba18b74920b902c798dfead0328Xavier Ducrohet // compute the pixel value based on the display metrics 92616584225125acba18b74920b902c798dfead0328Xavier Ducrohet mStatusBarSize = (int)typedValue.getDimension(metrics); 92716584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 92816584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 92916584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 93016584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 93116584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 93216584225125acba18b74920b902c798dfead0328Xavier Ducrohet 933bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private void findActionBar(RenderResources resources, DisplayMetrics metrics) { 934bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (mWindowIsFloating) { 935bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet return; 93616584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 93716584225125acba18b74920b902c798dfead0328Xavier Ducrohet 93816584225125acba18b74920b902c798dfead0328Xavier Ducrohet boolean windowActionBar = getBooleanThemeValue(resources, 93916584225125acba18b74920b902c798dfead0328Xavier Ducrohet "windowActionBar", true /*defaultValue*/); 94016584225125acba18b74920b902c798dfead0328Xavier Ducrohet 94116584225125acba18b74920b902c798dfead0328Xavier Ducrohet // if there's a value and it's false (default is true) 94216584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (windowActionBar) { 943c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 944c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // default size of the window title bar 945bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet mActionBarSize = DEFAULT_TITLE_BAR_HEIGHT; 946c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 947c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get value from the theme. 94816584225125acba18b74920b902c798dfead0328Xavier Ducrohet ResourceValue value = resources.findItemInTheme("actionBarSize"); 949c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 950c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // resolve it 95116584225125acba18b74920b902c798dfead0328Xavier Ducrohet value = resources.resolveResValue(value); 952c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 953c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (value != null) { 954c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // get the numerical value, if available 955c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet TypedValue typedValue = ResourceHelper.getValue(value.getValue()); 956c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (typedValue != null) { 957c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // compute the pixel value based on the display metrics 958bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet mActionBarSize = (int)typedValue.getDimension(metrics); 959c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 960c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 961bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } else { 962bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // action bar overrides title bar so only look for this one if action bar is hidden 963bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet boolean windowNoTitle = getBooleanThemeValue(resources, 964bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet "windowNoTitle", false /*defaultValue*/); 965c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 966bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (windowNoTitle == false) { 96716584225125acba18b74920b902c798dfead0328Xavier Ducrohet 968bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // default size of the window title bar 969bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet mTitleBarSize = DEFAULT_TITLE_BAR_HEIGHT; 97016584225125acba18b74920b902c798dfead0328Xavier Ducrohet 971bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // get value from the theme. 972bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet ResourceValue value = resources.findItemInTheme("windowTitleSize"); 97316584225125acba18b74920b902c798dfead0328Xavier Ducrohet 974bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // resolve it 975bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet value = resources.resolveResValue(value); 976c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 977bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (value != null) { 978bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // get the numerical value, if available 979bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet TypedValue typedValue = ResourceHelper.getValue(value.getValue()); 980bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (typedValue != null) { 981bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // compute the pixel value based on the display metrics 982bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet mTitleBarSize = (int)typedValue.getDimension(metrics); 983bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 98416584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 98516584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 986bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 98716584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 98816584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 98916584225125acba18b74920b902c798dfead0328Xavier Ducrohet 99016584225125acba18b74920b902c798dfead0328Xavier Ducrohet private void findSystemBar(RenderResources resources, DisplayMetrics metrics) { 991bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (isTabletUi() && mWindowIsFloating == false) { 992c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 993c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // default value 994bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet mSystemBarSize = 48; // ?? 995c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 996d1d6fafc7fc63543b10552dadf202dd6fa40fe6bXavier Ducrohet // get the real value 99735ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN, 99816584225125acba18b74920b902c798dfead0328Xavier Ducrohet "status_bar_height"); 99916584225125acba18b74920b902c798dfead0328Xavier Ducrohet 1000c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (value != null) { 1001c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet TypedValue typedValue = ResourceHelper.getValue(value.getValue()); 1002c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (typedValue != null) { 1003c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // compute the pixel value based on the display metrics 100416584225125acba18b74920b902c798dfead0328Xavier Ducrohet mSystemBarSize = (int)typedValue.getDimension(metrics); 1005c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1006c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 100716584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 100816584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 100916584225125acba18b74920b902c798dfead0328Xavier Ducrohet 101016584225125acba18b74920b902c798dfead0328Xavier Ducrohet private boolean getBooleanThemeValue(RenderResources resources, 101116584225125acba18b74920b902c798dfead0328Xavier Ducrohet String name, boolean defaultValue) { 101216584225125acba18b74920b902c798dfead0328Xavier Ducrohet 101316584225125acba18b74920b902c798dfead0328Xavier Ducrohet // get the title bar flag from the current theme. 101416584225125acba18b74920b902c798dfead0328Xavier Ducrohet ResourceValue value = resources.findItemInTheme(name); 101516584225125acba18b74920b902c798dfead0328Xavier Ducrohet 101616584225125acba18b74920b902c798dfead0328Xavier Ducrohet // because it may reference something else, we resolve it. 101716584225125acba18b74920b902c798dfead0328Xavier Ducrohet value = resources.resolveResValue(value); 1018c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 101916584225125acba18b74920b902c798dfead0328Xavier Ducrohet // if there's no value, return the default. 102016584225125acba18b74920b902c798dfead0328Xavier Ducrohet if (value == null || value.getValue() == null) { 102116584225125acba18b74920b902c798dfead0328Xavier Ducrohet return defaultValue; 1022c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1023c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 102416584225125acba18b74920b902c798dfead0328Xavier Ducrohet return XmlUtils.convertValueToBoolean(value.getValue(), defaultValue); 1025c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1026c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1027c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 1028c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Post process on a view hierachy that was just inflated. 1029c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * <p/>At the moment this only support TabHost: If {@link TabHost} is detected, look for the 1030c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically 1031c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * based on the content of the {@link FrameLayout}. 1032c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param view the root view to process. 1033c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param projectCallback callback to the project. 1034c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 1035c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private void postInflateProcess(View view, IProjectCallback projectCallback) 1036c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throws PostInflateException { 1037c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (view instanceof TabHost) { 1038c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet setupTabHost((TabHost)view, projectCallback); 103931fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet } else if (view instanceof QuickContactBadge) { 104031fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet QuickContactBadge badge = (QuickContactBadge) view; 104131fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet badge.setImageToDefault(); 1042c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } else if (view instanceof ViewGroup) { 1043c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet ViewGroup group = (ViewGroup)view; 1044c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet final int count = group.getChildCount(); 1045c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet for (int c = 0 ; c < count ; c++) { 1046c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet View child = group.getChildAt(c); 1047c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet postInflateProcess(child, projectCallback); 1048c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1049c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1050c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1051c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1052c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 1053c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Sets up a {@link TabHost} object. 1054c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param tabHost the TabHost to setup. 1055c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param projectCallback The project callback object to access the project R class. 1056c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @throws PostInflateException 1057c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 1058c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet private void setupTabHost(TabHost tabHost, IProjectCallback projectCallback) 1059c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throws PostInflateException { 1060c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // look for the TabWidget, and the FrameLayout. They have their own specific names 1061c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet View v = tabHost.findViewById(android.R.id.tabs); 1062c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1063c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (v == null) { 1064c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException( 1065c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a TabWidget with id \"android:id/tabs\".\n"); 1066c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1067c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1068c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if ((v instanceof TabWidget) == false) { 1069c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException(String.format( 1070c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a TabWidget with id \"android:id/tabs\".\n" + 1071c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName())); 1072c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1073c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1074c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet v = tabHost.findViewById(android.R.id.tabcontent); 1075c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1076c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (v == null) { 1077c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // TODO: see if we can fake tabs even without the FrameLayout (same below when the framelayout is empty) 1078c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException( 1079c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a FrameLayout with id \"android:id/tabcontent\"."); 1080c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1081c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1082c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if ((v instanceof FrameLayout) == false) { 1083c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet throw new PostInflateException(String.format( 1084c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" + 1085c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName())); 1086c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1087c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1088c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet FrameLayout content = (FrameLayout)v; 1089c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1090c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // now process the content of the framelayout and dynamically create tabs for it. 1091c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet final int count = content.getChildCount(); 1092c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1093c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // this must be called before addTab() so that the TabHost searches its TabWidget 1094c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet // and FrameLayout. 1095c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet tabHost.setup(); 1096c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1097796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye if (count == 0) { 1098796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye // Create a dummy child to get a single tab 1099796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye TabSpec spec = tabHost.newTabSpec("tag").setIndicator("Tab Label", 1100796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye tabHost.getResources().getDrawable(android.R.drawable.ic_menu_info_details)) 1101796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye .setContent(new TabHost.TabContentFactory() { 1102796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye public View createTabContent(String tag) { 1103b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet return new LinearLayout(getContext()); 1104796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } 1105796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye }); 1106796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye tabHost.addTab(spec); 1107796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye return; 1108796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } else { 1109796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye // for each child of the framelayout, add a new TabSpec 1110796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye for (int i = 0 ; i < count ; i++) { 1111796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye View child = content.getChildAt(i); 1112796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye String tabSpec = String.format("tab_spec%d", i+1); 1113796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye int id = child.getId(); 1114b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet Pair<ResourceType, String> resource = projectCallback.resolveResourceId(id); 1115796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye String name; 1116796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye if (resource != null) { 1117b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet name = resource.getSecond(); 1118796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } else { 1119796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye name = String.format("Tab %d", i+1); // default name if id is unresolved. 1120796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye } 1121796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id)); 1122c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1123c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1124c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1125c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1126bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private List<ViewInfo> startVisitingViews(View view, int offset) { 1127bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (view == null) { 1128bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet return null; 1129bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 1130bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 1131bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // adjust the offset to this view. 1132bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet offset += view.getTop(); 1133bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 1134bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (view == mContentRoot) { 1135bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet return visitAllChildren(mContentRoot, offset); 1136bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 1137bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 1138bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // otherwise, look for mContentRoot in the children 1139bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (view instanceof ViewGroup) { 1140bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet ViewGroup group = ((ViewGroup) view); 1141bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 1142bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet for (int i = 0; i < group.getChildCount(); i++) { 1143bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet List<ViewInfo> list = startVisitingViews(group.getChildAt(i), offset); 1144bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (list != null) { 1145bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet return list; 1146bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 1147bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 1148bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 1149bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 1150bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet return null; 1151bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 1152c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1153c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet /** 1154c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Visits a View and its children and generate a {@link ViewInfo} containing the 1155c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * bounds of all the views. 1156c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * @param view the root View 1157bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @param offset an offset for the view bounds. 1158c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */ 1159bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private ViewInfo visit(View view, int offset) { 1160c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (view == null) { 1161c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return null; 1162c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1163c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1164c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet ViewInfo result = new ViewInfo(view.getClass().getName(), 1165b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet getContext().getViewKey(view), 116616584225125acba18b74920b902c798dfead0328Xavier Ducrohet view.getLeft(), view.getTop() + offset, view.getRight(), view.getBottom() + offset, 1167cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet view, view.getLayoutParams()); 1168c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1169c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet if (view instanceof ViewGroup) { 1170c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet ViewGroup group = ((ViewGroup) view); 1171bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet result.setChildren(visitAllChildren(group, 0 /*offset*/)); 1172c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1173c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1174c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return result; 1175c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1176c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 1177bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet /** 1178bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * Visits all the children of a given ViewGroup generate a list of {@link ViewInfo} 1179bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * containing the bounds of all the views. 1180bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @param view the root View 1181bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @param offset an offset for the view bounds. 1182bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet */ 1183bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset) { 11847d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet if (viewGroup == null) { 11857d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet return null; 11867d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet } 11877d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet 11887d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet List<ViewInfo> children = new ArrayList<ViewInfo>(); 11897d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet for (int i = 0; i < viewGroup.getChildCount(); i++) { 1190bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet children.add(visit(viewGroup.getChildAt(i), offset)); 11917d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet } 11927d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet return children; 11937d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet } 11947d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet 11957d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet 11969eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet private void invalidateRenderingSize() { 11979eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet mMeasuredScreenWidth = mMeasuredScreenHeight = -1; 11989eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet } 11999eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet 1200c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet public BufferedImage getImage() { 1201c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet return mImage; 1202c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1203c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet 120416584225125acba18b74920b902c798dfead0328Xavier Ducrohet public boolean isAlphaChannelImage() { 120516584225125acba18b74920b902c798dfead0328Xavier Ducrohet return mIsAlphaChannelImage; 120616584225125acba18b74920b902c798dfead0328Xavier Ducrohet } 120716584225125acba18b74920b902c798dfead0328Xavier Ducrohet 12087d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet public List<ViewInfo> getViewInfos() { 12097d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet return mViewInfoList; 1210c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet } 1211cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet 121219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public Map<String, String> getDefaultProperties(Object viewObject) { 1213b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet return getContext().getDefaultPropMap(viewObject); 1214cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet } 1215c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 121619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public void setScene(RenderSession session) { 121719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet mScene = session; 1218c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 1219c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet 122019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet public RenderSession getSession() { 1221c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet return mScene; 1222c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet } 1223c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet} 1224