RenderSessionImpl.java revision 1b87390c9426c4bc9119829e9375d712dfde11c3
1c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet/*
2c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Copyright (C) 2010 The Android Open Source Project
3c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet *
4c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License");
5c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * you may not use this file except in compliance with the License.
6c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * You may obtain a copy of the License at
7c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet *
8c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet *      http://www.apache.org/licenses/LICENSE-2.0
9c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet *
10c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * Unless required by applicable law or agreed to in writing, software
11c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS,
12c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * See the License for the specific language governing permissions and
14c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * limitations under the License.
15c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */
16c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
17c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetpackage com.android.layoutlib.bridge.impl;
18c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_ANIM_NOT_FOUND;
2019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_INFLATION;
2119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLATED;
2219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN;
2319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP_NO_CHILDREN;
2419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
2519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet
262fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.ide.common.rendering.api.AdapterBinding;
27891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport com.android.ide.common.rendering.api.HardwareConfig;
2819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.IAnimationListener;
2919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.ILayoutPullParser;
3019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.IProjectCallback;
31bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderParams;
3270552fb92dbc5cb5b1d53b20f92f2a64969a50c4Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderResources;
3319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderSession;
342fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.ide.common.rendering.api.ResourceReference;
3519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.ResourceValue;
3619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.Result;
3719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.Result.Status;
3846d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams;
391126422ee1f532d8582a4e3b56dbfe505c15e775Xavier Ducrohetimport com.android.ide.common.rendering.api.SessionParams.RenderingMode;
4046d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport com.android.ide.common.rendering.api.ViewInfo;
41c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.internal.util.XmlUtils;
422eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohetimport com.android.layoutlib.bridge.Bridge;
43c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeContext;
4401811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
45c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
46891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport com.android.layoutlib.bridge.bars.NavigationBar;
47891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport com.android.layoutlib.bridge.bars.StatusBar;
48bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohetimport com.android.layoutlib.bridge.bars.TitleBar;
491b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Guptaimport com.android.layoutlib.bridge.bars.ActionBarLayout;
502fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeAdapter;
512fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter;
524ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Guptaimport com.android.resources.Density;
5335ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohetimport com.android.resources.ResourceType;
54891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport com.android.resources.ScreenOrientation;
55b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohetimport com.android.util.Pair;
56c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
57bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohetimport org.xmlpull.v1.XmlPullParserException;
58bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
597f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.animation.AnimationThread;
60e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohetimport android.animation.Animator;
612eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohetimport android.animation.AnimatorInflater;
62e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohetimport android.animation.LayoutTransition;
632b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohetimport android.animation.LayoutTransition.TransitionListener;
64c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.app.Fragment_Delegate;
65c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Bitmap;
66c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Bitmap_Delegate;
67c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Canvas;
68c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.drawable.Drawable;
69c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.util.DisplayMetrics;
70c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.util.TypedValue;
717f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.view.AttachInfo_Accessor;
727f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.view.BridgeInflater;
736dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.IWindowManager;
74891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport android.view.IWindowManagerImpl;
756dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.Surface;
76c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.View;
77c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.View.MeasureSpec;
7846d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport android.view.ViewGroup;
7901811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohetimport android.view.ViewGroup.LayoutParams;
8005b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohetimport android.view.ViewGroup.MarginLayoutParams;
816dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.WindowManagerGlobal_Delegate;
822fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AbsListView;
832fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AbsSpinner;
842fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AdapterView;
852fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.ExpandableListView;
86c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.widget.FrameLayout;
87796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbyeimport android.widget.LinearLayout;
882fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.ListView;
8931fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohetimport android.widget.QuickContactBadge;
90c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.widget.TabHost;
91796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbyeimport android.widget.TabHost.TabSpec;
9246d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport android.widget.TabWidget;
93c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
945a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohetimport java.awt.AlphaComposite;
95c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.Color;
96c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.Graphics2D;
97c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.image.BufferedImage;
98c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.ArrayList;
99c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.List;
100c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.Map;
101c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
102c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet/**
10319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * Class implementing the render session.
104c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet *
10519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * A session is a stateful representation of a layout file. It is initialized with data coming
10619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then
107c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * be done on the layout.
108c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet *
109c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */
110b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetpublic class RenderSessionImpl extends RenderAction<SessionParams> {
111c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
112c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private static final int DEFAULT_TITLE_BAR_HEIGHT = 25;
113c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private static final int DEFAULT_STATUS_BAR_HEIGHT = 25;
114c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
115c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    // scene state
11619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    private RenderSession mScene;
117c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private BridgeXmlBlockParser mBlockParser;
118c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private BridgeInflater mInflater;
119ffb42f6c5043de226f02318a1311669d35a90711Xavier Ducrohet    private ResourceValue mWindowBackground;
120bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private ViewGroup mViewRoot;
121bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private FrameLayout mContentRoot;
1229eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet    private Canvas mCanvas;
1239eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet    private int mMeasuredScreenWidth = -1;
1249eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet    private int mMeasuredScreenHeight = -1;
125bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private boolean mIsAlphaChannelImage;
126bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private boolean mWindowIsFloating;
12716584225125acba18b74920b902c798dfead0328Xavier Ducrohet
12816584225125acba18b74920b902c798dfead0328Xavier Ducrohet    private int mStatusBarSize;
129891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet    private int mNavigationBarSize;
130891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet    private int mNavigationBarOrientation = LinearLayout.HORIZONTAL;
131bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private int mTitleBarSize;
132bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private int mActionBarSize;
13316584225125acba18b74920b902c798dfead0328Xavier Ducrohet
134c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
135c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    // information being returned through the API
136c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private BufferedImage mImage;
1377d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet    private List<ViewInfo> mViewInfoList;
1384ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    private List<ViewInfo> mSystemViewInfoList;
139c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
140c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private static final class PostInflateException extends Exception {
141c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        private static final long serialVersionUID = 1L;
142c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
143c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        public PostInflateException(String message) {
144c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            super(message);
145c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
146c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
147c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
148c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
149c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * Creates a layout scene with all the information coming from the layout bridge API.
150c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * <p>
1511b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta     * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init(long)},
1521b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta     * which act as a
15319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     * call to {@link RenderSessionImpl#acquire(long)}
154c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     *
1551b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta     * @see Bridge#createSession(SessionParams)
156c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     */
1571126422ee1f532d8582a4e3b56dbfe505c15e775Xavier Ducrohet    public RenderSessionImpl(SessionParams params) {
158b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        super(new SessionParams(params));
1592eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    }
1602eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
1612eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    /**
1622eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * Initializes and acquires the scene, creating various Android objects such as context,
1632eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * inflater, and parser.
1642eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *
1652eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @param timeout the time to wait if another rendering is happening.
1662eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *
1672eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @return whether the scene was prepared
1682eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *
1692eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @see #acquire(long)
1702eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @see #release()
1712eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     */
172b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    @Override
17319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public Result init(long timeout) {
174b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        Result result = super.init(timeout);
175b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        if (result.isSuccess() == false) {
1762eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            return result;
1772eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        }
178c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
179b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        SessionParams params = getParams();
180b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        BridgeContext context = getContext();
181c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
182b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        RenderResources resources = getParams().getResources();
183b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        DisplayMetrics metrics = getContext().getMetrics();
184c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
18516584225125acba18b74920b902c798dfead0328Xavier Ducrohet        // use default of true in case it's not found to use alpha by default
18616584225125acba18b74920b902c798dfead0328Xavier Ducrohet        mIsAlphaChannelImage  = getBooleanThemeValue(resources,
18716584225125acba18b74920b902c798dfead0328Xavier Ducrohet                "windowIsFloating", true /*defaultValue*/);
18816584225125acba18b74920b902c798dfead0328Xavier Ducrohet
189bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        mWindowIsFloating = getBooleanThemeValue(resources, "windowIsFloating",
190bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                true /*defaultValue*/);
1912eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
19216584225125acba18b74920b902c798dfead0328Xavier Ducrohet        findBackground(resources);
19316584225125acba18b74920b902c798dfead0328Xavier Ducrohet        findStatusBar(resources, metrics);
194bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        findActionBar(resources, metrics);
195891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet        findNavigationBar(resources, metrics);
196c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1976dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet        // FIXME: find those out, and possibly add them to the render params
1986dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet        boolean hasNavigationBar = true;
1996dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet        IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(),
2006dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet                metrics, Surface.ROTATION_0,
20180f00c1f2375796dab09bc4ed5b7631c62f7e158John Spurlock                hasNavigationBar);
2026dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet        WindowManagerGlobal_Delegate.setWindowManagerService(iwm);
2036dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet
204c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        // build the inflater and parser.
205b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        mInflater = new BridgeInflater(context, params.getProjectCallback());
206b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        context.setBridgeInflater(mInflater);
2072eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
20802d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet        mBlockParser = new BridgeXmlBlockParser(
20902d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet                params.getLayoutDescription(), context, false /* platformResourceFlag */);
2102eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
211168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet        return SUCCESS.createResult();
212c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
213c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
214c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
215c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * Inflates the layout.
216c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * <p>
2172eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
2182eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *
2192eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
2202eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *      the scene, or if {@link #init(long)} was not called.
221c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     */
22219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public Result inflate() {
2232eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        checkLock();
2242eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
225c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        try {
226c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
227b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            SessionParams params = getParams();
228891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            HardwareConfig hardwareConfig = params.getHardwareConfig();
229b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            BridgeContext context = getContext();
23088db0ee2afbae38b53a0527506f0890914a7f115Deepanshu Gupta            boolean isRtl = Bridge.isLocaleRtl(params.getLocale());
2314ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            int layoutDirection = isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
2321b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta            ActionBarLayout actionBar = null;
233891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
234abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet            // the view group that receives the window background.
235abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet            ViewGroup backgroundView = null;
236abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet
237b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            if (mWindowIsFloating || params.isForceNoDecor()) {
238abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                backgroundView = mViewRoot = mContentRoot = new FrameLayout(context);
2394ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                mViewRoot.setLayoutDirection(layoutDirection);
240bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            } else {
241891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                if (hasSoftwareButtons() && mNavigationBarOrientation == LinearLayout.VERTICAL) {
242891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    /*
243891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                     * This is a special case where the navigation bar is on the right.
244891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       +-------------------------------------------------+---+
245891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | Status bar (always)                             |   |
246891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       +-------------------------------------------------+   |
247891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | (Layout with background drawable)               |   |
248891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | +---------------------------------------------+ |   |
249891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | | Title/Action bar (optional)                 | |   |
250891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | +---------------------------------------------+ |   |
251891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | | Content, vertical extending                 | |   |
252891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | |                                             | |   |
253891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | +---------------------------------------------+ |   |
254891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       +-------------------------------------------------+---+
255891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
256891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       So we create a horizontal layout, with the nav bar on the right,
257891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       and the left part is the normal layout below without the nav bar at
258891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       the bottom
259891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                     */
260891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    LinearLayout topLayout = new LinearLayout(context);
2614ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    topLayout.setLayoutDirection(layoutDirection);
262891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    mViewRoot = topLayout;
263891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    topLayout.setOrientation(LinearLayout.HORIZONTAL);
264891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
265891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    try {
2664ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                        NavigationBar navigationBar = createNavigationBar(context,
2674ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                                hardwareConfig.getDensity(), isRtl, params.isRtlSupported());
268891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                        topLayout.addView(navigationBar);
269891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    } catch (XmlPullParserException e) {
270891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
271891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    }
272891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                }
273891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
274bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                /*
275bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                 * we're creating the following layout
276bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                 *
277bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                   +-------------------------------------------------+
278891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                   | Status bar (always)                             |
279bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                   +-------------------------------------------------+
280abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | (Layout with background drawable)               |
281abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | +---------------------------------------------+ |
282abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | | Title/Action bar (optional)                 | |
283abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | +---------------------------------------------+ |
284abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | | Content, vertical extending                 | |
285abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | |                                             | |
286abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | +---------------------------------------------+ |
287bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                   +-------------------------------------------------+
288891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                   | Navigation bar for soft buttons, maybe see above|
289bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                   +-------------------------------------------------+
290bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
291bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                 */
292bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
293b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                LinearLayout topLayout = new LinearLayout(context);
294bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                topLayout.setOrientation(LinearLayout.VERTICAL);
2954ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                topLayout.setLayoutDirection(layoutDirection);
296891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                // if we don't already have a view root this is it
297891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                if (mViewRoot == null) {
298891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    mViewRoot = topLayout;
299891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                } else {
3004ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    int topLayoutWidth =
3014ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                            params.getHardwareConfig().getScreenWidth() - mNavigationBarSize;
302891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
3034ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                            topLayoutWidth, LayoutParams.MATCH_PARENT);
304891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    topLayout.setLayoutParams(layoutParams);
305891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
306891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    // this is the case of soft buttons + vertical bar.
307891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    // this top layout is the first layout in the horizontal layout. see above)
30888db0ee2afbae38b53a0527506f0890914a7f115Deepanshu Gupta                    if (isRtl && params.isRtlSupported()) {
30988db0ee2afbae38b53a0527506f0890914a7f115Deepanshu Gupta                        // If RTL is enabled, layoutlib will mirror the layouts. So, add the
31088db0ee2afbae38b53a0527506f0890914a7f115Deepanshu Gupta                        // topLayout to the right of Navigation Bar and layoutlib will draw it
31188db0ee2afbae38b53a0527506f0890914a7f115Deepanshu Gupta                        // to the left.
31288db0ee2afbae38b53a0527506f0890914a7f115Deepanshu Gupta                        mViewRoot.addView(topLayout);
31388db0ee2afbae38b53a0527506f0890914a7f115Deepanshu Gupta                    } else {
31488db0ee2afbae38b53a0527506f0890914a7f115Deepanshu Gupta                        // Add the top layout to the left of the Navigation Bar.
31588db0ee2afbae38b53a0527506f0890914a7f115Deepanshu Gupta                        mViewRoot.addView(topLayout, 0);
31688db0ee2afbae38b53a0527506f0890914a7f115Deepanshu Gupta                    }
317891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                }
318bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
319bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                if (mStatusBarSize > 0) {
320bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    // system bar
321bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    try {
3224ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                        StatusBar statusBar = createStatusBar(context, hardwareConfig.getDensity(),
3234ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                                layoutDirection, params.isRtlSupported());
3244ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                        topLayout.addView(statusBar);
325bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    } catch (XmlPullParserException e) {
326bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
327bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    }
328bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                }
329bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
330abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                LinearLayout backgroundLayout = new LinearLayout(context);
331abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                backgroundView = backgroundLayout;
332abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                backgroundLayout.setOrientation(LinearLayout.VERTICAL);
333abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
33435d56c0d67537e56fafebd8edf790026644fe8deDeepanshu Gupta                        LayoutParams.MATCH_PARENT, 0);
335abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                layoutParams.weight = 1;
336abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                backgroundLayout.setLayoutParams(layoutParams);
337abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                topLayout.addView(backgroundLayout);
338abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet
339abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet
340bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                // if the theme says no title/action bar, then the size will be 0
341bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                if (mActionBarSize > 0) {
342bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    try {
3431b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta                        actionBar = createActionBar(context, params);
344abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                        backgroundLayout.addView(actionBar);
3451b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta                        actionBar.createMenuPopup();
3461b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta                        mContentRoot = actionBar.getContentRoot();
347bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    } catch (XmlPullParserException e) {
348bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
349bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    }
350bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                } else if (mTitleBarSize > 0) {
351bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    try {
3524ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                        TitleBar titleBar = createTitleBar(context,
353891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                                hardwareConfig.getDensity(), params.getAppLabel());
354abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                        backgroundLayout.addView(titleBar);
355bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    } catch (XmlPullParserException e) {
356bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
357bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    }
358bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                }
359bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
360bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                // content frame
3614ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                if (mContentRoot == null) {
3624ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    mContentRoot = new FrameLayout(context);
3634ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    layoutParams = new LinearLayout.LayoutParams(
3644ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                            LayoutParams.MATCH_PARENT, 0);
3654ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    layoutParams.weight = 1;
3664ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    mContentRoot.setLayoutParams(layoutParams);
3674ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    backgroundLayout.addView(mContentRoot);
3684ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                }
369bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
370891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                if (mNavigationBarOrientation == LinearLayout.HORIZONTAL &&
371891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                        mNavigationBarSize > 0) {
372bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    // system bar
373bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    try {
3744ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                        NavigationBar navigationBar = createNavigationBar(context,
3754ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                                hardwareConfig.getDensity(), isRtl, params.isRtlSupported());
376891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                        topLayout.addView(navigationBar);
377bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    } catch (XmlPullParserException e) {
378bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
379bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    }
380bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                }
381bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            }
382bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
383c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
384c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // Sets the project callback (custom view loader) to the fragment delegate so that
385c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // it can instantiate the custom Fragment.
386b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            Fragment_Delegate.setProjectCallback(params.getProjectCallback());
387c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
388bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            View view = mInflater.inflate(mBlockParser, mContentRoot);
389c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
3902fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            // done with the parser, pop it.
3912fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            context.popParser();
3922fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
393c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            Fragment_Delegate.setProjectCallback(null);
394c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
395c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // set the AttachInfo on the root view.
3967f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet            AttachInfo_Accessor.setAttachInfo(mViewRoot);
397c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
39833758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet            // post-inflate process. For now this supports TabHost/TabWidget
399b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            postInflateProcess(view, params.getProjectCallback());
40033758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet
401c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // get the background drawable
402abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet            if (mWindowBackground != null && backgroundView != null) {
403b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                Drawable d = ResourceHelper.getDrawable(mWindowBackground, context);
404891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                backgroundView.setBackground(d);
405c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
406c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
40719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult();
408c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        } catch (PostInflateException e) {
40919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return ERROR_INFLATION.createResult(e.getMessage(), e);
410c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        } catch (Throwable e) {
411c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // get the real cause of the exception.
412c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            Throwable t = e;
413c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            while (t.getCause() != null) {
414c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                t = t.getCause();
415c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
416c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
41719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return ERROR_INFLATION.createResult(t.getMessage(), t);
418c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
419c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
420c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
421c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
422c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * Renders the scene.
423c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * <p>
4242eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
4252eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *
4265a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet     * @param freshRender whether the render is a new one and should erase the existing bitmap (in
4275a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet     *      the case where bitmaps are reused). This is typically needed when not playing
4285a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet     *      animations.)
4295a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet     *
4302eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
4312eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
4329eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet     *
4331b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta     * @see SessionParams#getRenderingMode()
434bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * @see RenderSession#render(long)
435c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     */
4365a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet    public Result render(boolean freshRender) {
4372eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        checkLock();
4382eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
439b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        SessionParams params = getParams();
440b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
441c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        try {
442c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            if (mViewRoot == null) {
44319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet                return ERROR_NOT_INFLATED.createResult();
444c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
445c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
446b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            RenderingMode renderingMode = params.getRenderingMode();
447891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            HardwareConfig hardwareConfig = params.getHardwareConfig();
448fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet
4499eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet            // only do the screen measure when needed.
4509eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet            boolean newRenderSize = false;
4519eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet            if (mMeasuredScreenWidth == -1) {
4529eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                newRenderSize = true;
453891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                mMeasuredScreenWidth = hardwareConfig.getScreenWidth();
454891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                mMeasuredScreenHeight = hardwareConfig.getScreenHeight();
4559eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet
4569eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                if (renderingMode != RenderingMode.NORMAL) {
457c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    int widthMeasureSpecMode = renderingMode.isHorizExpand() ?
458c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
459c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            : MeasureSpec.EXACTLY;
460c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    int heightMeasureSpecMode = renderingMode.isVertExpand() ?
461c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
462c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            : MeasureSpec.EXACTLY;
463c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
464c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // We used to compare the measured size of the content to the screen size but
465c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // this does not work anymore due to the 2 following issues:
466c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // - If the content is in a decor (system bar, title/action bar), the root view
467c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    //   will not resize even with the UNSPECIFIED because of the embedded layout.
468c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // - If there is no decor, but a dialog frame, then the dialog padding prevents
469c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    //   comparing the size of the content to the screen frame (as it would not
470c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    //   take into account the dialog padding).
471c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
472c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // The solution is to first get the content size in a normal rendering, inside
473c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // the decor or the dialog padding.
474c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // Then measure only the content with UNSPECIFIED to see the size difference
475c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // and apply this to the screen size.
476c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
477c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // first measure the full layout, with EXACTLY to get the size of the
478c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // content as it is inside the decor/dialog
479c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    Pair<Integer, Integer> exactMeasure = measureView(
480c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mViewRoot, mContentRoot.getChildAt(0),
481c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mMeasuredScreenWidth, MeasureSpec.EXACTLY,
482c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mMeasuredScreenHeight, MeasureSpec.EXACTLY);
483c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
484c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // now measure the content only using UNSPECIFIED (where applicable, based on
485c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // the rendering mode). This will give us the size the content needs.
486c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    Pair<Integer, Integer> result = measureView(
487c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mContentRoot, mContentRoot.getChildAt(0),
488c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mMeasuredScreenWidth, widthMeasureSpecMode,
489c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mMeasuredScreenHeight, heightMeasureSpecMode);
490c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
491c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // now look at the difference and add what is needed.
4929eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                    if (renderingMode.isHorizExpand()) {
493c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                        int measuredWidth = exactMeasure.getFirst();
494c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                        int neededWidth = result.getFirst();
495c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                        if (neededWidth > measuredWidth) {
496c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mMeasuredScreenWidth += neededWidth - measuredWidth;
4979eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                        }
498fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet                    }
499c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
5009eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                    if (renderingMode.isVertExpand()) {
501c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                        int measuredHeight = exactMeasure.getSecond();
502c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                        int neededHeight = result.getSecond();
503c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                        if (neededHeight > measuredHeight) {
504c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mMeasuredScreenHeight += neededHeight - measuredHeight;
5059eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                        }
506fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet                    }
507c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                }
508c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
509c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
510c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet            // measure again with the size we need
511c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // This must always be done before the call to layout
512c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet            measureView(mViewRoot, null /*measuredView*/,
513c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    mMeasuredScreenWidth, MeasureSpec.EXACTLY,
514c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    mMeasuredScreenHeight, MeasureSpec.EXACTLY);
515c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
516c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // now do the layout.
51716584225125acba18b74920b902c798dfead0328Xavier Ducrohet            mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
518c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
51910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet            if (params.isLayoutOnly()) {
52010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                // delete the canvas and image to reset them on the next full rendering
52110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                mImage = null;
52210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                mCanvas = null;
52310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet            } else {
5247f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet                AttachInfo_Accessor.dispatchOnPreDraw(mViewRoot);
52510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet
52610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                // draw the views
52710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                // create the BufferedImage into which the layout will be rendered.
52810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                boolean newImage = false;
52910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                if (newRenderSize || mCanvas == null) {
53010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    if (params.getImageFactory() != null) {
53110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        mImage = params.getImageFactory().getImage(
53210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                                mMeasuredScreenWidth,
53310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                                mMeasuredScreenHeight);
53410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    } else {
53510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        mImage = new BufferedImage(
53610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                                mMeasuredScreenWidth,
53710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                                mMeasuredScreenHeight,
53810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                                BufferedImage.TYPE_INT_ARGB);
53910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        newImage = true;
54010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    }
54110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet
54210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    if (params.isBgColorOverridden()) {
54310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        // since we override the content, it's the same as if it was a new image.
54410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        newImage = true;
54510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        Graphics2D gc = mImage.createGraphics();
54610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        gc.setColor(new Color(params.getOverrideBgColor(), true));
54710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        gc.setComposite(AlphaComposite.Src);
54810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
54910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        gc.dispose();
55010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    }
55110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet
55210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    // create an Android bitmap around the BufferedImage
55310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
554891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                            true /*isMutable*/, hardwareConfig.getDensity());
55510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet
55610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    // create a Canvas around the Android bitmap
55710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    mCanvas = new Canvas(bitmap);
558891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue());
5599eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                }
560c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
56110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                if (freshRender && newImage == false) {
5629eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                    Graphics2D gc = mImage.createGraphics();
5635a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet                    gc.setComposite(AlphaComposite.Src);
564c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
56510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    gc.setColor(new Color(0x00000000, true));
56610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    gc.fillRect(0, 0,
56710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                            mMeasuredScreenWidth, mMeasuredScreenHeight);
56816584225125acba18b74920b902c798dfead0328Xavier Ducrohet
56910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    // done
57010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    gc.dispose();
57110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                }
57216584225125acba18b74920b902c798dfead0328Xavier Ducrohet
57310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                mViewRoot.draw(mCanvas);
5745a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet            }
5755a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet
5764ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(), false);
577c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
578c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // success!
57919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult();
580c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        } catch (Throwable e) {
581c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // get the real cause of the exception.
582c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            Throwable t = e;
583c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            while (t.getCause() != null) {
584c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                t = t.getCause();
585c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
586c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
58719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return ERROR_UNKNOWN.createResult(t.getMessage(), t);
588c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
589c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
590c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
591c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
592c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * Executes {@link View#measure(int, int)} on a given view with the given parameters (used
593c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * to create measure specs with {@link MeasureSpec#makeMeasureSpec(int, int)}.
594c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     *
595c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * if <var>measuredView</var> is non null, the method returns a {@link Pair} of (width, height)
596c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * for the view (using {@link View#getMeasuredWidth()} and {@link View#getMeasuredHeight()}).
597c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     *
598c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @param viewToMeasure the view on which to execute measure().
599c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @param measuredView if non null, the view to query for its measured width/height.
600c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @param width the width to use in the MeasureSpec.
601c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @param widthMode the MeasureSpec mode to use for the width.
602c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @param height the height to use in the MeasureSpec.
603c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @param heightMode the MeasureSpec mode to use for the height.
604c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @return the measured width/height if measuredView is non-null, null otherwise.
605c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     */
606c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet    private Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
607c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet            int width, int widthMode, int height, int heightMode) {
608c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet        int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode);
609c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet        int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode);
610c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet        viewToMeasure.measure(w_spec, h_spec);
611c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
612c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet        if (measuredView != null) {
613c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet            return Pair.of(measuredView.getMeasuredWidth(), measuredView.getMeasuredHeight());
614c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet        }
615c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
616c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet        return null;
617c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet    }
618c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
619c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet    /**
6202eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * Animate an object
6212eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * <p>
6222eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
6232eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *
6242eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
6252eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
626e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
627bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * @see RenderSession#animate(Object, String, boolean, IAnimationListener)
6282eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     */
62919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public Result animate(Object targetObject, String animationName,
6302eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            boolean isFrameworkAnimation, IAnimationListener listener) {
6312eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        checkLock();
6322eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
633b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        BridgeContext context = getContext();
634b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
6352eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        // find the animation file.
636ffb42f6c5043de226f02318a1311669d35a90711Xavier Ducrohet        ResourceValue animationResource = null;
6372eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        int animationId = 0;
6382eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        if (isFrameworkAnimation) {
639b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            animationResource = context.getRenderResources().getFrameworkResource(
64035ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet                    ResourceType.ANIMATOR, animationName);
6412eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            if (animationResource != null) {
642b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet                animationId = Bridge.getResourceId(ResourceType.ANIMATOR, animationName);
6432eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            }
6442eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        } else {
645b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            animationResource = context.getRenderResources().getProjectResource(
64635ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet                    ResourceType.ANIMATOR, animationName);
6472eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            if (animationResource != null) {
648b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                animationId = context.getProjectCallback().getResourceId(
64935ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet                        ResourceType.ANIMATOR, animationName);
6502eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            }
6512eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        }
6522eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
6532eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        if (animationResource != null) {
6542eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            try {
655b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                Animator anim = AnimatorInflater.loadAnimator(context, animationId);
6562eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet                if (anim != null) {
6572eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet                    anim.setTarget(targetObject);
6582eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
659e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    new PlayAnimationThread(anim, this, animationName, listener).start();
6602eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
66119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet                    return SUCCESS.createResult();
6622eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet                }
6632eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            } catch (Exception e) {
664c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet                // get the real cause of the exception.
665c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet                Throwable t = e;
666c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet                while (t.getCause() != null) {
667c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet                    t = t.getCause();
668c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet                }
669c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
67019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet                return ERROR_UNKNOWN.createResult(t.getMessage(), t);
6712eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            }
6722eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        }
6732eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
67419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet        return ERROR_ANIM_NOT_FOUND.createResult();
675c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet    }
676c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
677e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    /**
678e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * Insert a new child into an existing parent.
679e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * <p>
680e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
681e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
682e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
683e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
684e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
685bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener)
686e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     */
68719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml,
688e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            final int index, IAnimationListener listener) {
689c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        checkLock();
690c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
691b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        BridgeContext context = getContext();
692b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
693c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        // create a block parser for the XML
69402d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet        BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
69502d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet                childXml, context, false /* platformResourceFlag */);
696c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
697c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        // inflate the child without adding it to the root since we want to control where it'll
698c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        // get added. We do pass the parentView however to ensure that the layoutParams will
699c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        // be created correctly.
700e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/);
70102d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet        blockParser.ensurePopped();
702c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
703e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        invalidateRenderingSize();
704e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
705e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        if (listener != null) {
706e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            new AnimationThread(this, "insertChild", listener) {
707e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
708e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                @Override
70919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet                public Result preAnimation() {
710e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    parentView.setLayoutTransition(new LayoutTransition());
711e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    return addView(parentView, child, index);
712e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                }
713e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
714e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                @Override
715e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                public void postAnimation() {
716e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    parentView.setLayoutTransition(null);
717e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                }
718e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            }.start();
719e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
720e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            // always return success since the real status will come through the listener.
72119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult(child);
7229eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet        }
7239eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet
724e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        // add it to the parentView in the correct location
72519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet        Result result = addView(parentView, child, index);
726e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        if (result.isSuccess() == false) {
727e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            return result;
728e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
729c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
7305a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet        result = render(false /*freshRender*/);
731c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet        if (result.isSuccess()) {
732e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            result = result.getCopyWithData(child);
733c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet        }
734c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet
735c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet        return result;
736c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet    }
737c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
738e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    /**
739e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * Adds a given view to a given parent at a given index.
740e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
741e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @param parent the parent to receive the view
742e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @param view the view to add to the parent
743e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @param index the index where to do the add.
744e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
74519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     * @return a Result with {@link Status#SUCCESS} or
74619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
747e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *     adding views.
748e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     */
74919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    private Result addView(ViewGroup parent, View view, int index) {
750e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        try {
751e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            parent.addView(view, index);
75219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult();
753e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        } catch (UnsupportedOperationException e) {
754e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            // looks like this is a view class that doesn't support children manipulation!
75519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
756e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
757e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    }
758e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
759e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    /**
760e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * Moves a view to a new parent at a given location
761e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * <p>
762e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
763e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
764e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
765e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
766e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
767bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener)
768e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     */
7692b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet    public Result moveChild(final ViewGroup newParentView, final View childView, final int index,
770479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            Map<String, String> layoutParamsMap, final IAnimationListener listener) {
771c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        checkLock();
772c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
773e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        invalidateRenderingSize();
774e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
77501811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet        LayoutParams layoutParams = null;
776e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        if (layoutParamsMap != null) {
777e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            // need to create a new LayoutParams object for the new parent.
7782b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet            layoutParams = newParentView.generateLayoutParams(
779e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    new BridgeLayoutParamsMapAttributes(layoutParamsMap));
780e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
7819eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet
7822b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet        // get the current parent of the view that needs to be moved.
7832b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet        final ViewGroup previousParent = (ViewGroup) childView.getParent();
7842b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
785e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        if (listener != null) {
786e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            final LayoutParams params = layoutParams;
78701811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet
788479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            // there is no support for animating views across layouts, so in case the new and old
789479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            // parent views are different we fake the animation through a no animation thread.
790479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            if (previousParent != newParentView) {
791479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                new Thread("not animated moveChild") {
792479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    @Override
793479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    public void run() {
794479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        Result result = moveView(previousParent, newParentView, childView, index,
795479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                                params);
796479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        if (result.isSuccess() == false) {
797479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            listener.done(result);
798479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        }
799479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
800479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // ready to do the work, acquire the scene.
801479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        result = acquire(250);
802479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        if (result.isSuccess() == false) {
803479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            listener.done(result);
804479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            return;
805479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        }
806479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
807479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        try {
8085a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet                            result = render(false /*freshRender*/);
809479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            if (result.isSuccess()) {
810479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                                listener.onNewFrame(RenderSessionImpl.this.getSession());
811479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            }
812479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        } finally {
813479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            release();
814479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        }
815479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
816479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        listener.done(result);
8172b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                    }
818479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                }.start();
819479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            } else {
820479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                new AnimationThread(this, "moveChild", listener) {
8212b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
822479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    @Override
823479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    public Result preAnimation() {
824479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // set up the transition for the parent.
825479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        LayoutTransition transition = new LayoutTransition();
826479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        previousParent.setLayoutTransition(transition);
8277550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet
828479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // tweak the animation durations and start delays (to match the duration of
829479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // animation playing just before).
830479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // Note: Cannot user Animation.setDuration() directly. Have to set it
831479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // on the LayoutTransition.
832479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        transition.setDuration(LayoutTransition.DISAPPEARING, 100);
833479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // CHANGE_DISAPPEARING plays after DISAPPEARING
834479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100);
83501811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet
836479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100);
837479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
838479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100);
839479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // CHANGE_APPEARING plays after CHANGE_APPEARING
840479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        transition.setStartDelay(LayoutTransition.APPEARING, 100);
841479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
842479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        transition.setDuration(LayoutTransition.APPEARING, 100);
843479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
844479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        return moveView(previousParent, newParentView, childView, index, params);
845479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    }
846479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
847479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    @Override
848479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    public void postAnimation() {
849479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        previousParent.setLayoutTransition(null);
850479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        newParentView.setLayoutTransition(null);
851479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    }
852479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                }.start();
853479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            }
854e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
855e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            // always return success since the real status will come through the listener.
85619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult(layoutParams);
857c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        }
858c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
8592b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet        Result result = moveView(previousParent, newParentView, childView, index, layoutParams);
860e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        if (result.isSuccess() == false) {
861e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            return result;
862e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
863c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
8645a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet        result = render(false /*freshRender*/);
86501811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet        if (layoutParams != null && result.isSuccess()) {
866e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            result = result.getCopyWithData(layoutParams);
86701811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet        }
86801811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet
86901811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet        return result;
870c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet    }
871c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
872e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    /**
873e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * Moves a View from its current parent to a new given parent at a new given location, with
874e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * an optional new {@link LayoutParams} instance
875e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
8762b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet     * @param previousParent the previous parent, still owning the child at the time of the call.
8772b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet     * @param newParent the new parent
878479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet     * @param movedView the view to move
879e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @param index the new location in the new parent
880e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @param params an option (can be null) {@link LayoutParams} instance.
881e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
88219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     * @return a Result with {@link Status#SUCCESS} or
88319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
884e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *     adding views.
885e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     */
886479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet    private Result moveView(ViewGroup previousParent, final ViewGroup newParent,
887479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            final View movedView, final int index, final LayoutParams params) {
8889eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet        try {
8892b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet            // check if there is a transition on the previousParent.
890479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            LayoutTransition previousTransition = previousParent.getLayoutTransition();
891479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            if (previousTransition != null) {
8927550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // in this case there is an animation. This means we have to wait for the child's
8937550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // parent reference to be null'ed out so that we can add it to the new parent.
8947550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // It is technically removed right before the DISAPPEARING animation is done (if
8957550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // the animation of this type is not null, otherwise it's after which is impossible
8967550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // to handle).
8977550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // Because there is no move animation, if the new parent is the same as the old
8987550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before
8997550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // adding the child or the child will appear in its new location before the
9007550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // other children have made room for it.
9012b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
9022b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                // add a listener to the transition to be notified of the actual removal.
903479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                previousTransition.addTransitionListener(new TransitionListener() {
904479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    private int mChangeDisappearingCount = 0;
9052b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
90646d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet                    @Override
9072b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                    public void startTransition(LayoutTransition transition, ViewGroup container,
9082b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                            View view, int transitionType) {
909479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
910479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            mChangeDisappearingCount++;
911479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        }
9122b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                    }
913e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
91446d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet                    @Override
9152b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                    public void endTransition(LayoutTransition transition, ViewGroup container,
9162b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                            View view, int transitionType) {
917479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
918479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            mChangeDisappearingCount--;
919479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        }
920479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
921479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING &&
922479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                                mChangeDisappearingCount == 0) {
9232b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                            // add it to the parentView in the correct location
9242b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                            if (params != null) {
925479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                                newParent.addView(movedView, index, params);
9262b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                            } else {
927479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                                newParent.addView(movedView, index);
9282b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                            }
9292b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                        }
9302b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                    }
9312b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                });
9322b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
9332b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                // remove the view from the current parent.
934479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                previousParent.removeView(movedView);
9352b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
9362b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                // and return since adding the view to the new parent is done in the listener.
9372b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                return SUCCESS.createResult();
938e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            } else {
9392b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                // standard code with no animation. pretty simple.
940479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                previousParent.removeView(movedView);
941e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
9422b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                // add it to the parentView in the correct location
9432b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                if (params != null) {
944479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    newParent.addView(movedView, index, params);
9452b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                } else {
946479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    newParent.addView(movedView, index);
9472b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                }
9482b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
9492b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                return SUCCESS.createResult();
9502b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet            }
9519eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet        } catch (UnsupportedOperationException e) {
9529eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet            // looks like this is a view class that doesn't support children manipulation!
95319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
954c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        }
955e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    }
956e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
957e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    /**
958e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * Removes a child from its current parent.
959e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * <p>
960e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
961e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
962e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
963e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
964e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
965bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * @see RenderSession#removeChild(Object, IAnimationListener)
966e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     */
96719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public Result removeChild(final View childView, IAnimationListener listener) {
968e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        checkLock();
969c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
9709eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet        invalidateRenderingSize();
9719eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet
972e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        final ViewGroup parent = (ViewGroup) childView.getParent();
973e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
974e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        if (listener != null) {
975e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            new AnimationThread(this, "moveChild", listener) {
976e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
977e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                @Override
97819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet                public Result preAnimation() {
979e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    parent.setLayoutTransition(new LayoutTransition());
980e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    return removeView(parent, childView);
981e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                }
982e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
983e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                @Override
984e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                public void postAnimation() {
985e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    parent.setLayoutTransition(null);
986e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                }
987e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            }.start();
988e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
989e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            // always return success since the real status will come through the listener.
99019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult();
991e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
992e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
99319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet        Result result = removeView(parent, childView);
994e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        if (result.isSuccess() == false) {
995e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            return result;
996e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
997e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
9985a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet        return render(false /*freshRender*/);
9992eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    }
10002eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
10012eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    /**
1002e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * Removes a given view from its current parent.
1003e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
1004e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @param view the view to remove from its parent
1005e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
100619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     * @return a Result with {@link Status#SUCCESS} or
100719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
1008e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *     adding views.
1009e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     */
101019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    private Result removeView(ViewGroup parent, View view) {
1011e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        try {
1012e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            parent.removeView(view);
101319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult();
1014e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        } catch (UnsupportedOperationException e) {
1015e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            // looks like this is a view class that doesn't support children manipulation!
101619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
1017e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
1018e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    }
1019e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
10202eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
102116584225125acba18b74920b902c798dfead0328Xavier Ducrohet    private void findBackground(RenderResources resources) {
1022b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        if (getParams().isBgColorOverridden() == false) {
102301b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet            mWindowBackground = resources.findItemInTheme("windowBackground",
102401b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet                    true /*isFrameworkAttr*/);
102516584225125acba18b74920b902c798dfead0328Xavier Ducrohet            if (mWindowBackground != null) {
102616584225125acba18b74920b902c798dfead0328Xavier Ducrohet                mWindowBackground = resources.resolveResValue(mWindowBackground);
102716584225125acba18b74920b902c798dfead0328Xavier Ducrohet            }
102816584225125acba18b74920b902c798dfead0328Xavier Ducrohet        }
102916584225125acba18b74920b902c798dfead0328Xavier Ducrohet    }
1030c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1031891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet    private boolean hasSoftwareButtons() {
1032891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet        return getParams().getHardwareConfig().hasSoftwareButtons();
103316584225125acba18b74920b902c798dfead0328Xavier Ducrohet    }
1034c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
103516584225125acba18b74920b902c798dfead0328Xavier Ducrohet    private void findStatusBar(RenderResources resources, DisplayMetrics metrics) {
1036891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet        boolean windowFullscreen = getBooleanThemeValue(resources,
1037891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                "windowFullscreen", false /*defaultValue*/);
103816584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1039891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet        if (windowFullscreen == false && mWindowIsFloating == false) {
1040891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            // default value
1041891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT;
104216584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1043891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            // get the real value
1044891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
1045891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    "status_bar_height");
104616584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1047891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            if (value != null) {
1048891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                TypedValue typedValue = ResourceHelper.getValue("status_bar_height",
1049891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                        value.getValue(), true /*requireUnit*/);
1050891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                if (typedValue != null) {
1051891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    // compute the pixel value based on the display metrics
1052891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    mStatusBarSize = (int)typedValue.getDimension(metrics);
105316584225125acba18b74920b902c798dfead0328Xavier Ducrohet                }
105416584225125acba18b74920b902c798dfead0328Xavier Ducrohet            }
105516584225125acba18b74920b902c798dfead0328Xavier Ducrohet        }
105616584225125acba18b74920b902c798dfead0328Xavier Ducrohet    }
105716584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1058bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private void findActionBar(RenderResources resources, DisplayMetrics metrics) {
1059bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        if (mWindowIsFloating) {
1060bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            return;
106116584225125acba18b74920b902c798dfead0328Xavier Ducrohet        }
106216584225125acba18b74920b902c798dfead0328Xavier Ducrohet
106316584225125acba18b74920b902c798dfead0328Xavier Ducrohet        boolean windowActionBar = getBooleanThemeValue(resources,
106416584225125acba18b74920b902c798dfead0328Xavier Ducrohet                "windowActionBar", true /*defaultValue*/);
106516584225125acba18b74920b902c798dfead0328Xavier Ducrohet
106616584225125acba18b74920b902c798dfead0328Xavier Ducrohet        // if there's a value and it's false (default is true)
106716584225125acba18b74920b902c798dfead0328Xavier Ducrohet        if (windowActionBar) {
1068c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1069c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // default size of the window title bar
1070bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            mActionBarSize = DEFAULT_TITLE_BAR_HEIGHT;
1071c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1072c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // get value from the theme.
107301b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet            ResourceValue value = resources.findItemInTheme("actionBarSize",
107401b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet                    true /*isFrameworkAttr*/);
1075c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1076c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // resolve it
107716584225125acba18b74920b902c798dfead0328Xavier Ducrohet            value = resources.resolveResValue(value);
1078c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1079c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            if (value != null) {
1080c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                // get the numerical value, if available
108104ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet                TypedValue typedValue = ResourceHelper.getValue("actionBarSize", value.getValue(),
108204ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet                        true /*requireUnit*/);
1083c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                if (typedValue != null) {
1084c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    // compute the pixel value based on the display metrics
1085bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    mActionBarSize = (int)typedValue.getDimension(metrics);
1086c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                }
1087c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
1088bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        } else {
1089bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            // action bar overrides title bar so only look for this one if action bar is hidden
1090bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            boolean windowNoTitle = getBooleanThemeValue(resources,
1091bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    "windowNoTitle", false /*defaultValue*/);
1092c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1093bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            if (windowNoTitle == false) {
109416584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1095bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                // default size of the window title bar
1096bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                mTitleBarSize = DEFAULT_TITLE_BAR_HEIGHT;
109716584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1098bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                // get value from the theme.
109901b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet                ResourceValue value = resources.findItemInTheme("windowTitleSize",
110001b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet                        true /*isFrameworkAttr*/);
110116584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1102bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                // resolve it
1103bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                value = resources.resolveResValue(value);
1104c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1105bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                if (value != null) {
1106bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    // get the numerical value, if available
110704ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet                    TypedValue typedValue = ResourceHelper.getValue("windowTitleSize",
110804ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet                            value.getValue(), true /*requireUnit*/);
1109bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    if (typedValue != null) {
1110bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                        // compute the pixel value based on the display metrics
1111bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                        mTitleBarSize = (int)typedValue.getDimension(metrics);
1112bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    }
111316584225125acba18b74920b902c798dfead0328Xavier Ducrohet                }
111416584225125acba18b74920b902c798dfead0328Xavier Ducrohet            }
1115bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
111616584225125acba18b74920b902c798dfead0328Xavier Ducrohet        }
111716584225125acba18b74920b902c798dfead0328Xavier Ducrohet    }
111816584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1119891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet    private void findNavigationBar(RenderResources resources, DisplayMetrics metrics) {
1120891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet        if (hasSoftwareButtons() && mWindowIsFloating == false) {
1121c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1122c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // default value
1123891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            mNavigationBarSize = 48; // ??
1124891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
1125891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            HardwareConfig hardwareConfig = getParams().getHardwareConfig();
1126891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
1127891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            boolean barOnBottom = true;
1128891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
1129891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            if (hardwareConfig.getOrientation() == ScreenOrientation.LANDSCAPE) {
1130891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                // compute the dp of the screen.
1131891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                int shortSize = hardwareConfig.getScreenHeight();
1132891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
1133891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                // compute in dp
1134891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / hardwareConfig.getDensity().getDpiValue();
1135891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
1136891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                if (shortSizeDp < 600) {
1137891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    // 0-599dp: "phone" UI with bar on the side
1138891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    barOnBottom = false;
1139891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                } else {
1140891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    // 600+dp: "tablet" UI with bar on the bottom
1141891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    barOnBottom = true;
1142891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                }
1143891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            }
1144891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
1145891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            if (barOnBottom) {
1146891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                mNavigationBarOrientation = LinearLayout.HORIZONTAL;
1147891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            } else {
1148891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                mNavigationBarOrientation = LinearLayout.VERTICAL;
1149891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            }
1150c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1151d1d6fafc7fc63543b10552dadf202dd6fa40fe6bXavier Ducrohet            // get the real value
115235ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet            ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
1153891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    barOnBottom ? "navigation_bar_height" : "navigation_bar_width");
115416584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1155c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            if (value != null) {
1156891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                TypedValue typedValue = ResourceHelper.getValue("navigation_bar_height",
115704ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet                        value.getValue(), true /*requireUnit*/);
1158c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                if (typedValue != null) {
1159c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    // compute the pixel value based on the display metrics
1160891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    mNavigationBarSize = (int)typedValue.getDimension(metrics);
1161c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                }
1162c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
116316584225125acba18b74920b902c798dfead0328Xavier Ducrohet        }
116416584225125acba18b74920b902c798dfead0328Xavier Ducrohet    }
116516584225125acba18b74920b902c798dfead0328Xavier Ducrohet
116601b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet    /**
116701b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     * Looks for a attribute in the current theme. The attribute is in the android
116801b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     * namespace.
116901b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     *
117001b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     * @param resources the render resources
117101b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     * @param name the name of the attribute
117201b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     * @param defaultValue the default value.
117301b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     * @return the value of the attribute or the default one if not found.
117401b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     */
117516584225125acba18b74920b902c798dfead0328Xavier Ducrohet    private boolean getBooleanThemeValue(RenderResources resources,
117616584225125acba18b74920b902c798dfead0328Xavier Ducrohet            String name, boolean defaultValue) {
117716584225125acba18b74920b902c798dfead0328Xavier Ducrohet
117816584225125acba18b74920b902c798dfead0328Xavier Ducrohet        // get the title bar flag from the current theme.
117901b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet        ResourceValue value = resources.findItemInTheme(name, true /*isFrameworkAttr*/);
118016584225125acba18b74920b902c798dfead0328Xavier Ducrohet
118116584225125acba18b74920b902c798dfead0328Xavier Ducrohet        // because it may reference something else, we resolve it.
118216584225125acba18b74920b902c798dfead0328Xavier Ducrohet        value = resources.resolveResValue(value);
1183c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
118416584225125acba18b74920b902c798dfead0328Xavier Ducrohet        // if there's no value, return the default.
118516584225125acba18b74920b902c798dfead0328Xavier Ducrohet        if (value == null || value.getValue() == null) {
118616584225125acba18b74920b902c798dfead0328Xavier Ducrohet            return defaultValue;
1187c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1188c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
118916584225125acba18b74920b902c798dfead0328Xavier Ducrohet        return XmlUtils.convertValueToBoolean(value.getValue(), defaultValue);
1190c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
1191c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1192c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
1193c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * Post process on a view hierachy that was just inflated.
1194c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * <p/>At the moment this only support TabHost: If {@link TabHost} is detected, look for the
1195c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically
1196c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * based on the content of the {@link FrameLayout}.
1197c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * @param view the root view to process.
1198c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * @param projectCallback callback to the project.
1199c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     */
1200c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private void postInflateProcess(View view, IProjectCallback projectCallback)
1201c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            throws PostInflateException {
1202c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        if (view instanceof TabHost) {
1203c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            setupTabHost((TabHost)view, projectCallback);
120431fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet        } else if (view instanceof QuickContactBadge) {
120531fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet            QuickContactBadge badge = (QuickContactBadge) view;
120631fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet            badge.setImageToDefault();
12072fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet        } else if (view instanceof AdapterView<?>) {
12082fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            // get the view ID.
12092fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            int id = view.getId();
12102fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12112fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            BridgeContext context = getContext();
12122fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12132fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            // get a ResourceReference from the integer ID.
12142fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            ResourceReference listRef = context.resolveId(id);
12152fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12162fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            if (listRef != null) {
12172fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                SessionParams params = getParams();
12182fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                AdapterBinding binding = params.getAdapterBindings().get(listRef);
12192fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12202fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                // if there was no adapter binding, trying to get it from the call back.
12212fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                if (binding == null) {
12222fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    binding = params.getProjectCallback().getAdapterBinding(listRef,
12232fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            context.getViewKey(view), view);
12242fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                }
12252fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12262fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                if (binding != null) {
12272fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12282fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    if (view instanceof AbsListView) {
12292fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        if ((binding.getFooterCount() > 0 || binding.getHeaderCount() > 0) &&
12302fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                view instanceof ListView) {
12312fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            ListView list = (ListView) view;
12322fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12332fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            boolean skipCallbackParser = false;
12342fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12352fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            int count = binding.getHeaderCount();
12362fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            for (int i = 0 ; i < count ; i++) {
12372fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                Pair<View, Boolean> pair = context.inflateView(
12382fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        binding.getHeaderAt(i),
12392fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        list, false /*attachToRoot*/, skipCallbackParser);
12402fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                if (pair.getFirst() != null) {
12412fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                    list.addHeaderView(pair.getFirst());
12422fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                }
12432fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12442fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                skipCallbackParser |= pair.getSecond();
12452fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            }
12462fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12472fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            count = binding.getFooterCount();
12482fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            for (int i = 0 ; i < count ; i++) {
12492fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                Pair<View, Boolean> pair = context.inflateView(
12502fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        binding.getFooterAt(i),
12512fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        list, false /*attachToRoot*/, skipCallbackParser);
12522fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                if (pair.getFirst() != null) {
12532fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                    list.addFooterView(pair.getFirst());
12542fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                }
12552fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12562fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                skipCallbackParser |= pair.getSecond();
12572fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            }
12582fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        }
12592fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12602fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        if (view instanceof ExpandableListView) {
12612fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            ((ExpandableListView) view).setAdapter(
12622fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                    new FakeExpandableAdapter(
12632fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                            listRef, binding, params.getProjectCallback()));
12642fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        } else {
12652fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            ((AbsListView) view).setAdapter(
12662fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                    new FakeAdapter(
12672fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                            listRef, binding, params.getProjectCallback()));
12682fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        }
12692fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    } else if (view instanceof AbsSpinner) {
12702fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        ((AbsSpinner) view).setAdapter(
12712fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                new FakeAdapter(
12722fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        listRef, binding, params.getProjectCallback()));
12732fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    }
12742fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                }
12752fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            }
1276c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        } else if (view instanceof ViewGroup) {
1277c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            ViewGroup group = (ViewGroup)view;
1278c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            final int count = group.getChildCount();
1279c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            for (int c = 0 ; c < count ; c++) {
1280c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                View child = group.getChildAt(c);
1281c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                postInflateProcess(child, projectCallback);
1282c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
1283c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1284c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
1285c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1286c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
1287c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * Sets up a {@link TabHost} object.
1288c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * @param tabHost the TabHost to setup.
1289c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * @param projectCallback The project callback object to access the project R class.
1290c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * @throws PostInflateException
1291c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     */
1292c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private void setupTabHost(TabHost tabHost, IProjectCallback projectCallback)
1293c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            throws PostInflateException {
1294c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        // look for the TabWidget, and the FrameLayout. They have their own specific names
1295c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        View v = tabHost.findViewById(android.R.id.tabs);
1296c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1297c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        if (v == null) {
1298c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            throw new PostInflateException(
1299c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    "TabHost requires a TabWidget with id \"android:id/tabs\".\n");
1300c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1301c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1302c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        if ((v instanceof TabWidget) == false) {
1303c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            throw new PostInflateException(String.format(
1304c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    "TabHost requires a TabWidget with id \"android:id/tabs\".\n" +
1305c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName()));
1306c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1307c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1308c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        v = tabHost.findViewById(android.R.id.tabcontent);
1309c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1310c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        if (v == null) {
1311c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // TODO: see if we can fake tabs even without the FrameLayout (same below when the framelayout is empty)
1312c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            throw new PostInflateException(
1313c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    "TabHost requires a FrameLayout with id \"android:id/tabcontent\".");
1314c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1315c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1316c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        if ((v instanceof FrameLayout) == false) {
1317c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            throw new PostInflateException(String.format(
1318c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" +
1319c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName()));
1320c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1321c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1322c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        FrameLayout content = (FrameLayout)v;
1323c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1324c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        // now process the content of the framelayout and dynamically create tabs for it.
1325c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        final int count = content.getChildCount();
1326c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1327c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        // this must be called before addTab() so that the TabHost searches its TabWidget
1328c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        // and FrameLayout.
1329c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        tabHost.setup();
1330c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1331796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye        if (count == 0) {
1332796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye            // Create a dummy child to get a single tab
1333796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye            TabSpec spec = tabHost.newTabSpec("tag").setIndicator("Tab Label",
1334796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                    tabHost.getResources().getDrawable(android.R.drawable.ic_menu_info_details))
1335796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                    .setContent(new TabHost.TabContentFactory() {
133646d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet                        @Override
1337796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                        public View createTabContent(String tag) {
1338b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                            return new LinearLayout(getContext());
1339796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                        }
1340796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                    });
1341796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye            tabHost.addTab(spec);
1342796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye            return;
1343796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye        } else {
1344796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye            // for each child of the framelayout, add a new TabSpec
1345796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye            for (int i = 0 ; i < count ; i++) {
1346796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                View child = content.getChildAt(i);
1347796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                String tabSpec = String.format("tab_spec%d", i+1);
1348796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                int id = child.getId();
1349b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet                Pair<ResourceType, String> resource = projectCallback.resolveResourceId(id);
1350796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                String name;
1351796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                if (resource != null) {
1352b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet                    name = resource.getSecond();
1353796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                } else {
1354796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                    name = String.format("Tab %d", i+1); // default name if id is unresolved.
1355796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                }
1356796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id));
1357c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
1358c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1359c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
1360c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
13614ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    /**
13624ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * Visits a {@link View} and its children and generate a {@link ViewInfo} containing the
13634ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * bounds of all the views.
13644ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     *
13654ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param view the root View
13664ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param offset an offset for the view bounds.
13674ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
13684ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
13694ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     *                       content frame.
13704ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     *
13714ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @return {@code ViewInfo} containing the bounds of the view and it children otherwise.
13724ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     */
13734ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    private ViewInfo visit(View view, int offset, boolean setExtendedInfo,
13744ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            boolean isContentFrame) {
13754ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        ViewInfo result = createViewInfo(view, offset, setExtendedInfo, isContentFrame);
1376bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
13774ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        if (view instanceof ViewGroup) {
13784ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            ViewGroup group = ((ViewGroup) view);
13794ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            result.setChildren(visitAllChildren(group, isContentFrame ? 0 : offset,
13804ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    setExtendedInfo, isContentFrame));
13814ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        }
13824ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        return result;
13834ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    }
1384bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
13854ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    /**
13864ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * Visits all the children of a given ViewGroup and generates a list of {@link ViewInfo}
13871b87390c9426c4bc9119829e9375d712dfde11c3Deepanshu Gupta     * containing the bounds of all the views. It also initializes the {@link #mViewInfoList} with
13884ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * the children of the {@code mContentRoot}.
13894ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     *
13904ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param viewGroup the root View
13914ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param offset an offset from the top for the content view frame.
13924ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
13934ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
13944ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     *                       content frame. {@code false} if the {@code ViewInfo} to be created is
13954ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     *                       part of the system decor.
13964ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     */
13974ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset,
13984ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            boolean setExtendedInfo, boolean isContentFrame) {
13994ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        if (viewGroup == null) {
14004ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            return null;
1401bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        }
1402bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
14034ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        if (!isContentFrame) {
14044ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            offset += viewGroup.getTop();
14054ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        }
1406bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
14074ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        int childCount = viewGroup.getChildCount();
14084ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        if (viewGroup == mContentRoot) {
14094ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            List<ViewInfo> childrenWithoutOffset = new ArrayList<ViewInfo>(childCount);
14104ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            List<ViewInfo> childrenWithOffset = new ArrayList<ViewInfo>(childCount);
14114ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            for (int i = 0; i < childCount; i++) {
14124ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                ViewInfo[] childViewInfo = visitContentRoot(viewGroup.getChildAt(i), offset,
141305b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet                        setExtendedInfo);
14144ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                childrenWithoutOffset.add(childViewInfo[0]);
14154ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                childrenWithOffset.add(childViewInfo[1]);
1416bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            }
14174ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            mViewInfoList = childrenWithOffset;
14184ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            return childrenWithoutOffset;
14194ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        } else {
14204ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            List<ViewInfo> children = new ArrayList<ViewInfo>(childCount);
14214ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            for (int i = 0; i < childCount; i++) {
14224ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo,
14234ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                        isContentFrame));
14244ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            }
14254ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            return children;
1426bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        }
14274ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    }
1428bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
14294ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    /**
14304ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * Visits the children of {@link #mContentRoot} and generates {@link ViewInfo} containing the
14314ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * bounds of all the views. It returns two {@code ViewInfo} objects with the same children,
14324ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * one with the {@code offset} and other without the {@code offset}. The offset is needed to
14334ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * get the right bounds if the {@code ViewInfo} hierarchy is accessed from
14344ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * {@code mViewInfoList}. When the hierarchy is accessed via {@code mSystemViewInfoList}, the
14354ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * offset is not needed.
14364ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     *
14374ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @return an array of length two, with ViewInfo at index 0 is without offset and ViewInfo at
14384ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     *         index 1 is with the offset.
14394ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     */
14404ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    private ViewInfo[] visitContentRoot(View view, int offset, boolean setExtendedInfo) {
14414ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        ViewInfo[] result = new ViewInfo[2];
14424ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        if (view == null) {
14434ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            return result;
14444ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        }
14454ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta
14464ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        result[0] = createViewInfo(view, 0, setExtendedInfo, true);
14474ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        result[1] = createViewInfo(view, offset, setExtendedInfo, true);
14484ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        if (view instanceof ViewGroup) {
14494ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            List<ViewInfo> children = visitAllChildren((ViewGroup) view, 0, setExtendedInfo, true);
14504ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            result[0].setChildren(children);
14514ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            result[1].setChildren(children);
14524ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        }
14534ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        return result;
1454bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    }
1455c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1456c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
14574ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * Creates a {@link ViewInfo} for the view. The {@code ViewInfo} corresponding to the children
14584ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * of the {@code view} are not created. Consequently, the children of {@code ViewInfo} is not
14594ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * set.
14604ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param offset an offset for the view bounds. Used only if view is part of the content frame.
1461c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     */
14624ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    private ViewInfo createViewInfo(View view, int offset, boolean setExtendedInfo,
14634ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            boolean isContentFrame) {
1464c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        if (view == null) {
1465c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            return null;
1466c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1467c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
14684ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        ViewInfo result;
14694ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        if (isContentFrame) {
14704ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            result = new ViewInfo(view.getClass().getName(),
14714ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    getContext().getViewKey(view),
14724ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    view.getLeft(), view.getTop() + offset, view.getRight(),
14734ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    view.getBottom() + offset, view, view.getLayoutParams());
14744ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta
14754ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        } else {
14764ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            result = new SystemViewInfo(view.getClass().getName(),
14774ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    getContext().getViewKey(view),
14784ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    view.getLeft(), view.getTop(), view.getRight(),
14794ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    view.getBottom(), view, view.getLayoutParams());
14804ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        }
1481c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
148205b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet        if (setExtendedInfo) {
148305b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet            MarginLayoutParams marginParams = null;
148405b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet            LayoutParams params = view.getLayoutParams();
148505b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet            if (params instanceof MarginLayoutParams) {
148605b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet                marginParams = (MarginLayoutParams) params;
148705b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet            }
148805b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet            result.setExtendedInfo(view.getBaseline(),
148905b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet                    marginParams != null ? marginParams.leftMargin : 0,
149005b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet                    marginParams != null ? marginParams.topMargin : 0,
149105b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet                    marginParams != null ? marginParams.rightMargin : 0,
149205b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet                    marginParams != null ? marginParams.bottomMargin : 0);
149305b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet        }
149405b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet
1495c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        return result;
1496c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
1497c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
14984ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    private void invalidateRenderingSize() {
14994ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        mMeasuredScreenWidth = mMeasuredScreenHeight = -1;
15004ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    }
15014ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta
1502bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    /**
15034ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * Creates the status bar with wifi and battery icons.
1504bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     */
15054ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    private StatusBar createStatusBar(BridgeContext context, Density density, int direction,
15064ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            boolean isRtlSupported) throws XmlPullParserException {
15074ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        StatusBar statusBar = new StatusBar(context, density,
15084ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                direction, isRtlSupported);
15094ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        statusBar.setLayoutParams(
15104ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                new LinearLayout.LayoutParams(
15114ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                        LayoutParams.MATCH_PARENT, mStatusBarSize));
15124ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        return statusBar;
15134ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    }
15147d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet
15154ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    /**
15164ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * Creates the navigation bar with back, home and recent buttons.
15174ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     *
15184ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param isRtl true if the current locale is right-to-left
15194ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * @param isRtlSupported true is the project manifest declares that the application
15204ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     *        is RTL aware.
15214ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     */
15224ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    private NavigationBar createNavigationBar(BridgeContext context, Density density,
15234ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            boolean isRtl, boolean isRtlSupported) throws XmlPullParserException {
15244ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        NavigationBar navigationBar = new NavigationBar(context,
15254ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                density, mNavigationBarOrientation, isRtl,
15264ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                isRtlSupported);
15274ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        if (mNavigationBarOrientation == LinearLayout.VERTICAL) {
15284ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            navigationBar.setLayoutParams(new LinearLayout.LayoutParams(mNavigationBarSize,
15294ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    LayoutParams.MATCH_PARENT));
15304ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        } else {
15314ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            navigationBar.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
15324ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                    mNavigationBarSize));
15337d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet        }
15344ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        return navigationBar;
15357d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet    }
15367d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet
15374ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    private TitleBar createTitleBar(BridgeContext context, Density density, String title)
15384ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            throws XmlPullParserException {
15394ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        TitleBar titleBar = new TitleBar(context, density, title);
15404ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        titleBar.setLayoutParams(
15414ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, mTitleBarSize));
15424ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        return titleBar;
15434ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    }
15447d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet
15454ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    /**
15464ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     * Creates the action bar. Also queries the project callback for missing information.
15474ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta     */
15484ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    private ActionBarLayout createActionBar(BridgeContext context, SessionParams params)
15494ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta            throws XmlPullParserException {
15504ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        ActionBarLayout actionBar = new ActionBarLayout(context, params);
15514ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        actionBar.setLayoutParams(new LinearLayout.LayoutParams(
15524ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
15534ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        return actionBar;
15549eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet    }
15559eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet
1556c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    public BufferedImage getImage() {
1557c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        return mImage;
1558c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
1559c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
156016584225125acba18b74920b902c798dfead0328Xavier Ducrohet    public boolean isAlphaChannelImage() {
156116584225125acba18b74920b902c798dfead0328Xavier Ducrohet        return mIsAlphaChannelImage;
156216584225125acba18b74920b902c798dfead0328Xavier Ducrohet    }
156316584225125acba18b74920b902c798dfead0328Xavier Ducrohet
15647d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet    public List<ViewInfo> getViewInfos() {
15657d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet        return mViewInfoList;
1566c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
1567cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet
15684ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    public List<ViewInfo> getSystemViewInfos() {
15694ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta        return mSystemViewInfoList;
15704ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta    }
15714ccc4bd54f85d86818f61d728c6361d2003ddd8eDeepanshu Gupta
157219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public Map<String, String> getDefaultProperties(Object viewObject) {
1573b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        return getContext().getDefaultPropMap(viewObject);
1574cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet    }
1575c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
157619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public void setScene(RenderSession session) {
157719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet        mScene = session;
1578c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet    }
1579c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
158019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public RenderSession getSession() {
1581c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        return mScene;
1582c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet    }
1583c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet}
1584