RenderSessionImpl.java revision a4a2d3d5936bcdda1409796179725d354e5f4400
13bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet/*
23bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Copyright (C) 2010 The Android Open Source Project
33bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet *
43bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License");
53bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * you may not use this file except in compliance with the License.
63bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * You may obtain a copy of the License at
73bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet *
83bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet *      http://www.apache.org/licenses/LICENSE-2.0
93bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet *
103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * Unless required by applicable law or agreed to in writing, software
113bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS,
123bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * See the License for the specific language governing permissions and
143bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * limitations under the License.
153bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */
163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
173bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetpackage com.android.layoutlib.bridge.impl;
183bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
19ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_ANIM_NOT_FOUND;
20ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_INFLATION;
21ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLATED;
22ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN;
23ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP_NO_CHILDREN;
24ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
25ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet
267062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport com.android.ide.common.rendering.api.AdapterBinding;
2764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohetimport com.android.ide.common.rendering.api.HardwareConfig;
28ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.IAnimationListener;
29ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.ILayoutPullParser;
30ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.IProjectCallback;
310d829bd739dfcb3374971c776676bf2e53bab43cXavier Ducrohetimport com.android.ide.common.rendering.api.RenderResources;
32ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderSession;
337062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport com.android.ide.common.rendering.api.ResourceReference;
34ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.ResourceValue;
35ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.Result;
36ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohetimport com.android.ide.common.rendering.api.Result.Status;
37d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams;
38b32414fe256a6fe1d65e7a1443cd6ea77db8bd95Xavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams.RenderingMode;
3945d9520182663e47a1878ce51be756219799b2c9Deepanshu Guptaimport com.android.ide.common.rendering.api.StyleResourceValue;
40d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohetimport com.android.ide.common.rendering.api.ViewInfo;
4170114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Guptaimport com.android.ide.common.rendering.api.ViewType;
423bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport com.android.internal.util.XmlUtils;
4341670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.ActionMenuItemView;
4441670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.BridgeMenuItemImpl;
4541670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.IconMenuItemView;
4641670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.ListMenuItemView;
4741670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.MenuItemImpl;
4841670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Guptaimport com.android.internal.view.menu.MenuView;
49ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohetimport com.android.layoutlib.bridge.Bridge;
503bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeContext;
51ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
523bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
53a4a2d3d5936bcdda1409796179725d354e5f4400Andrew Shulaevimport com.android.layoutlib.bridge.android.RenderParamsFlags;
54841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Guptaimport com.android.layoutlib.bridge.bars.BridgeActionBar;
55841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Guptaimport com.android.layoutlib.bridge.bars.AppCompatActionBar;
5682ca7fe915ed30a7e30eb3de3ce816a9ad0867d6Deepanshu Guptaimport com.android.layoutlib.bridge.bars.Config;
5764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohetimport com.android.layoutlib.bridge.bars.NavigationBar;
5864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohetimport com.android.layoutlib.bridge.bars.StatusBar;
59799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohetimport com.android.layoutlib.bridge.bars.TitleBar;
60841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Guptaimport com.android.layoutlib.bridge.bars.FrameworkActionBar;
617062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeAdapter;
627062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter;
6385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Guptaimport com.android.resources.Density;
641b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohetimport com.android.resources.ResourceType;
6564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohetimport com.android.resources.ScreenOrientation;
66947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohetimport com.android.util.Pair;
673bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
68799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohetimport org.xmlpull.v1.XmlPullParserException;
69799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
70994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohetimport android.animation.AnimationThread;
7133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohetimport android.animation.Animator;
72ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohetimport android.animation.AnimatorInflater;
7333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohetimport android.animation.LayoutTransition;
7462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohetimport android.animation.LayoutTransition.TransitionListener;
753bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.app.Fragment_Delegate;
763bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.Bitmap;
773bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.Bitmap_Delegate;
783bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.Canvas;
793bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.graphics.drawable.Drawable;
808a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Guptaimport android.preference.Preference_Delegate;
813bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.util.DisplayMetrics;
823bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.util.TypedValue;
83994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohetimport android.view.AttachInfo_Accessor;
84994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohetimport android.view.BridgeInflater;
8576f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohetimport android.view.IWindowManager;
8664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohetimport android.view.IWindowManagerImpl;
8776f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohetimport android.view.Surface;
883bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.view.View;
893bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.view.View.MeasureSpec;
90d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohetimport android.view.ViewGroup;
91ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohetimport android.view.ViewGroup.LayoutParams;
926208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohetimport android.view.ViewGroup.MarginLayoutParams;
9370114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Guptaimport android.view.ViewParent;
9476f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohetimport android.view.WindowManagerGlobal_Delegate;
957062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.AbsListView;
967062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.AbsSpinner;
9770114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Guptaimport android.widget.ActionMenuView;
987062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.AdapterView;
997062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.ExpandableListView;
1003bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.widget.FrameLayout;
101f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbyeimport android.widget.LinearLayout;
1027062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohetimport android.widget.ListView;
10362c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohetimport android.widget.QuickContactBadge;
1043bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport android.widget.TabHost;
105f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbyeimport android.widget.TabHost.TabSpec;
106d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohetimport android.widget.TabWidget;
1073bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1084c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohetimport java.awt.AlphaComposite;
1093bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.awt.Color;
1103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.awt.Graphics2D;
1113bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.awt.image.BufferedImage;
1123bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.util.ArrayList;
1133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.util.List;
1143bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohetimport java.util.Map;
1153bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet/**
117ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * Class implementing the render session.
118952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta * <p/>
119ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * A session is a stateful representation of a layout file. It is initialized with data coming
120ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then
1213bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet * be done on the layout.
1223bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet */
1230fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohetpublic class RenderSessionImpl extends RenderAction<SessionParams> {
1243bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1253bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private static final int DEFAULT_TITLE_BAR_HEIGHT = 25;
1263bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private static final int DEFAULT_STATUS_BAR_HEIGHT = 25;
1273bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1283bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    // scene state
129ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    private RenderSession mScene;
1303bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private BridgeXmlBlockParser mBlockParser;
1313bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private BridgeInflater mInflater;
1326a5b91fceb1913cab6416bef99d7b28530d16ecfXavier Ducrohet    private ResourceValue mWindowBackground;
133799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private ViewGroup mViewRoot;
134799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private FrameLayout mContentRoot;
1351392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet    private Canvas mCanvas;
1361392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet    private int mMeasuredScreenWidth = -1;
1371392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet    private int mMeasuredScreenHeight = -1;
138799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private boolean mIsAlphaChannelImage;
139799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private boolean mWindowIsFloating;
14045d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta    private Boolean mIsThemeAppCompat;
141a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
142a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    private int mStatusBarSize;
14364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet    private int mNavigationBarSize;
14464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet    private int mNavigationBarOrientation = LinearLayout.HORIZONTAL;
145799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private int mTitleBarSize;
146799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private int mActionBarSize;
147a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1483bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1493bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    // information being returned through the API
1503bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private BufferedImage mImage;
151e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet    private List<ViewInfo> mViewInfoList;
15285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private List<ViewInfo> mSystemViewInfoList;
1533bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1543bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private static final class PostInflateException extends Exception {
1553bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        private static final long serialVersionUID = 1L;
1563bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1573bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        public PostInflateException(String message) {
1583bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            super(message);
1593bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
1603bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
1613bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1623bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
1633bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * Creates a layout scene with all the information coming from the layout bridge API.
1643bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * <p>
1658d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta     * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init(long)},
1668d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta     * which act as a
167ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     * call to {@link RenderSessionImpl#acquire(long)}
1683bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     *
1698d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta     * @see Bridge#createSession(SessionParams)
1703bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     */
171b32414fe256a6fe1d65e7a1443cd6ea77db8bd95Xavier Ducrohet    public RenderSessionImpl(SessionParams params) {
1720fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        super(new SessionParams(params));
173ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet    }
174ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
175ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet    /**
176ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * Initializes and acquires the scene, creating various Android objects such as context,
177ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * inflater, and parser.
178ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *
179ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @param timeout the time to wait if another rendering is happening.
180ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *
181ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @return whether the scene was prepared
182ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *
183ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @see #acquire(long)
184ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @see #release()
185ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     */
1860fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet    @Override
187ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public Result init(long timeout) {
1880fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        Result result = super.init(timeout);
189952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!result.isSuccess()) {
190ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            return result;
191ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        }
1923bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1930fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        SessionParams params = getParams();
1940fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        BridgeContext context = getContext();
1953bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
196835ad76e300033f1d9cccd214bd7d61d78d0240aDeepanshu Gupta
1970fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        RenderResources resources = getParams().getResources();
1980fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        DisplayMetrics metrics = getContext().getMetrics();
1993bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
200a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        // use default of true in case it's not found to use alpha by default
20145d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta        mIsAlphaChannelImage  = getBooleanThemeValue(resources, "windowIsFloating", true, true);
20245d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta        // FIXME: Find out why both variables are taking the same value.
20345d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta        mWindowIsFloating = getBooleanThemeValue(resources, "windowIsFloating", true, true);
204ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
205a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        findBackground(resources);
206a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        findStatusBar(resources, metrics);
207799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet        findActionBar(resources, metrics);
20864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet        findNavigationBar(resources, metrics);
2093bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
21076f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet        // FIXME: find those out, and possibly add them to the render params
21176f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet        boolean hasNavigationBar = true;
212952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        //noinspection ConstantConditions
21376f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet        IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(),
21476f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet                metrics, Surface.ROTATION_0,
2151e3c4a072f4476cedb958d75e2a6edf3bde8378fJohn Spurlock                hasNavigationBar);
21676f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet        WindowManagerGlobal_Delegate.setWindowManagerService(iwm);
21776f4c3e91d8579a580569c3d079da99511309727Xavier Ducrohet
2183bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        // build the inflater and parser.
2190fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        mInflater = new BridgeInflater(context, params.getProjectCallback());
2200fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        context.setBridgeInflater(mInflater);
221ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
222a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet        mBlockParser = new BridgeXmlBlockParser(
223a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet                params.getLayoutDescription(), context, false /* platformResourceFlag */);
224ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
2253054fe698a6be732e24128541a1db867ec606a59Xavier Ducrohet        return SUCCESS.createResult();
2263bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
2273bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
2283bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
2293bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * Inflates the layout.
2303bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * <p>
231ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
232ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *
233ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
234ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *      the scene, or if {@link #init(long)} was not called.
2353bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     */
236ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public Result inflate() {
237ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        checkLock();
238ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
2393bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        try {
2403bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
2410fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            SessionParams params = getParams();
24264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            HardwareConfig hardwareConfig = params.getHardwareConfig();
2430fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            BridgeContext context = getContext();
244510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta            boolean isRtl = Bridge.isLocaleRtl(params.getLocale());
24585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            int layoutDirection = isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
24664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
247cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet            // the view group that receives the window background.
248952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            ViewGroup backgroundView;
249cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet
2500fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            if (mWindowIsFloating || params.isForceNoDecor()) {
251cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                backgroundView = mViewRoot = mContentRoot = new FrameLayout(context);
25285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                mViewRoot.setLayoutDirection(layoutDirection);
253799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            } else {
254bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                int simulatedPlatformVersion = params.getSimulatedPlatformVersion();
25564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                if (hasSoftwareButtons() && mNavigationBarOrientation == LinearLayout.VERTICAL) {
25664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    /*
25764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                     * This is a special case where the navigation bar is on the right.
25864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       +-------------------------------------------------+---+
25964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | Status bar (always)                             |   |
26064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       +-------------------------------------------------+   |
26164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | (Layout with background drawable)               |   |
26264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | +---------------------------------------------+ |   |
26364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | | Title/Action bar (optional)                 | |   |
26464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | +---------------------------------------------+ |   |
26564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | | Content, vertical extending                 | |   |
26664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | |                                             | |   |
26764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       | +---------------------------------------------+ |   |
26864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       +-------------------------------------------------+---+
26964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
27064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       So we create a horizontal layout, with the nav bar on the right,
27164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       and the left part is the normal layout below without the nav bar at
27264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                       the bottom
27364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                     */
27464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    LinearLayout topLayout = new LinearLayout(context);
27585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    topLayout.setLayoutDirection(layoutDirection);
27664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    mViewRoot = topLayout;
27764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    topLayout.setOrientation(LinearLayout.HORIZONTAL);
27864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
279bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                    if (Config.showOnScreenNavBar(simulatedPlatformVersion)) {
280f18273f698024ffa23ce457e7d30c683e7027680Deepanshu Gupta                        try {
281f18273f698024ffa23ce457e7d30c683e7027680Deepanshu Gupta                            NavigationBar navigationBar = createNavigationBar(context,
282bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                                    hardwareConfig.getDensity(), isRtl, params.isRtlSupported(),
283bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                                    simulatedPlatformVersion);
284f18273f698024ffa23ce457e7d30c683e7027680Deepanshu Gupta                            topLayout.addView(navigationBar);
285f18273f698024ffa23ce457e7d30c683e7027680Deepanshu Gupta                        } catch (XmlPullParserException ignored) {
286f18273f698024ffa23ce457e7d30c683e7027680Deepanshu Gupta                        }
28764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    }
28864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                }
28964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
290799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                /*
291799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                 * we're creating the following layout
292799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                 *
293799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                   +-------------------------------------------------+
29464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                   | Status bar (always)                             |
295799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                   +-------------------------------------------------+
296cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | (Layout with background drawable)               |
297cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | +---------------------------------------------+ |
298cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | | Title/Action bar (optional)                 | |
299cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | +---------------------------------------------+ |
300cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | | Content, vertical extending                 | |
301cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | |                                             | |
302cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                   | +---------------------------------------------+ |
303799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                   +-------------------------------------------------+
30464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                   | Navigation bar for soft buttons, maybe see above|
305799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                   +-------------------------------------------------+
306799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
307799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                 */
308799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
3090fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet                LinearLayout topLayout = new LinearLayout(context);
310799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                topLayout.setOrientation(LinearLayout.VERTICAL);
31185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                topLayout.setLayoutDirection(layoutDirection);
31264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                // if we don't already have a view root this is it
31364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                if (mViewRoot == null) {
31464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    mViewRoot = topLayout;
31564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                } else {
31685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    int topLayoutWidth =
31785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                            params.getHardwareConfig().getScreenWidth() - mNavigationBarSize;
31864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
31985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                            topLayoutWidth, LayoutParams.MATCH_PARENT);
32064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    topLayout.setLayoutParams(layoutParams);
32164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
32264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    // this is the case of soft buttons + vertical bar.
32364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    // this top layout is the first layout in the horizontal layout. see above)
324510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                    if (isRtl && params.isRtlSupported()) {
325510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                        // If RTL is enabled, layoutlib will mirror the layouts. So, add the
326510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                        // topLayout to the right of Navigation Bar and layoutlib will draw it
327510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                        // to the left.
328510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                        mViewRoot.addView(topLayout);
329510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                    } else {
330510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                        // Add the top layout to the left of the Navigation Bar.
331510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                        mViewRoot.addView(topLayout, 0);
332510148f0699abceb44a3634a648a589cc84f6cbfDeepanshu Gupta                    }
33364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                }
334799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
335799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                if (mStatusBarSize > 0) {
336799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    // system bar
337799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    try {
33885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                        StatusBar statusBar = createStatusBar(context, hardwareConfig.getDensity(),
339f18273f698024ffa23ce457e7d30c683e7027680Deepanshu Gupta                                layoutDirection, params.isRtlSupported(),
340bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                                simulatedPlatformVersion);
34185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                        topLayout.addView(statusBar);
342952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    } catch (XmlPullParserException ignored) {
343799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
344799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    }
345799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                }
346799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
347cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                LinearLayout backgroundLayout = new LinearLayout(context);
348cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                backgroundView = backgroundLayout;
349cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                backgroundLayout.setOrientation(LinearLayout.VERTICAL);
350cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
351fa7ed38ae9c180ff12a7312e6ec740b5ba313a97Deepanshu Gupta                        LayoutParams.MATCH_PARENT, 0);
352cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                layoutParams.weight = 1;
353cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                backgroundLayout.setLayoutParams(layoutParams);
354cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                topLayout.addView(backgroundLayout);
355cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet
356cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet
357799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                // if the theme says no title/action bar, then the size will be 0
358799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                if (mActionBarSize > 0) {
359841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta                    BridgeActionBar actionBar = createActionBar(context, params, backgroundLayout);
360952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    actionBar.createMenuPopup();
361952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    mContentRoot = actionBar.getContentRoot();
362799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                } else if (mTitleBarSize > 0) {
363799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    try {
36485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                        TitleBar titleBar = createTitleBar(context,
365bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                                params.getAppLabel(),
366bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                                simulatedPlatformVersion);
367cd85db6ff592d37faf751d262d5b9c152adfd632Xavier Ducrohet                        backgroundLayout.addView(titleBar);
368952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    } catch (XmlPullParserException ignored) {
369799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
370799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    }
371799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                }
372799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
373799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                // content frame
37485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                if (mContentRoot == null) {
37585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    mContentRoot = new FrameLayout(context);
37685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    layoutParams = new LinearLayout.LayoutParams(
37785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                            LayoutParams.MATCH_PARENT, 0);
37885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    layoutParams.weight = 1;
37985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    mContentRoot.setLayoutParams(layoutParams);
38085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    backgroundLayout.addView(mContentRoot);
38185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                }
382799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
383bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                if (Config.showOnScreenNavBar(simulatedPlatformVersion) &&
384f18273f698024ffa23ce457e7d30c683e7027680Deepanshu Gupta                        mNavigationBarOrientation == LinearLayout.HORIZONTAL &&
38564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                        mNavigationBarSize > 0) {
386799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    // system bar
387799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    try {
38885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                        NavigationBar navigationBar = createNavigationBar(context,
389bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                                hardwareConfig.getDensity(), isRtl, params.isRtlSupported(),
390bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                                simulatedPlatformVersion);
39164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                        topLayout.addView(navigationBar);
392952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    } catch (XmlPullParserException ignored) {
393799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
394799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    }
395799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                }
396799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            }
397799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
3983bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
3993bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // Sets the project callback (custom view loader) to the fragment delegate so that
4003bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // it can instantiate the custom Fragment.
4010fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            Fragment_Delegate.setProjectCallback(params.getProjectCallback());
4023bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
403a4a2d3d5936bcdda1409796179725d354e5f4400Andrew Shulaev            String rootTag = params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG);
4048a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta            boolean isPreference = "PreferenceScreen".equals(rootTag);
4058a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta            View view;
4068a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta            if (isPreference) {
4078a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta                view = Preference_Delegate.inflatePreference(getContext(), mBlockParser,
4088a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta                  mContentRoot);
4098a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta            } else {
4108a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta                view = mInflater.inflate(mBlockParser, mContentRoot);
4118a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta            }
4123bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
4137062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            // done with the parser, pop it.
4147062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            context.popParser();
4157062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
4163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            Fragment_Delegate.setProjectCallback(null);
4173bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
4183bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // set the AttachInfo on the root view.
419994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohet            AttachInfo_Accessor.setAttachInfo(mViewRoot);
4203bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
421a2378f55b81e7d29f451d7f65527de49417a3f0cXavier Ducrohet            // post-inflate process. For now this supports TabHost/TabWidget
4228a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta            postInflateProcess(view, params.getProjectCallback(), isPreference ? view : null);
423a2378f55b81e7d29f451d7f65527de49417a3f0cXavier Ducrohet
4243bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // get the background drawable
425952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            if (mWindowBackground != null) {
4260fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet                Drawable d = ResourceHelper.getDrawable(mWindowBackground, context);
42764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                backgroundView.setBackground(d);
4283bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
4293bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
430ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult();
4313bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        } catch (PostInflateException e) {
432ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return ERROR_INFLATION.createResult(e.getMessage(), e);
4333bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        } catch (Throwable e) {
4343bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // get the real cause of the exception.
4353bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            Throwable t = e;
4363bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            while (t.getCause() != null) {
4373bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                t = t.getCause();
4383bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
4393bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
440ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return ERROR_INFLATION.createResult(t.getMessage(), t);
4413bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
4423bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
4433bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
4443bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
4453bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * Renders the scene.
4463bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * <p>
447ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
448ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *
4494c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet     * @param freshRender whether the render is a new one and should erase the existing bitmap (in
4504c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet     *      the case where bitmaps are reused). This is typically needed when not playing
4514c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet     *      animations.)
4524c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet     *
453ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
454ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
4551392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet     *
4568d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta     * @see SessionParams#getRenderingMode()
457799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet     * @see RenderSession#render(long)
4583bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     */
4594c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet    public Result render(boolean freshRender) {
460ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        checkLock();
461ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
4620fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        SessionParams params = getParams();
4630fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet
4643bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        try {
4653bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            if (mViewRoot == null) {
466ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet                return ERROR_NOT_INFLATED.createResult();
4673bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
4683bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
4690fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            RenderingMode renderingMode = params.getRenderingMode();
47064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            HardwareConfig hardwareConfig = params.getHardwareConfig();
471e489a969de010782fcc0ab048c7357d42ada9400Xavier Ducrohet
4721392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet            // only do the screen measure when needed.
4731392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet            boolean newRenderSize = false;
4741392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet            if (mMeasuredScreenWidth == -1) {
4751392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                newRenderSize = true;
47664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                mMeasuredScreenWidth = hardwareConfig.getScreenWidth();
47764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                mMeasuredScreenHeight = hardwareConfig.getScreenHeight();
4781392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet
4791392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                if (renderingMode != RenderingMode.NORMAL) {
4808ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    int widthMeasureSpecMode = renderingMode.isHorizExpand() ?
4818ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
4828ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            : MeasureSpec.EXACTLY;
4838ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    int heightMeasureSpecMode = renderingMode.isVertExpand() ?
4848ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
4858ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            : MeasureSpec.EXACTLY;
4868ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
4878ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // We used to compare the measured size of the content to the screen size but
4888ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // this does not work anymore due to the 2 following issues:
4898ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // - If the content is in a decor (system bar, title/action bar), the root view
4908ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    //   will not resize even with the UNSPECIFIED because of the embedded layout.
4918ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // - If there is no decor, but a dialog frame, then the dialog padding prevents
4928ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    //   comparing the size of the content to the screen frame (as it would not
4938ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    //   take into account the dialog padding).
4948ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
4958ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // The solution is to first get the content size in a normal rendering, inside
4968ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // the decor or the dialog padding.
4978ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // Then measure only the content with UNSPECIFIED to see the size difference
4988ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // and apply this to the screen size.
4998ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
5008ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // first measure the full layout, with EXACTLY to get the size of the
5018ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // content as it is inside the decor/dialog
502952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    @SuppressWarnings("deprecation")
5038ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    Pair<Integer, Integer> exactMeasure = measureView(
5048ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mViewRoot, mContentRoot.getChildAt(0),
5058ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mMeasuredScreenWidth, MeasureSpec.EXACTLY,
5068ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mMeasuredScreenHeight, MeasureSpec.EXACTLY);
5078ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
5088ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // now measure the content only using UNSPECIFIED (where applicable, based on
5098ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // the rendering mode). This will give us the size the content needs.
510952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                    @SuppressWarnings("deprecation")
5118ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    Pair<Integer, Integer> result = measureView(
5128ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mContentRoot, mContentRoot.getChildAt(0),
5138ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mMeasuredScreenWidth, widthMeasureSpecMode,
5148ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mMeasuredScreenHeight, heightMeasureSpecMode);
5158ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
5168ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    // now look at the difference and add what is needed.
5171392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                    if (renderingMode.isHorizExpand()) {
5188ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                        int measuredWidth = exactMeasure.getFirst();
5198ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                        int neededWidth = result.getFirst();
5208ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                        if (neededWidth > measuredWidth) {
5218ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mMeasuredScreenWidth += neededWidth - measuredWidth;
5221392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                        }
523e489a969de010782fcc0ab048c7357d42ada9400Xavier Ducrohet                    }
5243bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
5251392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                    if (renderingMode.isVertExpand()) {
5268ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                        int measuredHeight = exactMeasure.getSecond();
5278ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                        int neededHeight = result.getSecond();
5288ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                        if (neededHeight > measuredHeight) {
5298ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                            mMeasuredScreenHeight += neededHeight - measuredHeight;
5301392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                        }
531e489a969de010782fcc0ab048c7357d42ada9400Xavier Ducrohet                    }
5323bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                }
5333bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
5343bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
5358ae691c1148038995d1185716f629b82c582897fXavier Ducrohet            // measure again with the size we need
5363bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // This must always be done before the call to layout
5378ae691c1148038995d1185716f629b82c582897fXavier Ducrohet            measureView(mViewRoot, null /*measuredView*/,
5388ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    mMeasuredScreenWidth, MeasureSpec.EXACTLY,
5398ae691c1148038995d1185716f629b82c582897fXavier Ducrohet                    mMeasuredScreenHeight, MeasureSpec.EXACTLY);
5403bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
5413bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // now do the layout.
542a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
5433bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
544f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet            if (params.isLayoutOnly()) {
545f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                // delete the canvas and image to reset them on the next full rendering
546f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                mImage = null;
547f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                mCanvas = null;
548f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet            } else {
549994236e95e9809ec8c1d06a218f606f1af2083afXavier Ducrohet                AttachInfo_Accessor.dispatchOnPreDraw(mViewRoot);
550f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet
551f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                // draw the views
552f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                // create the BufferedImage into which the layout will be rendered.
553f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                boolean newImage = false;
554e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez
555e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                // When disableBitmapCaching is true, we do not reuse mImage and
556e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                // we create a new one in every render.
557e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                // This is useful when mImage is just a wrapper of Graphics2D so
558e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                // it doesn't get cached.
559e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                boolean disableBitmapCaching = Boolean.TRUE.equals(params.getFlag(
560a4a2d3d5936bcdda1409796179725d354e5f4400Andrew Shulaev                    RenderParamsFlags.FLAG_KEY_DISABLE_BITMAP_CACHING));
561e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                if (newRenderSize || mCanvas == null || disableBitmapCaching) {
562f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    if (params.getImageFactory() != null) {
563f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        mImage = params.getImageFactory().getImage(
564f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                                mMeasuredScreenWidth,
565f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                                mMeasuredScreenHeight);
566f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    } else {
567f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        mImage = new BufferedImage(
568f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                                mMeasuredScreenWidth,
569f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                                mMeasuredScreenHeight,
570f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                                BufferedImage.TYPE_INT_ARGB);
571f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        newImage = true;
572f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    }
573f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet
574f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    if (params.isBgColorOverridden()) {
575f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        // since we override the content, it's the same as if it was a new image.
576f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        newImage = true;
577f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        Graphics2D gc = mImage.createGraphics();
578f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        gc.setColor(new Color(params.getOverrideBgColor(), true));
579f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        gc.setComposite(AlphaComposite.Src);
580f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
581f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                        gc.dispose();
582f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    }
583f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet
584f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    // create an Android bitmap around the BufferedImage
585f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
58664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                            true /*isMutable*/, hardwareConfig.getDensity());
587f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet
588e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                    if (mCanvas == null) {
589e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                        // create a Canvas around the Android bitmap
590e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                        mCanvas = new Canvas(bitmap);
591e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                    } else {
592e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                        mCanvas.setBitmap(bitmap);
593e12b3f96291cf0e3dc60d9db9ac3d3859325f3d4Diego Perez                    }
59464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue());
5951392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                }
5963bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
597952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                if (freshRender && !newImage) {
5981392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet                    Graphics2D gc = mImage.createGraphics();
5994c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet                    gc.setComposite(AlphaComposite.Src);
6003bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
601f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    gc.setColor(new Color(0x00000000, true));
602f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    gc.fillRect(0, 0,
603f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                            mMeasuredScreenWidth, mMeasuredScreenHeight);
604a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
605f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    // done
606f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                    gc.dispose();
607f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                }
608a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
609f27575799aab2e552c0491a07b34389e1422fc27Xavier Ducrohet                mViewRoot.draw(mCanvas);
6104c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet            }
6114c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet
61241670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(),
61341670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta                    false);
6143bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
6153bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // success!
616ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult();
6173bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        } catch (Throwable e) {
6183bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // get the real cause of the exception.
6193bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            Throwable t = e;
6203bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            while (t.getCause() != null) {
6213bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                t = t.getCause();
6223bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
6233bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
624ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return ERROR_UNKNOWN.createResult(t.getMessage(), t);
6253bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
6263bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
6273bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
6283bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
6298ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * Executes {@link View#measure(int, int)} on a given view with the given parameters (used
6308ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * to create measure specs with {@link MeasureSpec#makeMeasureSpec(int, int)}.
6318ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     *
6328ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * if <var>measuredView</var> is non null, the method returns a {@link Pair} of (width, height)
6338ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * for the view (using {@link View#getMeasuredWidth()} and {@link View#getMeasuredHeight()}).
6348ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     *
6358ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @param viewToMeasure the view on which to execute measure().
6368ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @param measuredView if non null, the view to query for its measured width/height.
6378ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @param width the width to use in the MeasureSpec.
6388ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @param widthMode the MeasureSpec mode to use for the width.
6398ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @param height the height to use in the MeasureSpec.
6408ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @param heightMode the MeasureSpec mode to use for the height.
6418ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     * @return the measured width/height if measuredView is non-null, null otherwise.
6428ae691c1148038995d1185716f629b82c582897fXavier Ducrohet     */
643952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta    @SuppressWarnings("deprecation")  // For the use of Pair
6448ae691c1148038995d1185716f629b82c582897fXavier Ducrohet    private Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
6458ae691c1148038995d1185716f629b82c582897fXavier Ducrohet            int width, int widthMode, int height, int heightMode) {
6468ae691c1148038995d1185716f629b82c582897fXavier Ducrohet        int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode);
6478ae691c1148038995d1185716f629b82c582897fXavier Ducrohet        int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode);
6488ae691c1148038995d1185716f629b82c582897fXavier Ducrohet        viewToMeasure.measure(w_spec, h_spec);
6498ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
6508ae691c1148038995d1185716f629b82c582897fXavier Ducrohet        if (measuredView != null) {
6518ae691c1148038995d1185716f629b82c582897fXavier Ducrohet            return Pair.of(measuredView.getMeasuredWidth(), measuredView.getMeasuredHeight());
6528ae691c1148038995d1185716f629b82c582897fXavier Ducrohet        }
6538ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
6548ae691c1148038995d1185716f629b82c582897fXavier Ducrohet        return null;
6558ae691c1148038995d1185716f629b82c582897fXavier Ducrohet    }
6568ae691c1148038995d1185716f629b82c582897fXavier Ducrohet
6578ae691c1148038995d1185716f629b82c582897fXavier Ducrohet    /**
658ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * Animate an object
659ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * <p>
660ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
661ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *
662ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
663ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
66433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
665799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet     * @see RenderSession#animate(Object, String, boolean, IAnimationListener)
666ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet     */
667ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public Result animate(Object targetObject, String animationName,
668ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            boolean isFrameworkAnimation, IAnimationListener listener) {
669ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        checkLock();
670ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
6710fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        BridgeContext context = getContext();
6720fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet
673ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        // find the animation file.
674952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        ResourceValue animationResource;
675ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        int animationId = 0;
676ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        if (isFrameworkAnimation) {
6770fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            animationResource = context.getRenderResources().getFrameworkResource(
6781b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet                    ResourceType.ANIMATOR, animationName);
679ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            if (animationResource != null) {
680947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohet                animationId = Bridge.getResourceId(ResourceType.ANIMATOR, animationName);
681ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            }
682ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        } else {
6830fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet            animationResource = context.getRenderResources().getProjectResource(
6841b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet                    ResourceType.ANIMATOR, animationName);
685ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            if (animationResource != null) {
6860fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet                animationId = context.getProjectCallback().getResourceId(
6871b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet                        ResourceType.ANIMATOR, animationName);
688ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            }
689ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        }
690ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
691ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        if (animationResource != null) {
692ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            try {
6930fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet                Animator anim = AnimatorInflater.loadAnimator(context, animationId);
694ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet                if (anim != null) {
695ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet                    anim.setTarget(targetObject);
696ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
69733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    new PlayAnimationThread(anim, this, animationName, listener).start();
698ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
699ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet                    return SUCCESS.createResult();
700ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet                }
701ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            } catch (Exception e) {
702b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet                // get the real cause of the exception.
703b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet                Throwable t = e;
704b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet                while (t.getCause() != null) {
705b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet                    t = t.getCause();
706b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet                }
707b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
708ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet                return ERROR_UNKNOWN.createResult(t.getMessage(), t);
709ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet            }
710ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet        }
711ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
712ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet        return ERROR_ANIM_NOT_FOUND.createResult();
713b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet    }
714b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
71533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    /**
71633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * Insert a new child into an existing parent.
71733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * <p>
71833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
71933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
72033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
72133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
72233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
723799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet     * @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener)
72433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     */
725ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml,
72633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            final int index, IAnimationListener listener) {
727b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        checkLock();
728b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
7290fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        BridgeContext context = getContext();
7300fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet
731b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        // create a block parser for the XML
732a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet        BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
733a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet                childXml, context, false /* platformResourceFlag */);
734b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
735b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        // inflate the child without adding it to the root since we want to control where it'll
736b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        // get added. We do pass the parentView however to ensure that the layoutParams will
737b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        // be created correctly.
73833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/);
739a732a0101ad07b28e828bbbc8fb81be0580d53b5Xavier Ducrohet        blockParser.ensurePopped();
740b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
74133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        invalidateRenderingSize();
74233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
74333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        if (listener != null) {
74433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            new AnimationThread(this, "insertChild", listener) {
74533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
74633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                @Override
747ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet                public Result preAnimation() {
74833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    parentView.setLayoutTransition(new LayoutTransition());
74933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    return addView(parentView, child, index);
75033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                }
75133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
75233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                @Override
75333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                public void postAnimation() {
75433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    parentView.setLayoutTransition(null);
75533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                }
75633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            }.start();
75733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
75833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            // always return success since the real status will come through the listener.
759ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult(child);
7601392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet        }
7611392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet
76233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        // add it to the parentView in the correct location
763ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet        Result result = addView(parentView, child, index);
764952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!result.isSuccess()) {
76533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            return result;
76633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
767b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
7684c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet        result = render(false /*freshRender*/);
7691766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet        if (result.isSuccess()) {
77033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            result = result.getCopyWithData(child);
7711766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet        }
7721766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet
7731766c77e7e79afbb4fd2611837ac487f5610d71dXavier Ducrohet        return result;
774b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet    }
775b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
77633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    /**
77733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * Adds a given view to a given parent at a given index.
77833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
77933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @param parent the parent to receive the view
78033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @param view the view to add to the parent
78133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @param index the index where to do the add.
78233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
783ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     * @return a Result with {@link Status#SUCCESS} or
784ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
78533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *     adding views.
78633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     */
787ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    private Result addView(ViewGroup parent, View view, int index) {
78833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        try {
78933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            parent.addView(view, index);
790ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult();
79133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        } catch (UnsupportedOperationException e) {
79233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            // looks like this is a view class that doesn't support children manipulation!
793ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
79433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
79533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    }
79633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
79733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    /**
79833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * Moves a view to a new parent at a given location
79933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * <p>
80033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
80133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
80233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
80333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
80433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
805799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet     * @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener)
80633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     */
80762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet    public Result moveChild(final ViewGroup newParentView, final View childView, final int index,
80824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            Map<String, String> layoutParamsMap, final IAnimationListener listener) {
809b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        checkLock();
810b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
81133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        invalidateRenderingSize();
81233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
813ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet        LayoutParams layoutParams = null;
81433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        if (layoutParamsMap != null) {
81533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            // need to create a new LayoutParams object for the new parent.
81662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet            layoutParams = newParentView.generateLayoutParams(
81733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    new BridgeLayoutParamsMapAttributes(layoutParamsMap));
81833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
8191392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet
82062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet        // get the current parent of the view that needs to be moved.
82162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet        final ViewGroup previousParent = (ViewGroup) childView.getParent();
82262039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
82333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        if (listener != null) {
82433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            final LayoutParams params = layoutParams;
825ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet
82624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            // there is no support for animating views across layouts, so in case the new and old
82724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            // parent views are different we fake the animation through a no animation thread.
82824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            if (previousParent != newParentView) {
82924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                new Thread("not animated moveChild") {
83024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    @Override
83124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    public void run() {
83224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        Result result = moveView(previousParent, newParentView, childView, index,
83324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                                params);
834952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                        if (!result.isSuccess()) {
83524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            listener.done(result);
83624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        }
83724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
83824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // ready to do the work, acquire the scene.
83924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        result = acquire(250);
840952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                        if (!result.isSuccess()) {
84124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            listener.done(result);
84224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            return;
84324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        }
84424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
84524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        try {
8464c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet                            result = render(false /*freshRender*/);
84724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            if (result.isSuccess()) {
84824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                                listener.onNewFrame(RenderSessionImpl.this.getSession());
84924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            }
85024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        } finally {
85124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            release();
85224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        }
85324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
85424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        listener.done(result);
85562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                    }
85624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                }.start();
85724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            } else {
85824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                new AnimationThread(this, "moveChild", listener) {
85962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
86024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    @Override
86124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    public Result preAnimation() {
86224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // set up the transition for the parent.
86324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        LayoutTransition transition = new LayoutTransition();
86424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        previousParent.setLayoutTransition(transition);
8655562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet
86624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // tweak the animation durations and start delays (to match the duration of
86724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // animation playing just before).
86824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // Note: Cannot user Animation.setDuration() directly. Have to set it
86924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // on the LayoutTransition.
87024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        transition.setDuration(LayoutTransition.DISAPPEARING, 100);
87124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // CHANGE_DISAPPEARING plays after DISAPPEARING
87224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100);
873ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet
87424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100);
87524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
87624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100);
87724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        // CHANGE_APPEARING plays after CHANGE_APPEARING
87824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        transition.setStartDelay(LayoutTransition.APPEARING, 100);
87924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
88024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        transition.setDuration(LayoutTransition.APPEARING, 100);
88124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
88224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        return moveView(previousParent, newParentView, childView, index, params);
88324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    }
88424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
88524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    @Override
88624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    public void postAnimation() {
88724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        previousParent.setLayoutTransition(null);
88824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        newParentView.setLayoutTransition(null);
88924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    }
89024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                }.start();
89124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            }
89233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
89333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            // always return success since the real status will come through the listener.
894ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult(layoutParams);
895b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        }
896b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
89762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet        Result result = moveView(previousParent, newParentView, childView, index, layoutParams);
898952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!result.isSuccess()) {
89933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            return result;
90033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
901b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
9024c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet        result = render(false /*freshRender*/);
903ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet        if (layoutParams != null && result.isSuccess()) {
90433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            result = result.getCopyWithData(layoutParams);
905ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet        }
906ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet
907ce63b05275ddd2acd9d2f39e9ab3cb3039f26677Xavier Ducrohet        return result;
908b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet    }
909b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
91033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    /**
91133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * Moves a View from its current parent to a new given parent at a new given location, with
91233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * an optional new {@link LayoutParams} instance
91333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
91462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet     * @param previousParent the previous parent, still owning the child at the time of the call.
91562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet     * @param newParent the new parent
91624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet     * @param movedView the view to move
91733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @param index the new location in the new parent
91833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @param params an option (can be null) {@link LayoutParams} instance.
91933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
920ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     * @return a Result with {@link Status#SUCCESS} or
921ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
92233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *     adding views.
92333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     */
92424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet    private Result moveView(ViewGroup previousParent, final ViewGroup newParent,
92524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            final View movedView, final int index, final LayoutParams params) {
9261392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet        try {
92762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet            // check if there is a transition on the previousParent.
92824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            LayoutTransition previousTransition = previousParent.getLayoutTransition();
92924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet            if (previousTransition != null) {
9305562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // in this case there is an animation. This means we have to wait for the child's
9315562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // parent reference to be null'ed out so that we can add it to the new parent.
9325562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // It is technically removed right before the DISAPPEARING animation is done (if
9335562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // the animation of this type is not null, otherwise it's after which is impossible
9345562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // to handle).
9355562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // Because there is no move animation, if the new parent is the same as the old
9365562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before
9375562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // adding the child or the child will appear in its new location before the
9385562208aafcaccf366dd8cd906700f48c6c342a8Xavier Ducrohet                // other children have made room for it.
93962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
94062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                // add a listener to the transition to be notified of the actual removal.
94124cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                previousTransition.addTransitionListener(new TransitionListener() {
94224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    private int mChangeDisappearingCount = 0;
94362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
944d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohet                    @Override
94562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                    public void startTransition(LayoutTransition transition, ViewGroup container,
94662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                            View view, int transitionType) {
94724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
94824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            mChangeDisappearingCount++;
94924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        }
95062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                    }
95133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
952d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohet                    @Override
95362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                    public void endTransition(LayoutTransition transition, ViewGroup container,
95462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                            View view, int transitionType) {
95524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
95624cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                            mChangeDisappearingCount--;
95724cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        }
95824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet
95924cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING &&
96024cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                                mChangeDisappearingCount == 0) {
96162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                            // add it to the parentView in the correct location
96262039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                            if (params != null) {
96324cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                                newParent.addView(movedView, index, params);
96462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                            } else {
96524cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                                newParent.addView(movedView, index);
96662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                            }
96762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                        }
96862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                    }
96962039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                });
97062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
97162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                // remove the view from the current parent.
97224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                previousParent.removeView(movedView);
97362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
97462039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                // and return since adding the view to the new parent is done in the listener.
97562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                return SUCCESS.createResult();
97633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            } else {
97762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                // standard code with no animation. pretty simple.
97824cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                previousParent.removeView(movedView);
97933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
98062039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                // add it to the parentView in the correct location
98162039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                if (params != null) {
98224cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    newParent.addView(movedView, index, params);
98362039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                } else {
98424cdf6c407351a157880a0a1bbf65c95af753418Xavier Ducrohet                    newParent.addView(movedView, index);
98562039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                }
98662039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet
98762039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet                return SUCCESS.createResult();
98862039873060d26a7be141573b0f468c5ba0414dcXavier Ducrohet            }
9891392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet        } catch (UnsupportedOperationException e) {
9901392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet            // looks like this is a view class that doesn't support children manipulation!
991ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
992b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        }
99333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    }
99433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
99533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    /**
99633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * Removes a child from its current parent.
99733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * <p>
99833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
99933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
100033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
100133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
100233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
1003799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet     * @see RenderSession#removeChild(Object, IAnimationListener)
100433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     */
1005ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public Result removeChild(final View childView, IAnimationListener listener) {
100633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        checkLock();
1007b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
10081392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet        invalidateRenderingSize();
10091392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet
101033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        final ViewGroup parent = (ViewGroup) childView.getParent();
101133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
101233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        if (listener != null) {
101333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            new AnimationThread(this, "moveChild", listener) {
101433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
101533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                @Override
1016ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet                public Result preAnimation() {
101733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    parent.setLayoutTransition(new LayoutTransition());
101833840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    return removeView(parent, childView);
101933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                }
102033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
102133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                @Override
102233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                public void postAnimation() {
102333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                    parent.setLayoutTransition(null);
102433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet                }
102533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            }.start();
102633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
102733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            // always return success since the real status will come through the listener.
1028ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult();
102933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
103033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
1031ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet        Result result = removeView(parent, childView);
1032952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!result.isSuccess()) {
103333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            return result;
103433840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
103533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
10364c6c050f68c67097b92eb38e9f01dae9885907caXavier Ducrohet        return render(false /*freshRender*/);
1037ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet    }
1038ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
1039ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet    /**
104033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * Removes a given view from its current parent.
104133840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
104233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     * @param view the view to remove from its parent
104333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *
1044ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     * @return a Result with {@link Status#SUCCESS} or
1045ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
104633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     *     adding views.
104733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet     */
1048ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    private Result removeView(ViewGroup parent, View view) {
104933840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        try {
105033840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            parent.removeView(view);
1051ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return SUCCESS.createResult();
105233840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        } catch (UnsupportedOperationException e) {
105333840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet            // looks like this is a view class that doesn't support children manipulation!
1054ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
105533840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet        }
105633840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet    }
105733840c00b3b56db9613dcd33abd69601b711ce69Xavier Ducrohet
1058ddea50d03cdda807bbaea54beffd7a341c51f770Xavier Ducrohet
1059a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    private void findBackground(RenderResources resources) {
1060952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!getParams().isBgColorOverridden()) {
106141fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet            mWindowBackground = resources.findItemInTheme("windowBackground",
106241fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet                    true /*isFrameworkAttr*/);
1063a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            if (mWindowBackground != null) {
1064a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet                mWindowBackground = resources.resolveResValue(mWindowBackground);
1065a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            }
1066a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        }
1067a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    }
10683bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
106964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet    private boolean hasSoftwareButtons() {
107064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet        return getParams().getHardwareConfig().hasSoftwareButtons();
1071a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    }
10723bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1073a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    private void findStatusBar(RenderResources resources, DisplayMetrics metrics) {
107464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet        boolean windowFullscreen = getBooleanThemeValue(resources,
107545d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta                "windowFullscreen", false, !isThemeAppCompat(resources));
1076a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1077952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!windowFullscreen && !mWindowIsFloating) {
107864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            // default value
107964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT;
1080a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
108164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            // get the real value
108264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
108364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    "status_bar_height");
1084a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
108564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            if (value != null) {
108664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                TypedValue typedValue = ResourceHelper.getValue("status_bar_height",
108764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                        value.getValue(), true /*requireUnit*/);
108864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                if (typedValue != null) {
108964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    // compute the pixel value based on the display metrics
109064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    mStatusBarSize = (int)typedValue.getDimension(metrics);
1091a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet                }
1092a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            }
1093a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        }
1094a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    }
1095a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1096799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    private void findActionBar(RenderResources resources, DisplayMetrics metrics) {
1097799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet        if (mWindowIsFloating) {
1098799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            return;
1099a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        }
1100a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1101a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        boolean windowActionBar = getBooleanThemeValue(resources,
110245d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta                "windowActionBar", true, !isThemeAppCompat(resources));
1103a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1104a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        // if there's a value and it's false (default is true)
1105a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        if (windowActionBar) {
11063bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
11073bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // default size of the window title bar
1108799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            mActionBarSize = DEFAULT_TITLE_BAR_HEIGHT;
11093bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
11103bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // get value from the theme.
111141fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet            ResourceValue value = resources.findItemInTheme("actionBarSize",
111241fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet                    true /*isFrameworkAttr*/);
11133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
11143bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // resolve it
1115a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            value = resources.resolveResValue(value);
11163bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
11173bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            if (value != null) {
11183bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                // get the numerical value, if available
1119d7e9eda58981700df39f08ee8465de236eeed2d4Xavier Ducrohet                TypedValue typedValue = ResourceHelper.getValue("actionBarSize", value.getValue(),
1120d7e9eda58981700df39f08ee8465de236eeed2d4Xavier Ducrohet                        true /*requireUnit*/);
11213bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                if (typedValue != null) {
11223bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    // compute the pixel value based on the display metrics
1123799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    mActionBarSize = (int)typedValue.getDimension(metrics);
11243bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                }
11253bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
1126799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet        } else {
1127799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            // action bar overrides title bar so only look for this one if action bar is hidden
1128799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            boolean windowNoTitle = getBooleanThemeValue(resources,
112945d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta                    "windowNoTitle", false, !isThemeAppCompat(resources));
11303bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1131952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            if (!windowNoTitle) {
1132a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1133799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                // default size of the window title bar
1134799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                mTitleBarSize = DEFAULT_TITLE_BAR_HEIGHT;
1135a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1136799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                // get value from the theme.
113741fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet                ResourceValue value = resources.findItemInTheme("windowTitleSize",
113841fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet                        true /*isFrameworkAttr*/);
1139a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1140799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                // resolve it
1141799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                value = resources.resolveResValue(value);
11423bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1143799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                if (value != null) {
1144799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    // get the numerical value, if available
1145d7e9eda58981700df39f08ee8465de236eeed2d4Xavier Ducrohet                    TypedValue typedValue = ResourceHelper.getValue("windowTitleSize",
1146d7e9eda58981700df39f08ee8465de236eeed2d4Xavier Ducrohet                            value.getValue(), true /*requireUnit*/);
1147799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    if (typedValue != null) {
1148799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                        // compute the pixel value based on the display metrics
1149799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                        mTitleBarSize = (int)typedValue.getDimension(metrics);
1150799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet                    }
1151a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet                }
1152a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            }
1153799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
1154a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        }
1155a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    }
1156a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
115764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet    private void findNavigationBar(RenderResources resources, DisplayMetrics metrics) {
1158952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (hasSoftwareButtons() && !mWindowIsFloating) {
11593bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
11603bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            // default value
116164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            mNavigationBarSize = 48; // ??
116264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
116364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            HardwareConfig hardwareConfig = getParams().getHardwareConfig();
116464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
116564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            boolean barOnBottom = true;
116664f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
116764f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            if (hardwareConfig.getOrientation() == ScreenOrientation.LANDSCAPE) {
116864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                // compute the dp of the screen.
116964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                int shortSize = hardwareConfig.getScreenHeight();
117064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
117164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                // compute in dp
1172952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT /
1173952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                        hardwareConfig.getDensity().getDpiValue();
117464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
1175952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                // 0-599dp: "phone" UI with bar on the side
1176952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                // 600+dp: "tablet" UI with bar on the bottom
1177952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                barOnBottom = shortSizeDp >= 600;
117864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            }
117964f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet
118064f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            if (barOnBottom) {
118164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                mNavigationBarOrientation = LinearLayout.HORIZONTAL;
118264f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            } else {
118364f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                mNavigationBarOrientation = LinearLayout.VERTICAL;
118464f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet            }
11853bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1186089143ffed72bb47fd8d870f29caffb646138781Xavier Ducrohet            // get the real value
11871b5ef2d19e1d7cb491c1c79f867e38ec0bde2770Xavier Ducrohet            ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
118864f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    barOnBottom ? "navigation_bar_height" : "navigation_bar_width");
1189a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
11903bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            if (value != null) {
119164f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                TypedValue typedValue = ResourceHelper.getValue("navigation_bar_height",
1192d7e9eda58981700df39f08ee8465de236eeed2d4Xavier Ducrohet                        value.getValue(), true /*requireUnit*/);
11933bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                if (typedValue != null) {
11943bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    // compute the pixel value based on the display metrics
119564f5dc0e6437e95695ed4048f047c3cbef447e0fXavier Ducrohet                    mNavigationBarSize = (int)typedValue.getDimension(metrics);
11963bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                }
11973bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
1198a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        }
1199a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    }
1200a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
120145d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta    private boolean isThemeAppCompat(RenderResources resources) {
120245d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta        // Ideally, we should check if the corresponding activity extends
120345d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta        // android.support.v7.app.ActionBarActivity, and not care about the theme name at all.
120445d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta        if (mIsThemeAppCompat == null) {
120545d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta            StyleResourceValue defaultTheme = resources.getDefaultTheme();
1206841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta          // We can't simply check for parent using resources.themeIsParentOf() since the
1207841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta          // inheritance structure isn't really what one would expect. The first common parent
1208841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta          // between Theme.AppCompat.Light and Theme.AppCompat is Theme.Material (for v21).
1209841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta            boolean isThemeAppCompat = false;
1210841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta            for (int i = 0; i < 50; i++) {
1211841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta                // for loop ensures that we don't run into cyclic theme inheritance.
1212841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta                if (defaultTheme.getName().startsWith("Theme.AppCompat")) {
1213841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta                    isThemeAppCompat = true;
1214841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta                    break;
1215841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta                }
1216841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta                defaultTheme = resources.getParent(defaultTheme);
1217841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta                if (defaultTheme == null) {
1218841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta                    break;
1219841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta                }
1220841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta            }
1221841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta            mIsThemeAppCompat = isThemeAppCompat;
122245d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta        }
122345d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta        return mIsThemeAppCompat;
122445d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta    }
122545d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta
122641fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet    /**
122745d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta     * Looks for an attribute in the current theme.
122841fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet     *
122941fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet     * @param resources the render resources
123041fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet     * @param name the name of the attribute
123141fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet     * @param defaultValue the default value.
123245d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta     * @param isFrameworkAttr if the attribute is in android namespace
123341fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet     * @return the value of the attribute or the default one if not found.
123441fb2853aa6de48c3b657bd6be32797dfac2103bXavier Ducrohet     */
1235a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    private boolean getBooleanThemeValue(RenderResources resources,
123645d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta            String name, boolean defaultValue, boolean isFrameworkAttr) {
1237a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
123845d9520182663e47a1878ce51be756219799b2c9Deepanshu Gupta        ResourceValue value = resources.findItemInTheme(name, isFrameworkAttr);
1239a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1240a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        // because it may reference something else, we resolve it.
1241a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        value = resources.resolveResValue(value);
12423bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1243a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        // if there's no value, return the default.
1244a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        if (value == null || value.getValue() == null) {
1245a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet            return defaultValue;
12463bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
12473bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1248a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        return XmlUtils.convertValueToBoolean(value.getValue(), defaultValue);
12493bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
12503bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
12513bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
1252952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta     * Post process on a view hierarchy that was just inflated.
1253952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta     * <p/>
1254952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta     * At the moment this only supports TabHost: If {@link TabHost} is detected, look for the
12553bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically
12563bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * based on the content of the {@link FrameLayout}.
12573bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * @param view the root view to process.
12583bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * @param projectCallback callback to the project.
12598a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta     * @param skip the view and it's children are not processed.
12603bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     */
1261952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta    @SuppressWarnings("deprecation")  // For the use of Pair
12628a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta    private void postInflateProcess(View view, IProjectCallback projectCallback, View skip)
12633bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            throws PostInflateException {
12648a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta        if (view == skip) {
12658a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta            return;
12668a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta        }
12673bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        if (view instanceof TabHost) {
12688a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta            setupTabHost((TabHost) view, projectCallback);
126962c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohet        } else if (view instanceof QuickContactBadge) {
127062c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohet            QuickContactBadge badge = (QuickContactBadge) view;
127162c9c3463a9b4a4bc899f5db353f2856876e6590Xavier Ducrohet            badge.setImageToDefault();
12727062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet        } else if (view instanceof AdapterView<?>) {
12737062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            // get the view ID.
12747062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            int id = view.getId();
12757062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12767062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            BridgeContext context = getContext();
12777062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12787062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            // get a ResourceReference from the integer ID.
12797062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            ResourceReference listRef = context.resolveId(id);
12807062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12817062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            if (listRef != null) {
12827062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                SessionParams params = getParams();
12837062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                AdapterBinding binding = params.getAdapterBindings().get(listRef);
12847062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12857062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                // if there was no adapter binding, trying to get it from the call back.
12867062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                if (binding == null) {
12877062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                    binding = params.getProjectCallback().getAdapterBinding(listRef,
12887062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            context.getViewKey(view), view);
12897062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                }
12907062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12917062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                if (binding != null) {
12927062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12937062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                    if (view instanceof AbsListView) {
12947062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                        if ((binding.getFooterCount() > 0 || binding.getHeaderCount() > 0) &&
12957062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                view instanceof ListView) {
12967062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            ListView list = (ListView) view;
12977062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
12987062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            boolean skipCallbackParser = false;
12997062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
13007062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            int count = binding.getHeaderCount();
13018a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta                            for (int i = 0; i < count; i++) {
13027062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                Pair<View, Boolean> pair = context.inflateView(
13037062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                        binding.getHeaderAt(i),
13047062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                        list, false /*attachToRoot*/, skipCallbackParser);
13057062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                if (pair.getFirst() != null) {
13067062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                    list.addHeaderView(pair.getFirst());
13077062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                }
13087062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
13097062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                skipCallbackParser |= pair.getSecond();
13107062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            }
13117062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
13127062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            count = binding.getFooterCount();
13138a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta                            for (int i = 0; i < count; i++) {
13147062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                Pair<View, Boolean> pair = context.inflateView(
13157062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                        binding.getFooterAt(i),
13167062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                        list, false /*attachToRoot*/, skipCallbackParser);
13177062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                if (pair.getFirst() != null) {
13187062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                    list.addFooterView(pair.getFirst());
13197062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                }
13207062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
13217062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                skipCallbackParser |= pair.getSecond();
13227062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            }
13237062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                        }
13247062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet
13257062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                        if (view instanceof ExpandableListView) {
13267062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            ((ExpandableListView) view).setAdapter(
13277062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                    new FakeExpandableAdapter(
13287062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                            listRef, binding, params.getProjectCallback()));
13297062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                        } else {
13307062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                            ((AbsListView) view).setAdapter(
13317062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                    new FakeAdapter(
13327062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                            listRef, binding, params.getProjectCallback()));
13337062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                        }
13347062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                    } else if (view instanceof AbsSpinner) {
13357062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                        ((AbsSpinner) view).setAdapter(
13367062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                new FakeAdapter(
13377062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                                        listRef, binding, params.getProjectCallback()));
13387062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                    }
13397062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet                }
13407062c1ad9adcb216ac49100ca1044e9d89e8f8c1Xavier Ducrohet            }
13413bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        } else if (view instanceof ViewGroup) {
13428a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta            ViewGroup group = (ViewGroup) view;
13433bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            final int count = group.getChildCount();
13448a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta            for (int c = 0; c < count; c++) {
13453bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                View child = group.getChildAt(c);
13468a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta                postInflateProcess(child, projectCallback, skip);
13473bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
13483bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
13493bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
13503bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
13513bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
13523bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * Sets up a {@link TabHost} object.
13533bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * @param tabHost the TabHost to setup.
13543bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * @param projectCallback The project callback object to access the project R class.
13553bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     * @throws PostInflateException
13563bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     */
13573bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    private void setupTabHost(TabHost tabHost, IProjectCallback projectCallback)
13583bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            throws PostInflateException {
13593bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        // look for the TabWidget, and the FrameLayout. They have their own specific names
13603bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        View v = tabHost.findViewById(android.R.id.tabs);
13613bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
13623bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        if (v == null) {
13633bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            throw new PostInflateException(
13643bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    "TabHost requires a TabWidget with id \"android:id/tabs\".\n");
13653bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
13663bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1367952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!(v instanceof TabWidget)) {
13683bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            throw new PostInflateException(String.format(
13693bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    "TabHost requires a TabWidget with id \"android:id/tabs\".\n" +
13703bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName()));
13713bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
13723bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
13733bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        v = tabHost.findViewById(android.R.id.tabcontent);
13743bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
13753bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        if (v == null) {
1376952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            // TODO: see if we can fake tabs even without the FrameLayout (same below when the frameLayout is empty)
1377952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            //noinspection SpellCheckingInspection
13783bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            throw new PostInflateException(
13793bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    "TabHost requires a FrameLayout with id \"android:id/tabcontent\".");
13803bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
13813bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1382952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        if (!(v instanceof FrameLayout)) {
1383952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            //noinspection SpellCheckingInspection
13843bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            throw new PostInflateException(String.format(
13853bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" +
13863bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet                    "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName()));
13873bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
13883bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
13893bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        FrameLayout content = (FrameLayout)v;
13903bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1391952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta        // now process the content of the frameLayout and dynamically create tabs for it.
13923bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        final int count = content.getChildCount();
13933bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
13943bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        // this must be called before addTab() so that the TabHost searches its TabWidget
13953bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        // and FrameLayout.
13963bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        tabHost.setup();
13973bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1398f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye        if (count == 0) {
1399f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye            // Create a dummy child to get a single tab
1400f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye            TabSpec spec = tabHost.newTabSpec("tag").setIndicator("Tab Label",
1401f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                    tabHost.getResources().getDrawable(android.R.drawable.ic_menu_info_details))
1402f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                    .setContent(new TabHost.TabContentFactory() {
1403d98e133b3911b8db3430ce9d85efd5a6adcf70bfXavier Ducrohet                        @Override
1404f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                        public View createTabContent(String tag) {
14050fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet                            return new LinearLayout(getContext());
1406f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                        }
1407f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                    });
1408f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye            tabHost.addTab(spec);
1409f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye        } else {
1410952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta            // for each child of the frameLayout, add a new TabSpec
1411f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye            for (int i = 0 ; i < count ; i++) {
1412f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                View child = content.getChildAt(i);
1413f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                String tabSpec = String.format("tab_spec%d", i+1);
14148a16d5d203a48e7b13761f329333b3dcb8f8210bDeepanshu Gupta                @SuppressWarnings("ConstantConditions")  // child cannot be null.
1415f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                int id = child.getId();
1416952c989b307d4b710ee1adba064f663808af9eb3Deepanshu Gupta                @SuppressWarnings("deprecation")
1417947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohet                Pair<ResourceType, String> resource = projectCallback.resolveResourceId(id);
1418f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                String name;
1419f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                if (resource != null) {
1420947b979a91ac1cd556244d875d8b8d4fec8fd474Xavier Ducrohet                    name = resource.getSecond();
1421f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                } else {
1422f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                    name = String.format("Tab %d", i+1); // default name if id is unresolved.
1423f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                }
1424f14c342b8a0024e5ca8c2c3ffce8b79abe03e941Tor Norbye                tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id));
14253bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            }
14263bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
14273bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
14283bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
142985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    /**
143085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Visits a {@link View} and its children and generate a {@link ViewInfo} containing the
143185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * bounds of all the views.
143285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *
143385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param view the root View
143485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param offset an offset for the view bounds.
143585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
143685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
143785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *                       content frame.
143885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *
143985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @return {@code ViewInfo} containing the bounds of the view and it children otherwise.
144085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     */
144185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private ViewInfo visit(View view, int offset, boolean setExtendedInfo,
144285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            boolean isContentFrame) {
144385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        ViewInfo result = createViewInfo(view, offset, setExtendedInfo, isContentFrame);
1444799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
144585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (view instanceof ViewGroup) {
144685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            ViewGroup group = ((ViewGroup) view);
144785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            result.setChildren(visitAllChildren(group, isContentFrame ? 0 : offset,
144885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    setExtendedInfo, isContentFrame));
144985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        }
145085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        return result;
145185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    }
1452799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
145385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    /**
145485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Visits all the children of a given ViewGroup and generates a list of {@link ViewInfo}
14558d43509cc2c0f95bd07d6585dadfac296bc5d24dDeepanshu Gupta     * containing the bounds of all the views. It also initializes the {@link #mViewInfoList} with
145685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * the children of the {@code mContentRoot}.
145785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *
145885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param viewGroup the root View
145985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param offset an offset from the top for the content view frame.
146085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
146185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
146285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *                       content frame. {@code false} if the {@code ViewInfo} to be created is
146385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *                       part of the system decor.
146485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     */
146585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset,
146685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            boolean setExtendedInfo, boolean isContentFrame) {
146785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (viewGroup == null) {
146885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            return null;
1469799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet        }
1470799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
147185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (!isContentFrame) {
147285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            offset += viewGroup.getTop();
147385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        }
1474799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
147585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        int childCount = viewGroup.getChildCount();
147685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (viewGroup == mContentRoot) {
147785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            List<ViewInfo> childrenWithoutOffset = new ArrayList<ViewInfo>(childCount);
147885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            List<ViewInfo> childrenWithOffset = new ArrayList<ViewInfo>(childCount);
147985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            for (int i = 0; i < childCount; i++) {
148085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                ViewInfo[] childViewInfo = visitContentRoot(viewGroup.getChildAt(i), offset,
14816208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet                        setExtendedInfo);
148285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                childrenWithoutOffset.add(childViewInfo[0]);
148385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                childrenWithOffset.add(childViewInfo[1]);
1484799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet            }
148585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            mViewInfoList = childrenWithOffset;
148685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            return childrenWithoutOffset;
148785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        } else {
148885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            List<ViewInfo> children = new ArrayList<ViewInfo>(childCount);
148985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            for (int i = 0; i < childCount; i++) {
149085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo,
149185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                        isContentFrame));
149285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            }
149385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            return children;
1494799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet        }
149585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    }
1496799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet
149785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    /**
149885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Visits the children of {@link #mContentRoot} and generates {@link ViewInfo} containing the
149985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * bounds of all the views. It returns two {@code ViewInfo} objects with the same children,
150085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * one with the {@code offset} and other without the {@code offset}. The offset is needed to
150185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * get the right bounds if the {@code ViewInfo} hierarchy is accessed from
150285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * {@code mViewInfoList}. When the hierarchy is accessed via {@code mSystemViewInfoList}, the
150385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * offset is not needed.
150485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *
150585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @return an array of length two, with ViewInfo at index 0 is without offset and ViewInfo at
150685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *         index 1 is with the offset.
150785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     */
150885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private ViewInfo[] visitContentRoot(View view, int offset, boolean setExtendedInfo) {
150985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        ViewInfo[] result = new ViewInfo[2];
151085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (view == null) {
151185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            return result;
151285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        }
151385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta
151485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        result[0] = createViewInfo(view, 0, setExtendedInfo, true);
151585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        result[1] = createViewInfo(view, offset, setExtendedInfo, true);
151685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (view instanceof ViewGroup) {
151785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            List<ViewInfo> children = visitAllChildren((ViewGroup) view, 0, setExtendedInfo, true);
151885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            result[0].setChildren(children);
151985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            result[1].setChildren(children);
152085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        }
152185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        return result;
1522799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    }
15233bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
15243bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    /**
152585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Creates a {@link ViewInfo} for the view. The {@code ViewInfo} corresponding to the children
152685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * of the {@code view} are not created. Consequently, the children of {@code ViewInfo} is not
152785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * set.
152885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param offset an offset for the view bounds. Used only if view is part of the content frame.
15293bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet     */
153085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private ViewInfo createViewInfo(View view, int offset, boolean setExtendedInfo,
153185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            boolean isContentFrame) {
15323bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        if (view == null) {
15333bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet            return null;
15343bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        }
15353bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
153685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        ViewInfo result;
153785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (isContentFrame) {
153870114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // The view is part of the layout added by the user. Hence,
153970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // the ViewCookie may be obtained only through the Context.
154085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            result = new ViewInfo(view.getClass().getName(),
154170114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    getContext().getViewKey(view),
154285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    view.getLeft(), view.getTop() + offset, view.getRight(),
154385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    view.getBottom() + offset, view, view.getLayoutParams());
154485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        } else {
154570114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // We are part of the system decor.
154670114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            SystemViewInfo r = new SystemViewInfo(view.getClass().getName(),
154741670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta                    getViewKey(view),
154885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    view.getLeft(), view.getTop(), view.getRight(),
154985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    view.getBottom(), view, view.getLayoutParams());
155070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            result = r;
155170114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // We currently mark three kinds of views:
155270114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // 1. Menus in the Action Bar
155370114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // 2. Menus in the Overflow popup.
155470114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            // 3. The overflow popup button.
155570114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            if (view instanceof ListMenuItemView) {
155670114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                // Mark 2.
155770114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                // All menus in the popup are of type ListMenuItemView.
155870114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                r.setViewType(ViewType.ACTION_BAR_OVERFLOW_MENU);
155970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            } else {
156070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                // Mark 3.
156170114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                ViewGroup.LayoutParams lp = view.getLayoutParams();
156270114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                if (lp instanceof ActionMenuView.LayoutParams &&
156370114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                        ((ActionMenuView.LayoutParams) lp).isOverflowButton) {
156470114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    r.setViewType(ViewType.ACTION_BAR_OVERFLOW);
156570114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                } else {
156670114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    // Mark 1.
156770114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    // A view is a menu in the Action Bar is it is not the overflow button and of
156870114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    // its parent is of type ActionMenuView. We can also check if the view is
156970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    // instanceof ActionMenuItemView but that will fail for menus using
157070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    // actionProviderClass.
157170114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    ViewParent parent = view.getParent();
157270114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    while (parent != mViewRoot && parent instanceof ViewGroup) {
157370114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                        if (parent instanceof ActionMenuView) {
157470114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                            r.setViewType(ViewType.ACTION_BAR_MENU);
157570114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                            break;
157670114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                        }
157770114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                        parent = parent.getParent();
157870114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                    }
157970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta                }
158070114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta            }
158185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        }
15823bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
15836208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet        if (setExtendedInfo) {
15846208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet            MarginLayoutParams marginParams = null;
15856208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet            LayoutParams params = view.getLayoutParams();
15866208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet            if (params instanceof MarginLayoutParams) {
15876208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet                marginParams = (MarginLayoutParams) params;
15886208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet            }
15896208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet            result.setExtendedInfo(view.getBaseline(),
15906208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet                    marginParams != null ? marginParams.leftMargin : 0,
15916208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet                    marginParams != null ? marginParams.topMargin : 0,
15926208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet                    marginParams != null ? marginParams.rightMargin : 0,
15936208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet                    marginParams != null ? marginParams.bottomMargin : 0);
15946208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet        }
15956208081afd488af51d4f7cbf858e2de59d47e4e5Xavier Ducrohet
15963bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        return result;
15973bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
15983bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
159970114b33f8054cc38090a2bbd213ebf15abee63dDeepanshu Gupta    /* (non-Javadoc)
160041670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta     * The cookie for menu items are stored in menu item and not in the map from View stored in
160141670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta     * BridgeContext.
160241670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta     */
160341670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta    private Object getViewKey(View view) {
160441670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        BridgeContext context = getContext();
160541670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        if (!(view instanceof MenuView.ItemView)) {
160641670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            return context.getViewKey(view);
160741670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        }
160841670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        MenuItemImpl menuItem;
160941670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        if (view instanceof ActionMenuItemView) {
161041670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            menuItem = ((ActionMenuItemView) view).getItemData();
161141670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        } else if (view instanceof ListMenuItemView) {
161241670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            menuItem = ((ListMenuItemView) view).getItemData();
161341670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        } else if (view instanceof IconMenuItemView) {
161441670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            menuItem = ((IconMenuItemView) view).getItemData();
161541670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        } else {
161641670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            menuItem = null;
161741670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        }
161841670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        if (menuItem instanceof BridgeMenuItemImpl) {
161941670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta            return ((BridgeMenuItemImpl) menuItem).getViewCookie();
162041670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        }
162141670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta
162241670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta        return null;
162341670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta    }
162441670df819e35f5822cc166db775ed2e9e3dfb7dDeepanshu Gupta
1625620f80a7ee9796c2c41ec0a42d10d2913fc50c90Diego Perez    public void invalidateRenderingSize() {
162685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        mMeasuredScreenWidth = mMeasuredScreenHeight = -1;
162785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    }
162885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta
1629799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet    /**
163085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Creates the status bar with wifi and battery icons.
1631799fe3b371c812a0e94872f896b54afa44e94868Xavier Ducrohet     */
163285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private StatusBar createStatusBar(BridgeContext context, Density density, int direction,
1633f18273f698024ffa23ce457e7d30c683e7027680Deepanshu Gupta            boolean isRtlSupported, int platformVersion) throws XmlPullParserException {
163485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        StatusBar statusBar = new StatusBar(context, density,
1635f18273f698024ffa23ce457e7d30c683e7027680Deepanshu Gupta                direction, isRtlSupported, platformVersion);
163685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        statusBar.setLayoutParams(
163785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                new LinearLayout.LayoutParams(
163885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                        LayoutParams.MATCH_PARENT, mStatusBarSize));
163985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        return statusBar;
164085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    }
1641e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet
164285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    /**
164385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Creates the navigation bar with back, home and recent buttons.
164485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *
164585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param isRtl true if the current locale is right-to-left
164685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * @param isRtlSupported true is the project manifest declares that the application
164785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     *        is RTL aware.
164885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     */
164985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    private NavigationBar createNavigationBar(BridgeContext context, Density density,
1650bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta            boolean isRtl, boolean isRtlSupported, int simulatedPlatformVersion)
1651bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta            throws XmlPullParserException {
165285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        NavigationBar navigationBar = new NavigationBar(context,
165385c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                density, mNavigationBarOrientation, isRtl,
1654bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta                isRtlSupported, simulatedPlatformVersion);
165585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        if (mNavigationBarOrientation == LinearLayout.VERTICAL) {
165685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            navigationBar.setLayoutParams(new LinearLayout.LayoutParams(mNavigationBarSize,
165785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    LayoutParams.MATCH_PARENT));
165885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        } else {
165985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            navigationBar.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
166085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                    mNavigationBarSize));
1661e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet        }
166285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        return navigationBar;
1663e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet    }
1664e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet
1665bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta    private TitleBar createTitleBar(BridgeContext context, String title,
1666bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta            int simulatedPlatformVersion)
166785c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta            throws XmlPullParserException {
1668bf50447839d4cdb1765d308a67aca43bb77cedbcDeepanshu Gupta        TitleBar titleBar = new TitleBar(context, title, simulatedPlatformVersion);
166985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        titleBar.setLayoutParams(
167085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta                new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, mTitleBarSize));
167185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        return titleBar;
167285c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    }
1673e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet
167485c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    /**
167585c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     * Creates the action bar. Also queries the project callback for missing information.
167685c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta     */
1677841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta    private BridgeActionBar createActionBar(BridgeContext context, SessionParams params,
1678cc1ce2c8d83464c7be38e3281bf8da3963505a9bDeepanshu Gupta            ViewGroup parentView) {
1679841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta        if (mIsThemeAppCompat == Boolean.TRUE) {
1680841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta            return new AppCompatActionBar(context, params, parentView);
1681841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta        } else {
1682841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta            return new FrameworkActionBar(context, params, parentView);
1683841330d24b2403832c91d379795f5bcbd938c3b7Deepanshu Gupta        }
16841392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet    }
16851392615c49943383baf51262e2df6975266b4c2fXavier Ducrohet
16863bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    public BufferedImage getImage() {
16873bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet        return mImage;
16883bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
16893bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet
1690a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    public boolean isAlphaChannelImage() {
1691a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet        return mIsAlphaChannelImage;
1692a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet    }
1693a6a38c02bfd3f6a678ac1671f5744b8e439e075aXavier Ducrohet
1694e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet    public List<ViewInfo> getViewInfos() {
1695e9a2ea4ac32589b372ec195d8be59391c686a8c6Xavier Ducrohet        return mViewInfoList;
16963bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet    }
16972d240967c9bc38cbf69967457b33f953f8826e96Xavier Ducrohet
169885c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    public List<ViewInfo> getSystemViewInfos() {
169985c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta        return mSystemViewInfoList;
170085c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta    }
170185c5ae75ab4b9041bb143f146ef5fc4547686210Deepanshu Gupta
1702ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public Map<String, String> getDefaultProperties(Object viewObject) {
17030fde9af6be75b32a401eafc8904426424e00e70cXavier Ducrohet        return getContext().getDefaultPropMap(viewObject);
17042d240967c9bc38cbf69967457b33f953f8826e96Xavier Ducrohet    }
1705b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
1706ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public void setScene(RenderSession session) {
1707ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet        mScene = session;
1708b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet    }
1709b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet
1710ecb67b629266bd616da571c1e391164a4f8c8e93Xavier Ducrohet    public RenderSession getSession() {
1711b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet        return mScene;
1712b12b63f973ebf8fdc4f36f77dd29bd1bed436609Xavier Ducrohet    }
17133bd98986a97e4e1921616a0a86983307e68ceb6cXavier Ducrohet}
1714