RenderSessionImpl.java revision 49ce36e1754243eedc124b4f7e68af1b458c821c
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
26d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Guptaimport com.android.annotations.NonNull;
27d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Guptaimport com.android.annotations.Nullable;
282fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.ide.common.rendering.api.AdapterBinding;
29891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport com.android.ide.common.rendering.api.HardwareConfig;
3019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.IAnimationListener;
3119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.ILayoutPullParser;
3219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.IProjectCallback;
3370552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderResources;
3419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderSession;
352fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.ide.common.rendering.api.ResourceReference;
3619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.ResourceValue;
3719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.Result;
3819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.Result.Status;
3946d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams;
401126422ee1f532d8582a4e3b56dbfe505c15e775Xavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams.RenderingMode;
418505c3870a17f41d23329344fe381cd9ff324bd2Deepanshu Guptaimport com.android.ide.common.rendering.api.StyleResourceValue;
4246d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport com.android.ide.common.rendering.api.ViewInfo;
43bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Guptaimport com.android.ide.common.rendering.api.ViewType;
44c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.internal.util.XmlUtils;
455ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Guptaimport com.android.internal.view.menu.ActionMenuItemView;
465ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Guptaimport com.android.internal.view.menu.BridgeMenuItemImpl;
475ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Guptaimport com.android.internal.view.menu.IconMenuItemView;
485ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Guptaimport com.android.internal.view.menu.ListMenuItemView;
495ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Guptaimport com.android.internal.view.menu.MenuItemImpl;
505ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Guptaimport com.android.internal.view.menu.MenuView;
512eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohetimport com.android.layoutlib.bridge.Bridge;
52c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeContext;
5301811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
54c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
5510bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Guptaimport com.android.layoutlib.bridge.android.SessionParamsFlags;
56d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Guptaimport com.android.layoutlib.bridge.android.support.RecyclerViewUtil;
57224e931fed1220f175805fdec71a882649270aa7Deepanshu Guptaimport com.android.layoutlib.bridge.bars.BridgeActionBar;
58224e931fed1220f175805fdec71a882649270aa7Deepanshu Guptaimport com.android.layoutlib.bridge.bars.AppCompatActionBar;
591076be31f1c14f39295cc2ce7a747ee9ad96ee73Deepanshu Guptaimport com.android.layoutlib.bridge.bars.Config;
60891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport com.android.layoutlib.bridge.bars.NavigationBar;
61891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport com.android.layoutlib.bridge.bars.StatusBar;
62bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohetimport com.android.layoutlib.bridge.bars.TitleBar;
63224e931fed1220f175805fdec71a882649270aa7Deepanshu Guptaimport com.android.layoutlib.bridge.bars.FrameworkActionBar;
642fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeAdapter;
652fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter;
664ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Guptaimport com.android.resources.Density;
6735ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohetimport com.android.resources.ResourceType;
68891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport com.android.resources.ScreenOrientation;
69b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohetimport com.android.util.Pair;
70c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
71bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohetimport org.xmlpull.v1.XmlPullParserException;
72bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
737f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.animation.AnimationThread;
74e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohetimport android.animation.Animator;
752eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohetimport android.animation.AnimatorInflater;
76e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohetimport android.animation.LayoutTransition;
772b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohetimport android.animation.LayoutTransition.TransitionListener;
78c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.app.Fragment_Delegate;
79c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Bitmap;
80c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Bitmap_Delegate;
81c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Canvas;
82c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.drawable.Drawable;
8310bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Guptaimport android.preference.Preference_Delegate;
84c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.util.DisplayMetrics;
85c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.util.TypedValue;
867f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.view.AttachInfo_Accessor;
877f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.view.BridgeInflater;
886dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.IWindowManager;
89891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport android.view.IWindowManagerImpl;
906dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.Surface;
91c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.View;
92c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.View.MeasureSpec;
9346d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport android.view.ViewGroup;
9401811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohetimport android.view.ViewGroup.LayoutParams;
9505b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohetimport android.view.ViewGroup.MarginLayoutParams;
96bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Guptaimport android.view.ViewParent;
976dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.WindowManagerGlobal_Delegate;
982fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AbsListView;
992fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AbsSpinner;
100bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Guptaimport android.widget.ActionMenuView;
1012fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AdapterView;
1022fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.ExpandableListView;
103c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.widget.FrameLayout;
104796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbyeimport android.widget.LinearLayout;
1052fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.ListView;
10631fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohetimport android.widget.QuickContactBadge;
107c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.widget.TabHost;
108796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbyeimport android.widget.TabHost.TabSpec;
10946d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport android.widget.TabWidget;
110c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1115a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohetimport java.awt.AlphaComposite;
112c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.Color;
113c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.Graphics2D;
114c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.image.BufferedImage;
115c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.ArrayList;
116c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.List;
117c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.Map;
118c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
119c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet/**
12019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * Class implementing the render session.
1211ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta * <p/>
12219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * A session is a stateful representation of a layout file. It is initialized with data coming
12319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then
124c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * be done on the layout.
125c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */
126b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetpublic class RenderSessionImpl extends RenderAction<SessionParams> {
127c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
128c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private static final int DEFAULT_TITLE_BAR_HEIGHT = 25;
129c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private static final int DEFAULT_STATUS_BAR_HEIGHT = 25;
130c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
131c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    // scene state
13219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    private RenderSession mScene;
133c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private BridgeXmlBlockParser mBlockParser;
134c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private BridgeInflater mInflater;
135ffb42f6c5043de226f02318a1311669d35a90711Xavier Ducrohet    private ResourceValue mWindowBackground;
136bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private ViewGroup mViewRoot;
137bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private FrameLayout mContentRoot;
1389eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet    private Canvas mCanvas;
1399eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet    private int mMeasuredScreenWidth = -1;
1409eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet    private int mMeasuredScreenHeight = -1;
141bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private boolean mIsAlphaChannelImage;
142bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private boolean mWindowIsFloating;
1438505c3870a17f41d23329344fe381cd9ff324bd2Deepanshu Gupta    private Boolean mIsThemeAppCompat;
14416584225125acba18b74920b902c798dfead0328Xavier Ducrohet
14516584225125acba18b74920b902c798dfead0328Xavier Ducrohet    private int mStatusBarSize;
146891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet    private int mNavigationBarSize;
147891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet    private int mNavigationBarOrientation = LinearLayout.HORIZONTAL;
148bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private int mTitleBarSize;
149bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private int mActionBarSize;
15016584225125acba18b74920b902c798dfead0328Xavier Ducrohet
151c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
152c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    // information being returned through the API
153c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private BufferedImage mImage;
1547d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet    private List<ViewInfo> mViewInfoList;
1554ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    private List<ViewInfo> mSystemViewInfoList;
156c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
157c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private static final class PostInflateException extends Exception {
158c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        private static final long serialVersionUID = 1L;
159c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
160c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        public PostInflateException(String message) {
161c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            super(message);
162c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
163c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
164c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
165c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
166c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * Creates a layout scene with all the information coming from the layout bridge API.
167c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * <p>
1681b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta     * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init(long)},
1691b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta     * which act as a
17019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     * call to {@link RenderSessionImpl#acquire(long)}
171c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     *
1721b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta     * @see Bridge#createSession(SessionParams)
173c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     */
1741126422ee1f532d8582a4e3b56dbfe505c15e775Xavier Ducrohet    public RenderSessionImpl(SessionParams params) {
175b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        super(new SessionParams(params));
1762eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    }
1772eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
1782eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    /**
1792eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * Initializes and acquires the scene, creating various Android objects such as context,
1802eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * inflater, and parser.
1812eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *
1822eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @param timeout the time to wait if another rendering is happening.
1832eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *
1842eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @return whether the scene was prepared
1852eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *
1862eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @see #acquire(long)
1872eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @see #release()
1882eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     */
189b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    @Override
19019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public Result init(long timeout) {
191b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        Result result = super.init(timeout);
1921ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta        if (!result.isSuccess()) {
1932eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            return result;
1942eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        }
195c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
196b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        SessionParams params = getParams();
197b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        BridgeContext context = getContext();
198c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1993a115628236ee9051518d4f96840cbb76070cf92Deepanshu Gupta
200b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        RenderResources resources = getParams().getResources();
201b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        DisplayMetrics metrics = getContext().getMetrics();
202c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
20316584225125acba18b74920b902c798dfead0328Xavier Ducrohet        // use default of true in case it's not found to use alpha by default
2048505c3870a17f41d23329344fe381cd9ff324bd2Deepanshu Gupta        mIsAlphaChannelImage  = getBooleanThemeValue(resources, "windowIsFloating", true, true);
2058505c3870a17f41d23329344fe381cd9ff324bd2Deepanshu Gupta        // FIXME: Find out why both variables are taking the same value.
2068505c3870a17f41d23329344fe381cd9ff324bd2Deepanshu Gupta        mWindowIsFloating = getBooleanThemeValue(resources, "windowIsFloating", true, true);
2072eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
20816584225125acba18b74920b902c798dfead0328Xavier Ducrohet        findBackground(resources);
20916584225125acba18b74920b902c798dfead0328Xavier Ducrohet        findStatusBar(resources, metrics);
210bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        findActionBar(resources, metrics);
211891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet        findNavigationBar(resources, metrics);
212c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
2136dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet        // FIXME: find those out, and possibly add them to the render params
2146dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet        boolean hasNavigationBar = true;
2151ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta        //noinspection ConstantConditions
2166dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet        IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(),
2176dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet                metrics, Surface.ROTATION_0,
21880f00c1f2375796dab09bc4ed5b7631c62f7e158John Spurlock                hasNavigationBar);
2196dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet        WindowManagerGlobal_Delegate.setWindowManagerService(iwm);
2206dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet
221c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        // build the inflater and parser.
222b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        mInflater = new BridgeInflater(context, params.getProjectCallback());
223b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        context.setBridgeInflater(mInflater);
2242eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
22502d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet        mBlockParser = new BridgeXmlBlockParser(
22602d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet                params.getLayoutDescription(), context, false /* platformResourceFlag */);
2272eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
228168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet        return SUCCESS.createResult();
229c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
230c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
231c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
232c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * Inflates the layout.
233c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * <p>
2342eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
2352eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *
2362eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
2372eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *      the scene, or if {@link #init(long)} was not called.
238c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     */
23919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public Result inflate() {
2402eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        checkLock();
2412eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
242c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        try {
243c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
244b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            SessionParams params = getParams();
245891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            HardwareConfig hardwareConfig = params.getHardwareConfig();
246b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            BridgeContext context = getContext();
24788db0ee2afbae38b53a0527506f0890914a7f115Deepanshu Gupta            boolean isRtl = Bridge.isLocaleRtl(params.getLocale());
2484ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            int layoutDirection = isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
249891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
250abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet            // the view group that receives the window background.
2511ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta            ViewGroup backgroundView;
252abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet
253b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            if (mWindowIsFloating || params.isForceNoDecor()) {
254abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                backgroundView = mViewRoot = mContentRoot = new FrameLayout(context);
2554ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                mViewRoot.setLayoutDirection(layoutDirection);
256bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            } else {
25742c7ce02f4023c94b315253754a20c20800be731Deepanshu Gupta                int simulatedPlatformVersion = params.getSimulatedPlatformVersion();
258891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                if (hasSoftwareButtons() && mNavigationBarOrientation == LinearLayout.VERTICAL) {
259891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    /*
260891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                     * This is a special case where the navigation bar is on the right.
261891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       +-------------------------------------------------+---+
262891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | Status bar (always)                             |   |
263891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       +-------------------------------------------------+   |
264891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | (Layout with background drawable)               |   |
265891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | +---------------------------------------------+ |   |
266891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | | Title/Action bar (optional)                 | |   |
267891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | +---------------------------------------------+ |   |
268891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | | Content, vertical extending                 | |   |
269891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | |                                             | |   |
270891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | +---------------------------------------------+ |   |
271891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       +-------------------------------------------------+---+
272891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
273891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       So we create a horizontal layout, with the nav bar on the right,
274891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       and the left part is the normal layout below without the nav bar at
275891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       the bottom
276891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                     */
277891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    LinearLayout topLayout = new LinearLayout(context);
2784ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    topLayout.setLayoutDirection(layoutDirection);
279891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    mViewRoot = topLayout;
280891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    topLayout.setOrientation(LinearLayout.HORIZONTAL);
281891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
28242c7ce02f4023c94b315253754a20c20800be731Deepanshu Gupta                    if (Config.showOnScreenNavBar(simulatedPlatformVersion)) {
2835a734548455e5bcc8a5fd6b3972017086d3c1287Deepanshu Gupta                        try {
2845a734548455e5bcc8a5fd6b3972017086d3c1287Deepanshu Gupta                            NavigationBar navigationBar = createNavigationBar(context,
28542c7ce02f4023c94b315253754a20c20800be731Deepanshu Gupta                                    hardwareConfig.getDensity(), isRtl, params.isRtlSupported(),
28642c7ce02f4023c94b315253754a20c20800be731Deepanshu Gupta                                    simulatedPlatformVersion);
2875a734548455e5bcc8a5fd6b3972017086d3c1287Deepanshu Gupta                            topLayout.addView(navigationBar);
2885a734548455e5bcc8a5fd6b3972017086d3c1287Deepanshu Gupta                        } catch (XmlPullParserException ignored) {
2895a734548455e5bcc8a5fd6b3972017086d3c1287Deepanshu Gupta                        }
290891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    }
291891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                }
292891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
293bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                /*
294bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                 * we're creating the following layout
295bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                 *
296bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                   +-------------------------------------------------+
297891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                   | Status bar (always)                             |
298bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                   +-------------------------------------------------+
299abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | (Layout with background drawable)               |
300abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | +---------------------------------------------+ |
301abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | | Title/Action bar (optional)                 | |
302abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | +---------------------------------------------+ |
303abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | | Content, vertical extending                 | |
304abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | |                                             | |
305abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | +---------------------------------------------+ |
306bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                   +-------------------------------------------------+
307891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                   | Navigation bar for soft buttons, maybe see above|
308bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                   +-------------------------------------------------+
309bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
310bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                 */
311bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
312b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                LinearLayout topLayout = new LinearLayout(context);
313bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                topLayout.setOrientation(LinearLayout.VERTICAL);
3144ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                topLayout.setLayoutDirection(layoutDirection);
315891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                // if we don't already have a view root this is it
316891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                if (mViewRoot == null) {
317891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    mViewRoot = topLayout;
318891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                } else {
3194ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    int topLayoutWidth =
3204ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                            params.getHardwareConfig().getScreenWidth() - mNavigationBarSize;
321891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
3224ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                            topLayoutWidth, LayoutParams.MATCH_PARENT);
323891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    topLayout.setLayoutParams(layoutParams);
324891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
325891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    // this is the case of soft buttons + vertical bar.
326891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    // this top layout is the first layout in the horizontal layout. see above)
32788db0ee2afbae38b53a0527506f0890914a7f115Deepanshu Gupta                    if (isRtl && params.isRtlSupported()) {
32888db0ee2afbae38b53a0527506f0890914a7f115Deepanshu Gupta                        // If RTL is enabled, layoutlib will mirror the layouts. So, add the
32988db0ee2afbae38b53a0527506f0890914a7f115Deepanshu Gupta                        // topLayout to the right of Navigation Bar and layoutlib will draw it
33088db0ee2afbae38b53a0527506f0890914a7f115Deepanshu Gupta                        // to the left.
33188db0ee2afbae38b53a0527506f0890914a7f115Deepanshu Gupta                        mViewRoot.addView(topLayout);
33288db0ee2afbae38b53a0527506f0890914a7f115Deepanshu Gupta                    } else {
33388db0ee2afbae38b53a0527506f0890914a7f115Deepanshu Gupta                        // Add the top layout to the left of the Navigation Bar.
33488db0ee2afbae38b53a0527506f0890914a7f115Deepanshu Gupta                        mViewRoot.addView(topLayout, 0);
33588db0ee2afbae38b53a0527506f0890914a7f115Deepanshu Gupta                    }
336891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                }
337bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
338bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                if (mStatusBarSize > 0) {
339bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    // system bar
340bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    try {
3414ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                        StatusBar statusBar = createStatusBar(context, hardwareConfig.getDensity(),
3425a734548455e5bcc8a5fd6b3972017086d3c1287Deepanshu Gupta                                layoutDirection, params.isRtlSupported(),
34342c7ce02f4023c94b315253754a20c20800be731Deepanshu Gupta                                simulatedPlatformVersion);
3444ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                        topLayout.addView(statusBar);
3451ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta                    } catch (XmlPullParserException ignored) {
346bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
347bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    }
348bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                }
349bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
350abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                LinearLayout backgroundLayout = new LinearLayout(context);
351abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                backgroundView = backgroundLayout;
352abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                backgroundLayout.setOrientation(LinearLayout.VERTICAL);
353abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
35435d56c0d67537e56fafebd8edf790026644fe8deDeepanshu Gupta                        LayoutParams.MATCH_PARENT, 0);
355abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                layoutParams.weight = 1;
356abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                backgroundLayout.setLayoutParams(layoutParams);
357abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                topLayout.addView(backgroundLayout);
358abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet
359abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet
360bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                // if the theme says no title/action bar, then the size will be 0
361bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                if (mActionBarSize > 0) {
362224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta                    BridgeActionBar actionBar = createActionBar(context, params, backgroundLayout);
3631ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta                    actionBar.createMenuPopup();
3641ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta                    mContentRoot = actionBar.getContentRoot();
365bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                } else if (mTitleBarSize > 0) {
366bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    try {
3674ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                        TitleBar titleBar = createTitleBar(context,
36842c7ce02f4023c94b315253754a20c20800be731Deepanshu Gupta                                params.getAppLabel(),
36942c7ce02f4023c94b315253754a20c20800be731Deepanshu Gupta                                simulatedPlatformVersion);
370abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                        backgroundLayout.addView(titleBar);
3711ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta                    } catch (XmlPullParserException ignored) {
372bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
373bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    }
374bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                }
375bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
376bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                // content frame
3774ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                if (mContentRoot == null) {
3784ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    mContentRoot = new FrameLayout(context);
3794ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    layoutParams = new LinearLayout.LayoutParams(
3804ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                            LayoutParams.MATCH_PARENT, 0);
3814ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    layoutParams.weight = 1;
3824ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    mContentRoot.setLayoutParams(layoutParams);
3834ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    backgroundLayout.addView(mContentRoot);
3844ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                }
385bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
38642c7ce02f4023c94b315253754a20c20800be731Deepanshu Gupta                if (Config.showOnScreenNavBar(simulatedPlatformVersion) &&
3875a734548455e5bcc8a5fd6b3972017086d3c1287Deepanshu Gupta                        mNavigationBarOrientation == LinearLayout.HORIZONTAL &&
388891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                        mNavigationBarSize > 0) {
389bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    // system bar
390bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    try {
3914ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                        NavigationBar navigationBar = createNavigationBar(context,
39242c7ce02f4023c94b315253754a20c20800be731Deepanshu Gupta                                hardwareConfig.getDensity(), isRtl, params.isRtlSupported(),
39342c7ce02f4023c94b315253754a20c20800be731Deepanshu Gupta                                simulatedPlatformVersion);
394891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                        topLayout.addView(navigationBar);
3951ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta                    } catch (XmlPullParserException ignored) {
396bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
397bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    }
398bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                }
399bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            }
400bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
401c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
402c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // Sets the project callback (custom view loader) to the fragment delegate so that
403c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // it can instantiate the custom Fragment.
404b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            Fragment_Delegate.setProjectCallback(params.getProjectCallback());
405c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
40610bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta            String rootTag = params.getFlag(SessionParamsFlags.FLAG_KEY_ROOT_TAG);
40710bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta            boolean isPreference = "PreferenceScreen".equals(rootTag);
40810bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta            View view;
40910bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta            if (isPreference) {
41010bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta                view = Preference_Delegate.inflatePreference(getContext(), mBlockParser,
41110bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta                  mContentRoot);
41210bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta            } else {
41310bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta                view = mInflater.inflate(mBlockParser, mContentRoot);
41410bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta            }
415c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
4162fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            // done with the parser, pop it.
4172fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            context.popParser();
4182fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
419c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            Fragment_Delegate.setProjectCallback(null);
420c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
421c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // set the AttachInfo on the root view.
4227f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet            AttachInfo_Accessor.setAttachInfo(mViewRoot);
423c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
42433758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet            // post-inflate process. For now this supports TabHost/TabWidget
42510bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta            postInflateProcess(view, params.getProjectCallback(), isPreference ? view : null);
42633758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet
427c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // get the background drawable
4281ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta            if (mWindowBackground != null) {
429b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                Drawable d = ResourceHelper.getDrawable(mWindowBackground, context);
430891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                backgroundView.setBackground(d);
431c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
432c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
43319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult();
434c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        } catch (PostInflateException e) {
43519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return ERROR_INFLATION.createResult(e.getMessage(), e);
436c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        } catch (Throwable e) {
437c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // get the real cause of the exception.
438c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            Throwable t = e;
439c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            while (t.getCause() != null) {
440c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                t = t.getCause();
441c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
442c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
44319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return ERROR_INFLATION.createResult(t.getMessage(), t);
444c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
445c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
446c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
447c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
448c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * Renders the scene.
449c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * <p>
4502eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
4512eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *
4525a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet     * @param freshRender whether the render is a new one and should erase the existing bitmap (in
4535a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet     *      the case where bitmaps are reused). This is typically needed when not playing
4545a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet     *      animations.)
4555a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet     *
4562eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
4572eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
4589eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet     *
4591b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta     * @see SessionParams#getRenderingMode()
460bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * @see RenderSession#render(long)
461c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     */
4625a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet    public Result render(boolean freshRender) {
4632eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        checkLock();
4642eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
465b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        SessionParams params = getParams();
466b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
467c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        try {
468c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            if (mViewRoot == null) {
46919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet                return ERROR_NOT_INFLATED.createResult();
470c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
471c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
472b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            RenderingMode renderingMode = params.getRenderingMode();
473891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            HardwareConfig hardwareConfig = params.getHardwareConfig();
474fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet
4759eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet            // only do the screen measure when needed.
4769eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet            boolean newRenderSize = false;
4779eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet            if (mMeasuredScreenWidth == -1) {
4789eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                newRenderSize = true;
479891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                mMeasuredScreenWidth = hardwareConfig.getScreenWidth();
480891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                mMeasuredScreenHeight = hardwareConfig.getScreenHeight();
4819eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet
4829eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                if (renderingMode != RenderingMode.NORMAL) {
483c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    int widthMeasureSpecMode = renderingMode.isHorizExpand() ?
484c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
485c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            : MeasureSpec.EXACTLY;
486c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    int heightMeasureSpecMode = renderingMode.isVertExpand() ?
487c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
488c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            : MeasureSpec.EXACTLY;
489c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
490c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // We used to compare the measured size of the content to the screen size but
491c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // this does not work anymore due to the 2 following issues:
492c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // - If the content is in a decor (system bar, title/action bar), the root view
493c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    //   will not resize even with the UNSPECIFIED because of the embedded layout.
494c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // - If there is no decor, but a dialog frame, then the dialog padding prevents
495c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    //   comparing the size of the content to the screen frame (as it would not
496c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    //   take into account the dialog padding).
497c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
498c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // The solution is to first get the content size in a normal rendering, inside
499c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // the decor or the dialog padding.
500c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // Then measure only the content with UNSPECIFIED to see the size difference
501c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // and apply this to the screen size.
502c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
503c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // first measure the full layout, with EXACTLY to get the size of the
504c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // content as it is inside the decor/dialog
5051ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta                    @SuppressWarnings("deprecation")
506c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    Pair<Integer, Integer> exactMeasure = measureView(
507c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mViewRoot, mContentRoot.getChildAt(0),
508c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mMeasuredScreenWidth, MeasureSpec.EXACTLY,
509c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mMeasuredScreenHeight, MeasureSpec.EXACTLY);
510c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
511c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // now measure the content only using UNSPECIFIED (where applicable, based on
512c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // the rendering mode). This will give us the size the content needs.
5131ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta                    @SuppressWarnings("deprecation")
514c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    Pair<Integer, Integer> result = measureView(
515c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mContentRoot, mContentRoot.getChildAt(0),
516c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mMeasuredScreenWidth, widthMeasureSpecMode,
517c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mMeasuredScreenHeight, heightMeasureSpecMode);
518c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
519c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // now look at the difference and add what is needed.
5209eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                    if (renderingMode.isHorizExpand()) {
521c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                        int measuredWidth = exactMeasure.getFirst();
522c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                        int neededWidth = result.getFirst();
523c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                        if (neededWidth > measuredWidth) {
524c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mMeasuredScreenWidth += neededWidth - measuredWidth;
5259eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                        }
526fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet                    }
527c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
5289eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                    if (renderingMode.isVertExpand()) {
529c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                        int measuredHeight = exactMeasure.getSecond();
530c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                        int neededHeight = result.getSecond();
531c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                        if (neededHeight > measuredHeight) {
532c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mMeasuredScreenHeight += neededHeight - measuredHeight;
5339eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                        }
534fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet                    }
535c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                }
536c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
537c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
538c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet            // measure again with the size we need
539c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // This must always be done before the call to layout
540c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet            measureView(mViewRoot, null /*measuredView*/,
541c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    mMeasuredScreenWidth, MeasureSpec.EXACTLY,
542c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    mMeasuredScreenHeight, MeasureSpec.EXACTLY);
543c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
544c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // now do the layout.
54516584225125acba18b74920b902c798dfead0328Xavier Ducrohet            mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
546c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
54710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet            if (params.isLayoutOnly()) {
54810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                // delete the canvas and image to reset them on the next full rendering
54910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                mImage = null;
55010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                mCanvas = null;
55110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet            } else {
5527f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet                AttachInfo_Accessor.dispatchOnPreDraw(mViewRoot);
55310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet
55410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                // draw the views
55510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                // create the BufferedImage into which the layout will be rendered.
55610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                boolean newImage = false;
55710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                if (newRenderSize || mCanvas == null) {
55810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    if (params.getImageFactory() != null) {
55910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        mImage = params.getImageFactory().getImage(
56010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                                mMeasuredScreenWidth,
56110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                                mMeasuredScreenHeight);
56210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    } else {
56310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        mImage = new BufferedImage(
56410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                                mMeasuredScreenWidth,
56510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                                mMeasuredScreenHeight,
56610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                                BufferedImage.TYPE_INT_ARGB);
56710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        newImage = true;
56810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    }
56910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet
57010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    if (params.isBgColorOverridden()) {
57110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        // since we override the content, it's the same as if it was a new image.
57210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        newImage = true;
57310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        Graphics2D gc = mImage.createGraphics();
57410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        gc.setColor(new Color(params.getOverrideBgColor(), true));
57510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        gc.setComposite(AlphaComposite.Src);
57610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
57710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        gc.dispose();
57810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    }
57910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet
58010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    // create an Android bitmap around the BufferedImage
58110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
582891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                            true /*isMutable*/, hardwareConfig.getDensity());
58310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet
58410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    // create a Canvas around the Android bitmap
58510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    mCanvas = new Canvas(bitmap);
586891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue());
5879eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                }
588c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
5891ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta                if (freshRender && !newImage) {
5909eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                    Graphics2D gc = mImage.createGraphics();
5915a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet                    gc.setComposite(AlphaComposite.Src);
592c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
59310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    gc.setColor(new Color(0x00000000, true));
59410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    gc.fillRect(0, 0,
59510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                            mMeasuredScreenWidth, mMeasuredScreenHeight);
59616584225125acba18b74920b902c798dfead0328Xavier Ducrohet
59710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    // done
59810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    gc.dispose();
59910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                }
60016584225125acba18b74920b902c798dfead0328Xavier Ducrohet
60110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                mViewRoot.draw(mCanvas);
6025a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet            }
6035a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet
6045ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta            mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(),
6055ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta                    false);
606c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
607c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // success!
60819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult();
609c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        } catch (Throwable e) {
610c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // get the real cause of the exception.
611c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            Throwable t = e;
612c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            while (t.getCause() != null) {
613c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                t = t.getCause();
614c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
615c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
61619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return ERROR_UNKNOWN.createResult(t.getMessage(), t);
617c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
618c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
619c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
620c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
621c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * Executes {@link View#measure(int, int)} on a given view with the given parameters (used
622c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * to create measure specs with {@link MeasureSpec#makeMeasureSpec(int, int)}.
623c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     *
624c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * if <var>measuredView</var> is non null, the method returns a {@link Pair} of (width, height)
625c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * for the view (using {@link View#getMeasuredWidth()} and {@link View#getMeasuredHeight()}).
626c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     *
627c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @param viewToMeasure the view on which to execute measure().
628c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @param measuredView if non null, the view to query for its measured width/height.
629c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @param width the width to use in the MeasureSpec.
630c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @param widthMode the MeasureSpec mode to use for the width.
631c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @param height the height to use in the MeasureSpec.
632c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @param heightMode the MeasureSpec mode to use for the height.
633c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @return the measured width/height if measuredView is non-null, null otherwise.
634c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     */
6351ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta    @SuppressWarnings("deprecation")  // For the use of Pair
636c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet    private Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
637c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet            int width, int widthMode, int height, int heightMode) {
638c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet        int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode);
639c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet        int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode);
640c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet        viewToMeasure.measure(w_spec, h_spec);
641c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
642c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet        if (measuredView != null) {
643c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet            return Pair.of(measuredView.getMeasuredWidth(), measuredView.getMeasuredHeight());
644c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet        }
645c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
646c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet        return null;
647c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet    }
648c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
649c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet    /**
6502eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * Animate an object
6512eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * <p>
6522eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
6532eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *
6542eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
6552eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
656e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
657bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * @see RenderSession#animate(Object, String, boolean, IAnimationListener)
6582eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     */
65919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public Result animate(Object targetObject, String animationName,
6602eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            boolean isFrameworkAnimation, IAnimationListener listener) {
6612eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        checkLock();
6622eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
663b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        BridgeContext context = getContext();
664b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
6652eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        // find the animation file.
6661ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta        ResourceValue animationResource;
6672eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        int animationId = 0;
6682eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        if (isFrameworkAnimation) {
669b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            animationResource = context.getRenderResources().getFrameworkResource(
67035ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet                    ResourceType.ANIMATOR, animationName);
6712eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            if (animationResource != null) {
672b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet                animationId = Bridge.getResourceId(ResourceType.ANIMATOR, animationName);
6732eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            }
6742eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        } else {
675b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            animationResource = context.getRenderResources().getProjectResource(
67635ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet                    ResourceType.ANIMATOR, animationName);
6772eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            if (animationResource != null) {
678b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                animationId = context.getProjectCallback().getResourceId(
67935ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet                        ResourceType.ANIMATOR, animationName);
6802eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            }
6812eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        }
6822eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
6832eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        if (animationResource != null) {
6842eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            try {
685b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                Animator anim = AnimatorInflater.loadAnimator(context, animationId);
6862eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet                if (anim != null) {
6872eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet                    anim.setTarget(targetObject);
6882eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
689e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    new PlayAnimationThread(anim, this, animationName, listener).start();
6902eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
69119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet                    return SUCCESS.createResult();
6922eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet                }
6932eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            } catch (Exception e) {
694c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet                // get the real cause of the exception.
695c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet                Throwable t = e;
696c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet                while (t.getCause() != null) {
697c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet                    t = t.getCause();
698c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet                }
699c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
70019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet                return ERROR_UNKNOWN.createResult(t.getMessage(), t);
7012eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            }
7022eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        }
7032eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
70419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet        return ERROR_ANIM_NOT_FOUND.createResult();
705c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet    }
706c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
707e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    /**
708e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * Insert a new child into an existing parent.
709e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * <p>
710e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
711e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
712e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
713e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
714e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
715bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener)
716e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     */
71719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml,
718e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            final int index, IAnimationListener listener) {
719c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        checkLock();
720c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
721b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        BridgeContext context = getContext();
722b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
723c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        // create a block parser for the XML
72402d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet        BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
72502d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet                childXml, context, false /* platformResourceFlag */);
726c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
727c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        // inflate the child without adding it to the root since we want to control where it'll
728c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        // get added. We do pass the parentView however to ensure that the layoutParams will
729c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        // be created correctly.
730e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/);
73102d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet        blockParser.ensurePopped();
732c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
733e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        invalidateRenderingSize();
734e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
735e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        if (listener != null) {
736e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            new AnimationThread(this, "insertChild", listener) {
737e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
738e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                @Override
73919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet                public Result preAnimation() {
740e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    parentView.setLayoutTransition(new LayoutTransition());
741e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    return addView(parentView, child, index);
742e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                }
743e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
744e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                @Override
745e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                public void postAnimation() {
746e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    parentView.setLayoutTransition(null);
747e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                }
748e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            }.start();
749e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
750e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            // always return success since the real status will come through the listener.
75119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult(child);
7529eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet        }
7539eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet
754e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        // add it to the parentView in the correct location
75519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet        Result result = addView(parentView, child, index);
7561ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta        if (!result.isSuccess()) {
757e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            return result;
758e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
759c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
7605a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet        result = render(false /*freshRender*/);
761c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet        if (result.isSuccess()) {
762e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            result = result.getCopyWithData(child);
763c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet        }
764c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet
765c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet        return result;
766c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet    }
767c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
768e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    /**
769e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * Adds a given view to a given parent at a given index.
770e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
771e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @param parent the parent to receive the view
772e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @param view the view to add to the parent
773e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @param index the index where to do the add.
774e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
77519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     * @return a Result with {@link Status#SUCCESS} or
77619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
777e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *     adding views.
778e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     */
77919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    private Result addView(ViewGroup parent, View view, int index) {
780e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        try {
781e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            parent.addView(view, index);
78219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult();
783e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        } catch (UnsupportedOperationException e) {
784e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            // looks like this is a view class that doesn't support children manipulation!
78519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
786e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
787e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    }
788e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
789e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    /**
790e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * Moves a view to a new parent at a given location
791e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * <p>
792e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
793e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
794e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
795e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
796e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
797bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener)
798e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     */
7992b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet    public Result moveChild(final ViewGroup newParentView, final View childView, final int index,
800479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            Map<String, String> layoutParamsMap, final IAnimationListener listener) {
801c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        checkLock();
802c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
803e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        invalidateRenderingSize();
804e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
80501811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet        LayoutParams layoutParams = null;
806e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        if (layoutParamsMap != null) {
807e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            // need to create a new LayoutParams object for the new parent.
8082b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet            layoutParams = newParentView.generateLayoutParams(
809e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    new BridgeLayoutParamsMapAttributes(layoutParamsMap));
810e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
8119eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet
8122b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet        // get the current parent of the view that needs to be moved.
8132b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet        final ViewGroup previousParent = (ViewGroup) childView.getParent();
8142b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
815e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        if (listener != null) {
816e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            final LayoutParams params = layoutParams;
81701811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet
818479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            // there is no support for animating views across layouts, so in case the new and old
819479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            // parent views are different we fake the animation through a no animation thread.
820479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            if (previousParent != newParentView) {
821479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                new Thread("not animated moveChild") {
822479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    @Override
823479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    public void run() {
824479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        Result result = moveView(previousParent, newParentView, childView, index,
825479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                                params);
8261ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta                        if (!result.isSuccess()) {
827479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            listener.done(result);
828479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        }
829479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
830479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // ready to do the work, acquire the scene.
831479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        result = acquire(250);
8321ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta                        if (!result.isSuccess()) {
833479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            listener.done(result);
834479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            return;
835479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        }
836479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
837479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        try {
8385a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet                            result = render(false /*freshRender*/);
839479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            if (result.isSuccess()) {
840479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                                listener.onNewFrame(RenderSessionImpl.this.getSession());
841479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            }
842479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        } finally {
843479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            release();
844479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        }
845479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
846479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        listener.done(result);
8472b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                    }
848479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                }.start();
849479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            } else {
850479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                new AnimationThread(this, "moveChild", listener) {
8512b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
852479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    @Override
853479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    public Result preAnimation() {
854479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // set up the transition for the parent.
855479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        LayoutTransition transition = new LayoutTransition();
856479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        previousParent.setLayoutTransition(transition);
8577550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet
858479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // tweak the animation durations and start delays (to match the duration of
859479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // animation playing just before).
860479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // Note: Cannot user Animation.setDuration() directly. Have to set it
861479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // on the LayoutTransition.
862479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        transition.setDuration(LayoutTransition.DISAPPEARING, 100);
863479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // CHANGE_DISAPPEARING plays after DISAPPEARING
864479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100);
86501811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet
866479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100);
867479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
868479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100);
869479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // CHANGE_APPEARING plays after CHANGE_APPEARING
870479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        transition.setStartDelay(LayoutTransition.APPEARING, 100);
871479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
872479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        transition.setDuration(LayoutTransition.APPEARING, 100);
873479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
874479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        return moveView(previousParent, newParentView, childView, index, params);
875479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    }
876479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
877479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    @Override
878479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    public void postAnimation() {
879479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        previousParent.setLayoutTransition(null);
880479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        newParentView.setLayoutTransition(null);
881479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    }
882479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                }.start();
883479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            }
884e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
885e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            // always return success since the real status will come through the listener.
88619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult(layoutParams);
887c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        }
888c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
8892b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet        Result result = moveView(previousParent, newParentView, childView, index, layoutParams);
8901ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta        if (!result.isSuccess()) {
891e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            return result;
892e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
893c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
8945a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet        result = render(false /*freshRender*/);
89501811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet        if (layoutParams != null && result.isSuccess()) {
896e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            result = result.getCopyWithData(layoutParams);
89701811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet        }
89801811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet
89901811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet        return result;
900c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet    }
901c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
902e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    /**
903e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * Moves a View from its current parent to a new given parent at a new given location, with
904e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * an optional new {@link LayoutParams} instance
905e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
9062b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet     * @param previousParent the previous parent, still owning the child at the time of the call.
9072b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet     * @param newParent the new parent
908479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet     * @param movedView the view to move
909e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @param index the new location in the new parent
910e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @param params an option (can be null) {@link LayoutParams} instance.
911e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
91219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     * @return a Result with {@link Status#SUCCESS} or
91319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
914e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *     adding views.
915e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     */
916479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet    private Result moveView(ViewGroup previousParent, final ViewGroup newParent,
917479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            final View movedView, final int index, final LayoutParams params) {
9189eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet        try {
9192b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet            // check if there is a transition on the previousParent.
920479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            LayoutTransition previousTransition = previousParent.getLayoutTransition();
921479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            if (previousTransition != null) {
9227550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // in this case there is an animation. This means we have to wait for the child's
9237550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // parent reference to be null'ed out so that we can add it to the new parent.
9247550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // It is technically removed right before the DISAPPEARING animation is done (if
9257550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // the animation of this type is not null, otherwise it's after which is impossible
9267550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // to handle).
9277550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // Because there is no move animation, if the new parent is the same as the old
9287550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before
9297550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // adding the child or the child will appear in its new location before the
9307550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // other children have made room for it.
9312b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
9322b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                // add a listener to the transition to be notified of the actual removal.
933479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                previousTransition.addTransitionListener(new TransitionListener() {
934479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    private int mChangeDisappearingCount = 0;
9352b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
93646d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet                    @Override
9372b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                    public void startTransition(LayoutTransition transition, ViewGroup container,
9382b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                            View view, int transitionType) {
939479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
940479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            mChangeDisappearingCount++;
941479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        }
9422b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                    }
943e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
94446d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet                    @Override
9452b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                    public void endTransition(LayoutTransition transition, ViewGroup container,
9462b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                            View view, int transitionType) {
947479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
948479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            mChangeDisappearingCount--;
949479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        }
950479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
951479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING &&
952479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                                mChangeDisappearingCount == 0) {
9532b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                            // add it to the parentView in the correct location
9542b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                            if (params != null) {
955479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                                newParent.addView(movedView, index, params);
9562b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                            } else {
957479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                                newParent.addView(movedView, index);
9582b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                            }
9592b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                        }
9602b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                    }
9612b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                });
9622b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
9632b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                // remove the view from the current parent.
964479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                previousParent.removeView(movedView);
9652b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
9662b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                // and return since adding the view to the new parent is done in the listener.
9672b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                return SUCCESS.createResult();
968e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            } else {
9692b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                // standard code with no animation. pretty simple.
970479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                previousParent.removeView(movedView);
971e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
9722b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                // add it to the parentView in the correct location
9732b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                if (params != null) {
974479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    newParent.addView(movedView, index, params);
9752b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                } else {
976479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    newParent.addView(movedView, index);
9772b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                }
9782b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
9792b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                return SUCCESS.createResult();
9802b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet            }
9819eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet        } catch (UnsupportedOperationException e) {
9829eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet            // looks like this is a view class that doesn't support children manipulation!
98319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
984c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        }
985e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    }
986e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
987e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    /**
988e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * Removes a child from its current parent.
989e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * <p>
990e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
991e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
992e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
993e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
994e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
995bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * @see RenderSession#removeChild(Object, IAnimationListener)
996e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     */
99719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public Result removeChild(final View childView, IAnimationListener listener) {
998e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        checkLock();
999c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
10009eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet        invalidateRenderingSize();
10019eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet
1002e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        final ViewGroup parent = (ViewGroup) childView.getParent();
1003e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
1004e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        if (listener != null) {
1005e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            new AnimationThread(this, "moveChild", listener) {
1006e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
1007e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                @Override
100819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet                public Result preAnimation() {
1009e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    parent.setLayoutTransition(new LayoutTransition());
1010e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    return removeView(parent, childView);
1011e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                }
1012e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
1013e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                @Override
1014e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                public void postAnimation() {
1015e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    parent.setLayoutTransition(null);
1016e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                }
1017e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            }.start();
1018e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
1019e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            // always return success since the real status will come through the listener.
102019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult();
1021e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
1022e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
102319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet        Result result = removeView(parent, childView);
10241ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta        if (!result.isSuccess()) {
1025e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            return result;
1026e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
1027e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
10285a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet        return render(false /*freshRender*/);
10292eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    }
10302eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
10312eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    /**
1032e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * Removes a given view from its current parent.
1033e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
1034e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @param view the view to remove from its parent
1035e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
103619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     * @return a Result with {@link Status#SUCCESS} or
103719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
1038e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *     adding views.
1039e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     */
104019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    private Result removeView(ViewGroup parent, View view) {
1041e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        try {
1042e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            parent.removeView(view);
104319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult();
1044e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        } catch (UnsupportedOperationException e) {
1045e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            // looks like this is a view class that doesn't support children manipulation!
104619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
1047e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
1048e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    }
1049e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
10502eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
105116584225125acba18b74920b902c798dfead0328Xavier Ducrohet    private void findBackground(RenderResources resources) {
10521ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta        if (!getParams().isBgColorOverridden()) {
105301b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet            mWindowBackground = resources.findItemInTheme("windowBackground",
105401b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet                    true /*isFrameworkAttr*/);
105516584225125acba18b74920b902c798dfead0328Xavier Ducrohet            if (mWindowBackground != null) {
105616584225125acba18b74920b902c798dfead0328Xavier Ducrohet                mWindowBackground = resources.resolveResValue(mWindowBackground);
105716584225125acba18b74920b902c798dfead0328Xavier Ducrohet            }
105816584225125acba18b74920b902c798dfead0328Xavier Ducrohet        }
105916584225125acba18b74920b902c798dfead0328Xavier Ducrohet    }
1060c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1061891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet    private boolean hasSoftwareButtons() {
1062891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet        return getParams().getHardwareConfig().hasSoftwareButtons();
106316584225125acba18b74920b902c798dfead0328Xavier Ducrohet    }
1064c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
106516584225125acba18b74920b902c798dfead0328Xavier Ducrohet    private void findStatusBar(RenderResources resources, DisplayMetrics metrics) {
1066891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet        boolean windowFullscreen = getBooleanThemeValue(resources,
10678505c3870a17f41d23329344fe381cd9ff324bd2Deepanshu Gupta                "windowFullscreen", false, !isThemeAppCompat(resources));
106816584225125acba18b74920b902c798dfead0328Xavier Ducrohet
10691ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta        if (!windowFullscreen && !mWindowIsFloating) {
1070891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            // default value
1071891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT;
107216584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1073891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            // get the real value
1074891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
1075891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    "status_bar_height");
107616584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1077891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            if (value != null) {
1078891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                TypedValue typedValue = ResourceHelper.getValue("status_bar_height",
1079891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                        value.getValue(), true /*requireUnit*/);
1080891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                if (typedValue != null) {
1081891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    // compute the pixel value based on the display metrics
1082891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    mStatusBarSize = (int)typedValue.getDimension(metrics);
108316584225125acba18b74920b902c798dfead0328Xavier Ducrohet                }
108416584225125acba18b74920b902c798dfead0328Xavier Ducrohet            }
108516584225125acba18b74920b902c798dfead0328Xavier Ducrohet        }
108616584225125acba18b74920b902c798dfead0328Xavier Ducrohet    }
108716584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1088bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private void findActionBar(RenderResources resources, DisplayMetrics metrics) {
1089bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        if (mWindowIsFloating) {
1090bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            return;
109116584225125acba18b74920b902c798dfead0328Xavier Ducrohet        }
109216584225125acba18b74920b902c798dfead0328Xavier Ducrohet
109316584225125acba18b74920b902c798dfead0328Xavier Ducrohet        boolean windowActionBar = getBooleanThemeValue(resources,
10948505c3870a17f41d23329344fe381cd9ff324bd2Deepanshu Gupta                "windowActionBar", true, !isThemeAppCompat(resources));
109516584225125acba18b74920b902c798dfead0328Xavier Ducrohet
109616584225125acba18b74920b902c798dfead0328Xavier Ducrohet        // if there's a value and it's false (default is true)
109716584225125acba18b74920b902c798dfead0328Xavier Ducrohet        if (windowActionBar) {
1098c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1099c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // default size of the window title bar
1100bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            mActionBarSize = DEFAULT_TITLE_BAR_HEIGHT;
1101c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1102c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // get value from the theme.
110301b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet            ResourceValue value = resources.findItemInTheme("actionBarSize",
110401b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet                    true /*isFrameworkAttr*/);
1105c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1106c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // resolve it
110716584225125acba18b74920b902c798dfead0328Xavier Ducrohet            value = resources.resolveResValue(value);
1108c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1109c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            if (value != null) {
1110c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                // get the numerical value, if available
111104ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet                TypedValue typedValue = ResourceHelper.getValue("actionBarSize", value.getValue(),
111204ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet                        true /*requireUnit*/);
1113c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                if (typedValue != null) {
1114c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    // compute the pixel value based on the display metrics
1115bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    mActionBarSize = (int)typedValue.getDimension(metrics);
1116c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                }
1117c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
1118bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        } else {
1119bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            // action bar overrides title bar so only look for this one if action bar is hidden
11202e4d93245764a1c1d7515361ddbb8fc1665f814eDeepanshu Gupta            boolean windowNoTitle = getBooleanThemeValue(resources, "windowNoTitle", false, true);
1121c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
11221ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta            if (!windowNoTitle) {
112316584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1124bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                // default size of the window title bar
1125bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                mTitleBarSize = DEFAULT_TITLE_BAR_HEIGHT;
112616584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1127bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                // get value from the theme.
112801b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet                ResourceValue value = resources.findItemInTheme("windowTitleSize",
112901b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet                        true /*isFrameworkAttr*/);
113016584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1131bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                // resolve it
1132bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                value = resources.resolveResValue(value);
1133c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1134bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                if (value != null) {
1135bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    // get the numerical value, if available
113604ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet                    TypedValue typedValue = ResourceHelper.getValue("windowTitleSize",
113704ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet                            value.getValue(), true /*requireUnit*/);
1138bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    if (typedValue != null) {
1139bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                        // compute the pixel value based on the display metrics
1140bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                        mTitleBarSize = (int)typedValue.getDimension(metrics);
1141bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    }
114216584225125acba18b74920b902c798dfead0328Xavier Ducrohet                }
114316584225125acba18b74920b902c798dfead0328Xavier Ducrohet            }
1144bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
114516584225125acba18b74920b902c798dfead0328Xavier Ducrohet        }
114616584225125acba18b74920b902c798dfead0328Xavier Ducrohet    }
114716584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1148891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet    private void findNavigationBar(RenderResources resources, DisplayMetrics metrics) {
11491ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta        if (hasSoftwareButtons() && !mWindowIsFloating) {
1150c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1151c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // default value
1152891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            mNavigationBarSize = 48; // ??
1153891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
1154891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            HardwareConfig hardwareConfig = getParams().getHardwareConfig();
1155891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
1156891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            boolean barOnBottom = true;
1157891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
1158891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            if (hardwareConfig.getOrientation() == ScreenOrientation.LANDSCAPE) {
1159891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                // compute the dp of the screen.
1160891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                int shortSize = hardwareConfig.getScreenHeight();
1161891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
1162891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                // compute in dp
11631ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta                int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT /
11641ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta                        hardwareConfig.getDensity().getDpiValue();
1165891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
11661ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta                // 0-599dp: "phone" UI with bar on the side
11671ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta                // 600+dp: "tablet" UI with bar on the bottom
11681ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta                barOnBottom = shortSizeDp >= 600;
1169891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            }
1170891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
1171891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            if (barOnBottom) {
1172891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                mNavigationBarOrientation = LinearLayout.HORIZONTAL;
1173891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            } else {
1174891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                mNavigationBarOrientation = LinearLayout.VERTICAL;
1175891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            }
1176c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1177d1d6fafc7fc63543b10552dadf202dd6fa40fe6bXavier Ducrohet            // get the real value
117835ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet            ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
1179891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    barOnBottom ? "navigation_bar_height" : "navigation_bar_width");
118016584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1181c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            if (value != null) {
1182891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                TypedValue typedValue = ResourceHelper.getValue("navigation_bar_height",
118304ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet                        value.getValue(), true /*requireUnit*/);
1184c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                if (typedValue != null) {
1185c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    // compute the pixel value based on the display metrics
1186891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    mNavigationBarSize = (int)typedValue.getDimension(metrics);
1187c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                }
1188c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
118916584225125acba18b74920b902c798dfead0328Xavier Ducrohet        }
119016584225125acba18b74920b902c798dfead0328Xavier Ducrohet    }
119116584225125acba18b74920b902c798dfead0328Xavier Ducrohet
11928505c3870a17f41d23329344fe381cd9ff324bd2Deepanshu Gupta    private boolean isThemeAppCompat(RenderResources resources) {
11938505c3870a17f41d23329344fe381cd9ff324bd2Deepanshu Gupta        // Ideally, we should check if the corresponding activity extends
11948505c3870a17f41d23329344fe381cd9ff324bd2Deepanshu Gupta        // android.support.v7.app.ActionBarActivity, and not care about the theme name at all.
11958505c3870a17f41d23329344fe381cd9ff324bd2Deepanshu Gupta        if (mIsThemeAppCompat == null) {
11968505c3870a17f41d23329344fe381cd9ff324bd2Deepanshu Gupta            StyleResourceValue defaultTheme = resources.getDefaultTheme();
1197224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta          // We can't simply check for parent using resources.themeIsParentOf() since the
1198224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta          // inheritance structure isn't really what one would expect. The first common parent
1199224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta          // between Theme.AppCompat.Light and Theme.AppCompat is Theme.Material (for v21).
1200224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            boolean isThemeAppCompat = false;
1201224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            for (int i = 0; i < 50; i++) {
1202224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta                // for loop ensures that we don't run into cyclic theme inheritance.
1203224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta                if (defaultTheme.getName().startsWith("Theme.AppCompat")) {
1204224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta                    isThemeAppCompat = true;
1205224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta                    break;
1206224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta                }
1207224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta                defaultTheme = resources.getParent(defaultTheme);
1208224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta                if (defaultTheme == null) {
1209224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta                    break;
1210224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta                }
1211224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            }
1212224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            mIsThemeAppCompat = isThemeAppCompat;
12138505c3870a17f41d23329344fe381cd9ff324bd2Deepanshu Gupta        }
12148505c3870a17f41d23329344fe381cd9ff324bd2Deepanshu Gupta        return mIsThemeAppCompat;
12158505c3870a17f41d23329344fe381cd9ff324bd2Deepanshu Gupta    }
12168505c3870a17f41d23329344fe381cd9ff324bd2Deepanshu Gupta
121701b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet    /**
12188505c3870a17f41d23329344fe381cd9ff324bd2Deepanshu Gupta     * Looks for an attribute in the current theme.
121901b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     *
122001b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     * @param resources the render resources
122101b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     * @param name the name of the attribute
122201b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     * @param defaultValue the default value.
12238505c3870a17f41d23329344fe381cd9ff324bd2Deepanshu Gupta     * @param isFrameworkAttr if the attribute is in android namespace
122401b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     * @return the value of the attribute or the default one if not found.
122501b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     */
122616584225125acba18b74920b902c798dfead0328Xavier Ducrohet    private boolean getBooleanThemeValue(RenderResources resources,
12278505c3870a17f41d23329344fe381cd9ff324bd2Deepanshu Gupta            String name, boolean defaultValue, boolean isFrameworkAttr) {
122816584225125acba18b74920b902c798dfead0328Xavier Ducrohet
12298505c3870a17f41d23329344fe381cd9ff324bd2Deepanshu Gupta        ResourceValue value = resources.findItemInTheme(name, isFrameworkAttr);
123016584225125acba18b74920b902c798dfead0328Xavier Ducrohet
123116584225125acba18b74920b902c798dfead0328Xavier Ducrohet        // because it may reference something else, we resolve it.
123216584225125acba18b74920b902c798dfead0328Xavier Ducrohet        value = resources.resolveResValue(value);
1233c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
123416584225125acba18b74920b902c798dfead0328Xavier Ducrohet        // if there's no value, return the default.
123516584225125acba18b74920b902c798dfead0328Xavier Ducrohet        if (value == null || value.getValue() == null) {
123616584225125acba18b74920b902c798dfead0328Xavier Ducrohet            return defaultValue;
1237c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1238c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
123916584225125acba18b74920b902c798dfead0328Xavier Ducrohet        return XmlUtils.convertValueToBoolean(value.getValue(), defaultValue);
1240c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
1241c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1242c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
12431ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta     * Post process on a view hierarchy that was just inflated.
12441ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta     * <p/>
12451ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta     * At the moment this only supports TabHost: If {@link TabHost} is detected, look for the
1246c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically
1247c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * based on the content of the {@link FrameLayout}.
1248c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * @param view the root view to process.
1249c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * @param projectCallback callback to the project.
125010bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta     * @param skip the view and it's children are not processed.
1251c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     */
12521ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta    @SuppressWarnings("deprecation")  // For the use of Pair
125310bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta    private void postInflateProcess(View view, IProjectCallback projectCallback, View skip)
1254c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            throws PostInflateException {
125510bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta        if (view == skip) {
125610bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta            return;
125710bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta        }
1258c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        if (view instanceof TabHost) {
125910bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta            setupTabHost((TabHost) view, projectCallback);
126031fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet        } else if (view instanceof QuickContactBadge) {
126131fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet            QuickContactBadge badge = (QuickContactBadge) view;
126231fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet            badge.setImageToDefault();
12632fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet        } else if (view instanceof AdapterView<?>) {
12642fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            // get the view ID.
12652fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            int id = view.getId();
12662fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12672fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            BridgeContext context = getContext();
12682fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12692fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            // get a ResourceReference from the integer ID.
12702fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            ResourceReference listRef = context.resolveId(id);
12712fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12722fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            if (listRef != null) {
12732fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                SessionParams params = getParams();
12742fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                AdapterBinding binding = params.getAdapterBindings().get(listRef);
12752fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12762fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                // if there was no adapter binding, trying to get it from the call back.
12772fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                if (binding == null) {
12782fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    binding = params.getProjectCallback().getAdapterBinding(listRef,
12792fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            context.getViewKey(view), view);
12802fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                }
12812fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12822fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                if (binding != null) {
12832fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12842fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    if (view instanceof AbsListView) {
12852fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        if ((binding.getFooterCount() > 0 || binding.getHeaderCount() > 0) &&
12862fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                view instanceof ListView) {
12872fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            ListView list = (ListView) view;
12882fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12892fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            boolean skipCallbackParser = false;
12902fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12912fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            int count = binding.getHeaderCount();
129210bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta                            for (int i = 0; i < count; i++) {
12932fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                Pair<View, Boolean> pair = context.inflateView(
12942fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        binding.getHeaderAt(i),
12952fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        list, false /*attachToRoot*/, skipCallbackParser);
12962fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                if (pair.getFirst() != null) {
12972fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                    list.addHeaderView(pair.getFirst());
12982fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                }
12992fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
13002fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                skipCallbackParser |= pair.getSecond();
13012fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            }
13022fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
13032fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            count = binding.getFooterCount();
130410bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta                            for (int i = 0; i < count; i++) {
13052fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                Pair<View, Boolean> pair = context.inflateView(
13062fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        binding.getFooterAt(i),
13072fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        list, false /*attachToRoot*/, skipCallbackParser);
13082fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                if (pair.getFirst() != null) {
13092fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                    list.addFooterView(pair.getFirst());
13102fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                }
13112fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
13122fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                skipCallbackParser |= pair.getSecond();
13132fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            }
13142fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        }
13152fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
13162fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        if (view instanceof ExpandableListView) {
13172fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            ((ExpandableListView) view).setAdapter(
13182fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                    new FakeExpandableAdapter(
13192fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                            listRef, binding, params.getProjectCallback()));
13202fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        } else {
13212fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            ((AbsListView) view).setAdapter(
13222fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                    new FakeAdapter(
13232fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                            listRef, binding, params.getProjectCallback()));
13242fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        }
13252fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    } else if (view instanceof AbsSpinner) {
13262fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        ((AbsSpinner) view).setAdapter(
13272fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                new FakeAdapter(
13282fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        listRef, binding, params.getProjectCallback()));
13292fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    }
13302fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                }
13312fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            }
1332d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta        } else if (isInstanceOf(view, RecyclerViewUtil.CN_RECYCLER_VIEW)) {
1333d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta            RecyclerViewUtil.setAdapter(view, getContext(), getParams());
1334c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        } else if (view instanceof ViewGroup) {
133510bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta            ViewGroup group = (ViewGroup) view;
1336c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            final int count = group.getChildCount();
133710bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta            for (int c = 0; c < count; c++) {
1338c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                View child = group.getChildAt(c);
133910bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta                postInflateProcess(child, projectCallback, skip);
1340c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
1341c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1342c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
1343c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1344c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
1345d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta     * Check if the object is an instance of a class named {@code className}. This doesn't work
1346d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta     * for interfaces.
1347d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta     */
1348d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta    public static boolean isInstanceOf(Object object, String className) {
1349d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta        Class superClass = object.getClass();
1350d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta        while (superClass != null) {
1351d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta            String name = superClass.getName();
1352d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta            if (name.equals(className)) {
1353d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta                return true;
1354d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta            }
1355d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta            superClass = superClass.getSuperclass();
1356d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta        }
1357d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta        return false;
1358d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta    }
1359d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta
1360d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta    /**
1361c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * Sets up a {@link TabHost} object.
1362c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * @param tabHost the TabHost to setup.
1363c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * @param projectCallback The project callback object to access the project R class.
1364c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * @throws PostInflateException
1365c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     */
1366c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private void setupTabHost(TabHost tabHost, IProjectCallback projectCallback)
1367c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            throws PostInflateException {
1368c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        // look for the TabWidget, and the FrameLayout. They have their own specific names
1369c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        View v = tabHost.findViewById(android.R.id.tabs);
1370c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1371c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        if (v == null) {
1372c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            throw new PostInflateException(
1373c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    "TabHost requires a TabWidget with id \"android:id/tabs\".\n");
1374c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1375c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
13761ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta        if (!(v instanceof TabWidget)) {
1377c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            throw new PostInflateException(String.format(
1378c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    "TabHost requires a TabWidget with id \"android:id/tabs\".\n" +
1379c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName()));
1380c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1381c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1382c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        v = tabHost.findViewById(android.R.id.tabcontent);
1383c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1384c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        if (v == null) {
13851ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta            // TODO: see if we can fake tabs even without the FrameLayout (same below when the frameLayout is empty)
13861ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta            //noinspection SpellCheckingInspection
1387c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            throw new PostInflateException(
1388c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    "TabHost requires a FrameLayout with id \"android:id/tabcontent\".");
1389c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1390c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
13911ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta        if (!(v instanceof FrameLayout)) {
13921ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta            //noinspection SpellCheckingInspection
1393c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            throw new PostInflateException(String.format(
1394c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" +
1395c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName()));
1396c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1397c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1398c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        FrameLayout content = (FrameLayout)v;
1399c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
14001ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta        // now process the content of the frameLayout and dynamically create tabs for it.
1401c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        final int count = content.getChildCount();
1402c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1403c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        // this must be called before addTab() so that the TabHost searches its TabWidget
1404c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        // and FrameLayout.
1405c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        tabHost.setup();
1406c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1407796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye        if (count == 0) {
1408796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye            // Create a dummy child to get a single tab
140949ce36e1754243eedc124b4f7e68af1b458c821cDeepanshu Gupta            TabSpec spec = tabHost.newTabSpec("tag")
141049ce36e1754243eedc124b4f7e68af1b458c821cDeepanshu Gupta                    .setIndicator("Tab Label", tabHost.getResources()
141149ce36e1754243eedc124b4f7e68af1b458c821cDeepanshu Gupta                            .getDrawable(android.R.drawable.ic_menu_info_details, null))
1412796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                    .setContent(new TabHost.TabContentFactory() {
141346d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet                        @Override
1414796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                        public View createTabContent(String tag) {
1415b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                            return new LinearLayout(getContext());
1416796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                        }
1417796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                    });
1418796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye            tabHost.addTab(spec);
1419796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye        } else {
14201ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta            // for each child of the frameLayout, add a new TabSpec
1421796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye            for (int i = 0 ; i < count ; i++) {
1422796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                View child = content.getChildAt(i);
1423796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                String tabSpec = String.format("tab_spec%d", i+1);
142410bb1371dca38b5b59f083ee963f7987da6511f2Deepanshu Gupta                @SuppressWarnings("ConstantConditions")  // child cannot be null.
1425796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                int id = child.getId();
14261ea1b21acd5517d5405bd3338ba24d5a03a8d792Deepanshu Gupta                @SuppressWarnings("deprecation")
1427b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet                Pair<ResourceType, String> resource = projectCallback.resolveResourceId(id);
1428796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                String name;
1429796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                if (resource != null) {
1430b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet                    name = resource.getSecond();
1431796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                } else {
1432796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                    name = String.format("Tab %d", i+1); // default name if id is unresolved.
1433796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                }
1434796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id));
1435c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
1436c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1437c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
1438c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
14394ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    /**
14404ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * Visits a {@link View} and its children and generate a {@link ViewInfo} containing the
14414ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * bounds of all the views.
14424ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     *
14434ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param view the root View
14444ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param offset an offset for the view bounds.
14454ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
14464ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
14474ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     *                       content frame.
14484ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     *
14494ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @return {@code ViewInfo} containing the bounds of the view and it children otherwise.
14504ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     */
14514ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    private ViewInfo visit(View view, int offset, boolean setExtendedInfo,
14524ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            boolean isContentFrame) {
14534ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        ViewInfo result = createViewInfo(view, offset, setExtendedInfo, isContentFrame);
1454bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
14554ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        if (view instanceof ViewGroup) {
14564ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            ViewGroup group = ((ViewGroup) view);
14574ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            result.setChildren(visitAllChildren(group, isContentFrame ? 0 : offset,
14584ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    setExtendedInfo, isContentFrame));
14594ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        }
14604ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        return result;
14614ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    }
1462bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
14634ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    /**
14644ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * Visits all the children of a given ViewGroup and generates a list of {@link ViewInfo}
14651b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta     * containing the bounds of all the views. It also initializes the {@link #mViewInfoList} with
14664ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * the children of the {@code mContentRoot}.
14674ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     *
14684ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param viewGroup the root View
14694ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param offset an offset from the top for the content view frame.
14704ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
14714ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
14724ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     *                       content frame. {@code false} if the {@code ViewInfo} to be created is
14734ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     *                       part of the system decor.
14744ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     */
14754ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset,
14764ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            boolean setExtendedInfo, boolean isContentFrame) {
14774ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        if (viewGroup == null) {
14784ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            return null;
1479bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        }
1480bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
14814ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        if (!isContentFrame) {
14824ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            offset += viewGroup.getTop();
14834ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        }
1484bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
14854ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        int childCount = viewGroup.getChildCount();
14864ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        if (viewGroup == mContentRoot) {
14874ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            List<ViewInfo> childrenWithoutOffset = new ArrayList<ViewInfo>(childCount);
14884ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            List<ViewInfo> childrenWithOffset = new ArrayList<ViewInfo>(childCount);
14894ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            for (int i = 0; i < childCount; i++) {
14904ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                ViewInfo[] childViewInfo = visitContentRoot(viewGroup.getChildAt(i), offset,
149105b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet                        setExtendedInfo);
14924ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                childrenWithoutOffset.add(childViewInfo[0]);
14934ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                childrenWithOffset.add(childViewInfo[1]);
1494bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            }
14954ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            mViewInfoList = childrenWithOffset;
14964ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            return childrenWithoutOffset;
14974ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        } else {
14984ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            List<ViewInfo> children = new ArrayList<ViewInfo>(childCount);
14994ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            for (int i = 0; i < childCount; i++) {
15004ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo,
15014ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                        isContentFrame));
15024ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            }
15034ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            return children;
1504bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        }
15054ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    }
1506bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
15074ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    /**
15084ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * Visits the children of {@link #mContentRoot} and generates {@link ViewInfo} containing the
15094ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * bounds of all the views. It returns two {@code ViewInfo} objects with the same children,
15104ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * one with the {@code offset} and other without the {@code offset}. The offset is needed to
15114ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * get the right bounds if the {@code ViewInfo} hierarchy is accessed from
15124ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * {@code mViewInfoList}. When the hierarchy is accessed via {@code mSystemViewInfoList}, the
15134ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * offset is not needed.
15144ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     *
15154ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @return an array of length two, with ViewInfo at index 0 is without offset and ViewInfo at
15164ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     *         index 1 is with the offset.
15174ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     */
1518d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta    @NonNull
15194ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    private ViewInfo[] visitContentRoot(View view, int offset, boolean setExtendedInfo) {
15204ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        ViewInfo[] result = new ViewInfo[2];
15214ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        if (view == null) {
15224ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            return result;
15234ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        }
15244ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta
15254ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        result[0] = createViewInfo(view, 0, setExtendedInfo, true);
15264ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        result[1] = createViewInfo(view, offset, setExtendedInfo, true);
15274ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        if (view instanceof ViewGroup) {
15284ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            List<ViewInfo> children = visitAllChildren((ViewGroup) view, 0, setExtendedInfo, true);
15294ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            result[0].setChildren(children);
15304ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            result[1].setChildren(children);
15314ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        }
15324ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        return result;
1533bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    }
1534c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1535c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
15364ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * Creates a {@link ViewInfo} for the view. The {@code ViewInfo} corresponding to the children
15374ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * of the {@code view} are not created. Consequently, the children of {@code ViewInfo} is not
15384ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * set.
15394ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param offset an offset for the view bounds. Used only if view is part of the content frame.
1540c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     */
15414ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    private ViewInfo createViewInfo(View view, int offset, boolean setExtendedInfo,
15424ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            boolean isContentFrame) {
1543c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        if (view == null) {
1544c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            return null;
1545c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1546c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
15474ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        ViewInfo result;
15484ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        if (isContentFrame) {
1549bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta            // The view is part of the layout added by the user. Hence,
1550bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta            // the ViewCookie may be obtained only through the Context.
15514ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            result = new ViewInfo(view.getClass().getName(),
1552bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                    getContext().getViewKey(view),
15534ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    view.getLeft(), view.getTop() + offset, view.getRight(),
15544ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    view.getBottom() + offset, view, view.getLayoutParams());
15554ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        } else {
1556bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta            // We are part of the system decor.
1557bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta            SystemViewInfo r = new SystemViewInfo(view.getClass().getName(),
15585ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta                    getViewKey(view),
15594ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    view.getLeft(), view.getTop(), view.getRight(),
15604ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    view.getBottom(), view, view.getLayoutParams());
1561bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta            result = r;
1562bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta            // We currently mark three kinds of views:
1563bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta            // 1. Menus in the Action Bar
1564bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta            // 2. Menus in the Overflow popup.
1565bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta            // 3. The overflow popup button.
1566bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta            if (view instanceof ListMenuItemView) {
1567bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                // Mark 2.
1568bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                // All menus in the popup are of type ListMenuItemView.
1569bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                r.setViewType(ViewType.ACTION_BAR_OVERFLOW_MENU);
1570bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta            } else {
1571bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                // Mark 3.
1572bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                ViewGroup.LayoutParams lp = view.getLayoutParams();
1573bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                if (lp instanceof ActionMenuView.LayoutParams &&
1574bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                        ((ActionMenuView.LayoutParams) lp).isOverflowButton) {
1575bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                    r.setViewType(ViewType.ACTION_BAR_OVERFLOW);
1576bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                } else {
1577bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                    // Mark 1.
1578bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                    // A view is a menu in the Action Bar is it is not the overflow button and of
1579bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                    // its parent is of type ActionMenuView. We can also check if the view is
1580bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                    // instanceof ActionMenuItemView but that will fail for menus using
1581bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                    // actionProviderClass.
1582bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                    ViewParent parent = view.getParent();
1583bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                    while (parent != mViewRoot && parent instanceof ViewGroup) {
1584bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                        if (parent instanceof ActionMenuView) {
1585bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                            r.setViewType(ViewType.ACTION_BAR_MENU);
1586bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                            break;
1587bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                        }
1588bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                        parent = parent.getParent();
1589bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                    }
1590bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta                }
1591bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta            }
15924ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        }
1593c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
159405b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet        if (setExtendedInfo) {
159505b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet            MarginLayoutParams marginParams = null;
159605b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet            LayoutParams params = view.getLayoutParams();
159705b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet            if (params instanceof MarginLayoutParams) {
159805b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet                marginParams = (MarginLayoutParams) params;
159905b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet            }
160005b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet            result.setExtendedInfo(view.getBaseline(),
160105b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet                    marginParams != null ? marginParams.leftMargin : 0,
160205b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet                    marginParams != null ? marginParams.topMargin : 0,
160305b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet                    marginParams != null ? marginParams.rightMargin : 0,
160405b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet                    marginParams != null ? marginParams.bottomMargin : 0);
160505b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet        }
160605b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet
1607c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        return result;
1608c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
1609c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1610bac0d9ae796920360ee2f2babd8f2c03d4c3c2b8Deepanshu Gupta    /* (non-Javadoc)
16115ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta     * The cookie for menu items are stored in menu item and not in the map from View stored in
16125ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta     * BridgeContext.
16135ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta     */
1614d345f44a87de1088fcd19e021238852bbffbbaecDeepanshu Gupta    @Nullable
16155ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta    private Object getViewKey(View view) {
16165ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta        BridgeContext context = getContext();
16175ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta        if (!(view instanceof MenuView.ItemView)) {
16185ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta            return context.getViewKey(view);
16195ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta        }
16205ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta        MenuItemImpl menuItem;
16215ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta        if (view instanceof ActionMenuItemView) {
16225ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta            menuItem = ((ActionMenuItemView) view).getItemData();
16235ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta        } else if (view instanceof ListMenuItemView) {
16245ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta            menuItem = ((ListMenuItemView) view).getItemData();
16255ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta        } else if (view instanceof IconMenuItemView) {
16265ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta            menuItem = ((IconMenuItemView) view).getItemData();
16275ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta        } else {
16285ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta            menuItem = null;
16295ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta        }
16305ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta        if (menuItem instanceof BridgeMenuItemImpl) {
16315ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta            return ((BridgeMenuItemImpl) menuItem).getViewCookie();
16325ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta        }
16335ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta
16345ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta        return null;
16355ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta    }
16365ba2f230faa355eb9bc1e90f6c48eeeb437f390cDeepanshu Gupta
16374ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    private void invalidateRenderingSize() {
16384ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        mMeasuredScreenWidth = mMeasuredScreenHeight = -1;
16394ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    }
16404ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta
1641bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    /**
16424ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * Creates the status bar with wifi and battery icons.
1643bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     */
16444ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    private StatusBar createStatusBar(BridgeContext context, Density density, int direction,
16455a734548455e5bcc8a5fd6b3972017086d3c1287Deepanshu Gupta            boolean isRtlSupported, int platformVersion) throws XmlPullParserException {
16464ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        StatusBar statusBar = new StatusBar(context, density,
16475a734548455e5bcc8a5fd6b3972017086d3c1287Deepanshu Gupta                direction, isRtlSupported, platformVersion);
16484ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        statusBar.setLayoutParams(
16494ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                new LinearLayout.LayoutParams(
16504ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                        LayoutParams.MATCH_PARENT, mStatusBarSize));
16514ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        return statusBar;
16524ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    }
16537d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet
16544ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    /**
16554ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * Creates the navigation bar with back, home and recent buttons.
16564ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     *
16574ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param isRtl true if the current locale is right-to-left
16584ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param isRtlSupported true is the project manifest declares that the application
16594ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     *        is RTL aware.
16604ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     */
16614ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    private NavigationBar createNavigationBar(BridgeContext context, Density density,
166242c7ce02f4023c94b315253754a20c20800be731Deepanshu Gupta            boolean isRtl, boolean isRtlSupported, int simulatedPlatformVersion)
166342c7ce02f4023c94b315253754a20c20800be731Deepanshu Gupta            throws XmlPullParserException {
16644ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        NavigationBar navigationBar = new NavigationBar(context,
16654ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                density, mNavigationBarOrientation, isRtl,
166642c7ce02f4023c94b315253754a20c20800be731Deepanshu Gupta                isRtlSupported, simulatedPlatformVersion);
16674ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        if (mNavigationBarOrientation == LinearLayout.VERTICAL) {
16684ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            navigationBar.setLayoutParams(new LinearLayout.LayoutParams(mNavigationBarSize,
16694ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    LayoutParams.MATCH_PARENT));
16704ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        } else {
16714ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            navigationBar.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
16724ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    mNavigationBarSize));
16737d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet        }
16744ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        return navigationBar;
16757d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet    }
16767d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet
167742c7ce02f4023c94b315253754a20c20800be731Deepanshu Gupta    private TitleBar createTitleBar(BridgeContext context, String title,
167842c7ce02f4023c94b315253754a20c20800be731Deepanshu Gupta            int simulatedPlatformVersion)
16794ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            throws XmlPullParserException {
168042c7ce02f4023c94b315253754a20c20800be731Deepanshu Gupta        TitleBar titleBar = new TitleBar(context, title, simulatedPlatformVersion);
16814ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        titleBar.setLayoutParams(
16824ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, mTitleBarSize));
16834ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        return titleBar;
16844ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    }
16857d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet
16864ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    /**
16874ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * Creates the action bar. Also queries the project callback for missing information.
16884ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     */
1689224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    private BridgeActionBar createActionBar(BridgeContext context, SessionParams params,
16900bffc736e1f260724764d31f7499cbc09471a535Deepanshu Gupta            ViewGroup parentView) {
1691224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        if (mIsThemeAppCompat == Boolean.TRUE) {
1692224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            return new AppCompatActionBar(context, params, parentView);
1693224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        } else {
1694224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            return new FrameworkActionBar(context, params, parentView);
1695224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        }
16969eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet    }
16979eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet
1698c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    public BufferedImage getImage() {
1699c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        return mImage;
1700c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
1701c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
170216584225125acba18b74920b902c798dfead0328Xavier Ducrohet    public boolean isAlphaChannelImage() {
170316584225125acba18b74920b902c798dfead0328Xavier Ducrohet        return mIsAlphaChannelImage;
170416584225125acba18b74920b902c798dfead0328Xavier Ducrohet    }
170516584225125acba18b74920b902c798dfead0328Xavier Ducrohet
17067d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet    public List<ViewInfo> getViewInfos() {
17077d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet        return mViewInfoList;
1708c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
1709cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet
17104ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    public List<ViewInfo> getSystemViewInfos() {
17114ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        return mSystemViewInfoList;
17124ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    }
17134ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta
171419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public Map<String, String> getDefaultProperties(Object viewObject) {
1715b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        return getContext().getDefaultPropMap(viewObject);
1716cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet    }
1717c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
171819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public void setScene(RenderSession session) {
171919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet        mScene = session;
1720c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet    }
1721c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
172219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public RenderSession getSession() {
1723c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        return mScene;
1724c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet    }
1725c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet}
1726