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;
46bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohetimport com.android.layoutlib.bridge.bars.FakeActionBar;
47891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport com.android.layoutlib.bridge.bars.NavigationBar;
48891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport com.android.layoutlib.bridge.bars.StatusBar;
49bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohetimport com.android.layoutlib.bridge.bars.TitleBar;
502fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeAdapter;
512fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter;
5235ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohetimport com.android.resources.ResourceType;
53891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport com.android.resources.ScreenOrientation;
54b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohetimport com.android.util.Pair;
55c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
56bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohetimport org.xmlpull.v1.XmlPullParserException;
57bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
587f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.animation.AnimationThread;
59e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohetimport android.animation.Animator;
602eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohetimport android.animation.AnimatorInflater;
61e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohetimport android.animation.LayoutTransition;
622b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohetimport android.animation.LayoutTransition.TransitionListener;
63c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.app.Fragment_Delegate;
64c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Bitmap;
65c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Bitmap_Delegate;
66c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.Canvas;
67c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.graphics.drawable.Drawable;
68c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.util.DisplayMetrics;
69c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.util.TypedValue;
707f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.view.AttachInfo_Accessor;
717f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohetimport android.view.BridgeInflater;
726dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.IWindowManager;
73891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohetimport android.view.IWindowManagerImpl;
746dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.Surface;
75c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.View;
76c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.view.View.MeasureSpec;
7746d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport android.view.ViewGroup;
7801811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohetimport android.view.ViewGroup.LayoutParams;
7905b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohetimport android.view.ViewGroup.MarginLayoutParams;
806dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohetimport android.view.WindowManagerGlobal_Delegate;
812fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AbsListView;
822fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AbsSpinner;
832fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.AdapterView;
842fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.ExpandableListView;
85c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.widget.FrameLayout;
86796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbyeimport android.widget.LinearLayout;
872fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohetimport android.widget.ListView;
8831fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohetimport android.widget.QuickContactBadge;
89c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport android.widget.TabHost;
90796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbyeimport android.widget.TabHost.TabSpec;
9146d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohetimport android.widget.TabWidget;
92c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
935a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohetimport java.awt.AlphaComposite;
94c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.Color;
95c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.Graphics2D;
96c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.awt.image.BufferedImage;
97c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.ArrayList;
98c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.List;
99c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport java.util.Map;
100c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
101c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet/**
10219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * Class implementing the render session.
103c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet *
10419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * A session is a stateful representation of a layout file. It is initialized with data coming
10519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then
106c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet * be done on the layout.
107c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet *
108c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet */
109b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohetpublic class RenderSessionImpl extends RenderAction<SessionParams> {
110c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
111c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private static final int DEFAULT_TITLE_BAR_HEIGHT = 25;
112c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private static final int DEFAULT_STATUS_BAR_HEIGHT = 25;
113c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
114c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    // scene state
11519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    private RenderSession mScene;
116c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private BridgeXmlBlockParser mBlockParser;
117c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private BridgeInflater mInflater;
118ffb42f6c5043de226f02318a1311669d35a90711Xavier Ducrohet    private ResourceValue mWindowBackground;
119bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private ViewGroup mViewRoot;
120bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private FrameLayout mContentRoot;
1219eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet    private Canvas mCanvas;
1229eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet    private int mMeasuredScreenWidth = -1;
1239eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet    private int mMeasuredScreenHeight = -1;
124bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private boolean mIsAlphaChannelImage;
125bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private boolean mWindowIsFloating;
12616584225125acba18b74920b902c798dfead0328Xavier Ducrohet
12716584225125acba18b74920b902c798dfead0328Xavier Ducrohet    private int mStatusBarSize;
128891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet    private int mNavigationBarSize;
129891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet    private int mNavigationBarOrientation = LinearLayout.HORIZONTAL;
130bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private int mTitleBarSize;
131bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private int mActionBarSize;
13216584225125acba18b74920b902c798dfead0328Xavier Ducrohet
133c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
134c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    // information being returned through the API
135c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private BufferedImage mImage;
1367d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet    private List<ViewInfo> mViewInfoList;
137c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
138c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private static final class PostInflateException extends Exception {
139c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        private static final long serialVersionUID = 1L;
140c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
141c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        public PostInflateException(String message) {
142c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            super(message);
143c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
144c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
145c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
146c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
147c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * Creates a layout scene with all the information coming from the layout bridge API.
148c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * <p>
14919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init()}, which act as a
15019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     * call to {@link RenderSessionImpl#acquire(long)}
151c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     *
152c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * @see LayoutBridge#createScene(com.android.layoutlib.api.SceneParams)
153c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     */
1541126422ee1f532d8582a4e3b56dbfe505c15e775Xavier Ducrohet    public RenderSessionImpl(SessionParams params) {
155b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        super(new SessionParams(params));
1562eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    }
1572eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
1582eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    /**
1592eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * Initializes and acquires the scene, creating various Android objects such as context,
1602eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * inflater, and parser.
1612eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *
1622eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @param timeout the time to wait if another rendering is happening.
1632eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *
1642eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @return whether the scene was prepared
1652eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *
1662eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @see #acquire(long)
1672eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @see #release()
1682eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     */
169b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet    @Override
17019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public Result init(long timeout) {
171b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        Result result = super.init(timeout);
172b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        if (result.isSuccess() == false) {
1732eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            return result;
1742eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        }
175c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
176b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        SessionParams params = getParams();
177b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        BridgeContext context = getContext();
178c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
179b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        RenderResources resources = getParams().getResources();
180b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        DisplayMetrics metrics = getContext().getMetrics();
181c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
18216584225125acba18b74920b902c798dfead0328Xavier Ducrohet        // use default of true in case it's not found to use alpha by default
18316584225125acba18b74920b902c798dfead0328Xavier Ducrohet        mIsAlphaChannelImage  = getBooleanThemeValue(resources,
18416584225125acba18b74920b902c798dfead0328Xavier Ducrohet                "windowIsFloating", true /*defaultValue*/);
18516584225125acba18b74920b902c798dfead0328Xavier Ducrohet
186bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        mWindowIsFloating = getBooleanThemeValue(resources, "windowIsFloating",
187bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                true /*defaultValue*/);
1882eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
18916584225125acba18b74920b902c798dfead0328Xavier Ducrohet        findBackground(resources);
19016584225125acba18b74920b902c798dfead0328Xavier Ducrohet        findStatusBar(resources, metrics);
191bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        findActionBar(resources, metrics);
192891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet        findNavigationBar(resources, metrics);
193c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1946dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet        // FIXME: find those out, and possibly add them to the render params
1956dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet        boolean hasSystemNavBar = true;
1966dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet        boolean hasNavigationBar = true;
1976dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet        IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(),
1986dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet                metrics, Surface.ROTATION_0,
1996dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet                hasSystemNavBar, hasNavigationBar);
2006dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet        WindowManagerGlobal_Delegate.setWindowManagerService(iwm);
2016dfd0b39a63559999a769f93d5cdb48abe675344Xavier Ducrohet
202c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        // build the inflater and parser.
203b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        mInflater = new BridgeInflater(context, params.getProjectCallback());
204b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        context.setBridgeInflater(mInflater);
2052eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
20602d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet        mBlockParser = new BridgeXmlBlockParser(
20702d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet                params.getLayoutDescription(), context, false /* platformResourceFlag */);
2082eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
209168677c9e2f8438ec5687e3c6b0e41b986c5b230Xavier Ducrohet        return SUCCESS.createResult();
210c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
211c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
212c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
213c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * Inflates the layout.
214c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * <p>
2152eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
2162eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *
2172eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
2182eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *      the scene, or if {@link #init(long)} was not called.
219c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     */
22019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public Result inflate() {
2212eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        checkLock();
2222eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
223c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        try {
224c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
225b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            SessionParams params = getParams();
226891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            HardwareConfig hardwareConfig = params.getHardwareConfig();
227b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            BridgeContext context = getContext();
228b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
229891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
230abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet            // the view group that receives the window background.
231abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet            ViewGroup backgroundView = null;
232abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet
233b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            if (mWindowIsFloating || params.isForceNoDecor()) {
234abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                backgroundView = mViewRoot = mContentRoot = new FrameLayout(context);
235bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            } else {
236891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                if (hasSoftwareButtons() && mNavigationBarOrientation == LinearLayout.VERTICAL) {
237891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    /*
238891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                     * This is a special case where the navigation bar is on the right.
239891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       +-------------------------------------------------+---+
240891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | Status bar (always)                             |   |
241891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       +-------------------------------------------------+   |
242891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | (Layout with background drawable)               |   |
243891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | +---------------------------------------------+ |   |
244891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | | Title/Action bar (optional)                 | |   |
245891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | +---------------------------------------------+ |   |
246891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | | Content, vertical extending                 | |   |
247891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | |                                             | |   |
248891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       | +---------------------------------------------+ |   |
249891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       +-------------------------------------------------+---+
250891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
251891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       So we create a horizontal layout, with the nav bar on the right,
252891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       and the left part is the normal layout below without the nav bar at
253891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                       the bottom
254891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                     */
255891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    LinearLayout topLayout = new LinearLayout(context);
256891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    mViewRoot = topLayout;
257891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    topLayout.setOrientation(LinearLayout.HORIZONTAL);
258891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
259891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    try {
260891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                        NavigationBar navigationBar = new NavigationBar(context,
261891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                                hardwareConfig.getDensity(), LinearLayout.VERTICAL);
262891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                        navigationBar.setLayoutParams(
263891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                                new LinearLayout.LayoutParams(
264891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                                        mNavigationBarSize,
265891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                                        LayoutParams.MATCH_PARENT));
266891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                        topLayout.addView(navigationBar);
267891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    } catch (XmlPullParserException e) {
268891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
269891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    }
270891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                }
271891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
272bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                /*
273bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                 * we're creating the following layout
274bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                 *
275bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                   +-------------------------------------------------+
276891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                   | Status bar (always)                             |
277bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                   +-------------------------------------------------+
278abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | (Layout with background drawable)               |
279abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | +---------------------------------------------+ |
280abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | | Title/Action bar (optional)                 | |
281abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | +---------------------------------------------+ |
282abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | | Content, vertical extending                 | |
283abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | |                                             | |
284abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                   | +---------------------------------------------+ |
285bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                   +-------------------------------------------------+
286891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                   | Navigation bar for soft buttons, maybe see above|
287bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                   +-------------------------------------------------+
288bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
289bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                 */
290bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
291b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                LinearLayout topLayout = new LinearLayout(context);
292bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                topLayout.setOrientation(LinearLayout.VERTICAL);
293891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                // if we don't already have a view root this is it
294891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                if (mViewRoot == null) {
295891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    mViewRoot = topLayout;
296891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                } else {
297891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
298891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                            LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
299891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    layoutParams.weight = 1;
300891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    topLayout.setLayoutParams(layoutParams);
301891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
302891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    // this is the case of soft buttons + vertical bar.
303891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    // this top layout is the first layout in the horizontal layout. see above)
304891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    mViewRoot.addView(topLayout, 0);
305891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                }
306bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
307bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                if (mStatusBarSize > 0) {
308bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    // system bar
309bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    try {
310891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                        StatusBar systemBar = new StatusBar(context, hardwareConfig.getDensity());
311bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                        systemBar.setLayoutParams(
312bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                                new LinearLayout.LayoutParams(
313bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                                        LayoutParams.MATCH_PARENT, mStatusBarSize));
314bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                        topLayout.addView(systemBar);
315bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    } catch (XmlPullParserException e) {
316bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
317bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    }
318bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                }
319bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
320abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                LinearLayout backgroundLayout = new LinearLayout(context);
321abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                backgroundView = backgroundLayout;
322abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                backgroundLayout.setOrientation(LinearLayout.VERTICAL);
323abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
324abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                        LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
325abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                layoutParams.weight = 1;
326abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                backgroundLayout.setLayoutParams(layoutParams);
327abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                topLayout.addView(backgroundLayout);
328abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet
329abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet
330bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                // if the theme says no title/action bar, then the size will be 0
331bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                if (mActionBarSize > 0) {
332bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    try {
333b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                        FakeActionBar actionBar = new FakeActionBar(context,
334891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                                hardwareConfig.getDensity(),
335b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                                params.getAppLabel(), params.getAppIcon());
336bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                        actionBar.setLayoutParams(
337bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                                new LinearLayout.LayoutParams(
338bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                                        LayoutParams.MATCH_PARENT, mActionBarSize));
339abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                        backgroundLayout.addView(actionBar);
340bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    } catch (XmlPullParserException e) {
341bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
342bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    }
343bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                } else if (mTitleBarSize > 0) {
344bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    try {
345b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                        TitleBar titleBar = new TitleBar(context,
346891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                                hardwareConfig.getDensity(), params.getAppLabel());
347bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                        titleBar.setLayoutParams(
348bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                                new LinearLayout.LayoutParams(
349bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                                        LayoutParams.MATCH_PARENT, mTitleBarSize));
350abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                        backgroundLayout.addView(titleBar);
351bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    } catch (XmlPullParserException e) {
352bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
353bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    }
354bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                }
355bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
356bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                // content frame
357b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                mContentRoot = new FrameLayout(context);
358abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                layoutParams = new LinearLayout.LayoutParams(
359bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                        LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
360b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                layoutParams.weight = 1;
361b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                mContentRoot.setLayoutParams(layoutParams);
362abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet                backgroundLayout.addView(mContentRoot);
363bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
364891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                if (mNavigationBarOrientation == LinearLayout.HORIZONTAL &&
365891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                        mNavigationBarSize > 0) {
366bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    // system bar
367bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    try {
368891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                        NavigationBar navigationBar = new NavigationBar(context,
369891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                                hardwareConfig.getDensity(), LinearLayout.HORIZONTAL);
370891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                        navigationBar.setLayoutParams(
371bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                                new LinearLayout.LayoutParams(
372891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                                        LayoutParams.MATCH_PARENT, mNavigationBarSize));
373891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                        topLayout.addView(navigationBar);
374bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    } catch (XmlPullParserException e) {
375bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
376bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    }
377bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                }
378bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            }
379bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
380c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
381c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // Sets the project callback (custom view loader) to the fragment delegate so that
382c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // it can instantiate the custom Fragment.
383b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            Fragment_Delegate.setProjectCallback(params.getProjectCallback());
384c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
385bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            View view = mInflater.inflate(mBlockParser, mContentRoot);
386c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
3872fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            // done with the parser, pop it.
3882fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            context.popParser();
3892fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
390c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            Fragment_Delegate.setProjectCallback(null);
391c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
392c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // set the AttachInfo on the root view.
3937f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet            AttachInfo_Accessor.setAttachInfo(mViewRoot);
394c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
39533758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet            // post-inflate process. For now this supports TabHost/TabWidget
396b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            postInflateProcess(view, params.getProjectCallback());
39733758ef8c98efb669c65eb9404b99ee5df09c6b5Xavier Ducrohet
398c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // get the background drawable
399abc33e014d4490dc993d1453e2589f538dbd7bbeXavier Ducrohet            if (mWindowBackground != null && backgroundView != null) {
400b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                Drawable d = ResourceHelper.getDrawable(mWindowBackground, context);
401891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                backgroundView.setBackground(d);
402c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
403c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
40419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult();
405c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        } catch (PostInflateException e) {
40619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return ERROR_INFLATION.createResult(e.getMessage(), e);
407c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        } catch (Throwable e) {
408c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // get the real cause of the exception.
409c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            Throwable t = e;
410c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            while (t.getCause() != null) {
411c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                t = t.getCause();
412c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
413c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
41419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return ERROR_INFLATION.createResult(t.getMessage(), t);
415c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
416c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
417c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
418c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
419c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * Renders the scene.
420c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * <p>
4212eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
4222eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *
4235a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet     * @param freshRender whether the render is a new one and should erase the existing bitmap (in
4245a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet     *      the case where bitmaps are reused). This is typically needed when not playing
4255a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet     *      animations.)
4265a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet     *
4272eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
4282eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
4299eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet     *
430bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * @see RenderParams#getRenderingMode()
431bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * @see RenderSession#render(long)
432c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     */
4335a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet    public Result render(boolean freshRender) {
4342eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        checkLock();
4352eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
436b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        SessionParams params = getParams();
437b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
438c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        try {
439c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            if (mViewRoot == null) {
44019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet                return ERROR_NOT_INFLATED.createResult();
441c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
442c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
443b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            RenderingMode renderingMode = params.getRenderingMode();
444891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            HardwareConfig hardwareConfig = params.getHardwareConfig();
445fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet
4469eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet            // only do the screen measure when needed.
4479eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet            boolean newRenderSize = false;
4489eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet            if (mMeasuredScreenWidth == -1) {
4499eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                newRenderSize = true;
450891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                mMeasuredScreenWidth = hardwareConfig.getScreenWidth();
451891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                mMeasuredScreenHeight = hardwareConfig.getScreenHeight();
4529eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet
4539eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                if (renderingMode != RenderingMode.NORMAL) {
454c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    int widthMeasureSpecMode = renderingMode.isHorizExpand() ?
455c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
456c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            : MeasureSpec.EXACTLY;
457c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    int heightMeasureSpecMode = renderingMode.isVertExpand() ?
458c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
459c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            : MeasureSpec.EXACTLY;
460c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
461c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // We used to compare the measured size of the content to the screen size but
462c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // this does not work anymore due to the 2 following issues:
463c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // - If the content is in a decor (system bar, title/action bar), the root view
464c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    //   will not resize even with the UNSPECIFIED because of the embedded layout.
465c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // - If there is no decor, but a dialog frame, then the dialog padding prevents
466c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    //   comparing the size of the content to the screen frame (as it would not
467c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    //   take into account the dialog padding).
468c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
469c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // The solution is to first get the content size in a normal rendering, inside
470c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // the decor or the dialog padding.
471c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // Then measure only the content with UNSPECIFIED to see the size difference
472c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // and apply this to the screen size.
473c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
474c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // first measure the full layout, with EXACTLY to get the size of the
475c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // content as it is inside the decor/dialog
476c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    Pair<Integer, Integer> exactMeasure = measureView(
477c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mViewRoot, mContentRoot.getChildAt(0),
478c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mMeasuredScreenWidth, MeasureSpec.EXACTLY,
479c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mMeasuredScreenHeight, MeasureSpec.EXACTLY);
480c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
481c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // now measure the content only using UNSPECIFIED (where applicable, based on
482c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // the rendering mode). This will give us the size the content needs.
483c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    Pair<Integer, Integer> result = measureView(
484c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mContentRoot, mContentRoot.getChildAt(0),
485c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mMeasuredScreenWidth, widthMeasureSpecMode,
486c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mMeasuredScreenHeight, heightMeasureSpecMode);
487c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
488c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    // now look at the difference and add what is needed.
4899eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                    if (renderingMode.isHorizExpand()) {
490c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                        int measuredWidth = exactMeasure.getFirst();
491c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                        int neededWidth = result.getFirst();
492c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                        if (neededWidth > measuredWidth) {
493c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mMeasuredScreenWidth += neededWidth - measuredWidth;
4949eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                        }
495fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet                    }
496c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
4979eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                    if (renderingMode.isVertExpand()) {
498c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                        int measuredHeight = exactMeasure.getSecond();
499c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                        int neededHeight = result.getSecond();
500c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                        if (neededHeight > measuredHeight) {
501c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                            mMeasuredScreenHeight += neededHeight - measuredHeight;
5029eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                        }
503fb25cae1916da1caf206ede879f07a4f8b61cfecXavier Ducrohet                    }
504c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                }
505c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
506c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
507c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet            // measure again with the size we need
508c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // This must always be done before the call to layout
509c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet            measureView(mViewRoot, null /*measuredView*/,
510c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    mMeasuredScreenWidth, MeasureSpec.EXACTLY,
511c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet                    mMeasuredScreenHeight, MeasureSpec.EXACTLY);
512c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
513c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // now do the layout.
51416584225125acba18b74920b902c798dfead0328Xavier Ducrohet            mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
515c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
51610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet            if (params.isLayoutOnly()) {
51710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                // delete the canvas and image to reset them on the next full rendering
51810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                mImage = null;
51910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                mCanvas = null;
52010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet            } else {
5217f9f99ea11051614a7727dfb9f9578b518e76e3cXavier Ducrohet                AttachInfo_Accessor.dispatchOnPreDraw(mViewRoot);
52210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet
52310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                // draw the views
52410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                // create the BufferedImage into which the layout will be rendered.
52510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                boolean newImage = false;
52610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                if (newRenderSize || mCanvas == null) {
52710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    if (params.getImageFactory() != null) {
52810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        mImage = params.getImageFactory().getImage(
52910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                                mMeasuredScreenWidth,
53010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                                mMeasuredScreenHeight);
53110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    } else {
53210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        mImage = new BufferedImage(
53310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                                mMeasuredScreenWidth,
53410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                                mMeasuredScreenHeight,
53510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                                BufferedImage.TYPE_INT_ARGB);
53610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        newImage = true;
53710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    }
53810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet
53910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    if (params.isBgColorOverridden()) {
54010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        // since we override the content, it's the same as if it was a new image.
54110df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        newImage = true;
54210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        Graphics2D gc = mImage.createGraphics();
54310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        gc.setColor(new Color(params.getOverrideBgColor(), true));
54410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        gc.setComposite(AlphaComposite.Src);
54510df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
54610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                        gc.dispose();
54710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    }
54810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet
54910df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    // create an Android bitmap around the BufferedImage
55010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
551891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                            true /*isMutable*/, hardwareConfig.getDensity());
55210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet
55310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    // create a Canvas around the Android bitmap
55410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    mCanvas = new Canvas(bitmap);
555891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue());
5569eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                }
557c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
55810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                if (freshRender && newImage == false) {
5599eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet                    Graphics2D gc = mImage.createGraphics();
5605a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet                    gc.setComposite(AlphaComposite.Src);
561c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
56210df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    gc.setColor(new Color(0x00000000, true));
56310df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    gc.fillRect(0, 0,
56410df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                            mMeasuredScreenWidth, mMeasuredScreenHeight);
56516584225125acba18b74920b902c798dfead0328Xavier Ducrohet
56610df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    // done
56710df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                    gc.dispose();
56810df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                }
56916584225125acba18b74920b902c798dfead0328Xavier Ducrohet
57010df650f0d4bdf086dae9ac29fafd8a1ded06c23Xavier Ducrohet                mViewRoot.draw(mCanvas);
5715a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet            }
5725a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet
57305b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet            mViewInfoList = startVisitingViews(mViewRoot, 0, params.getExtendedViewInfoMode());
574c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
575c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // success!
57619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult();
577c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        } catch (Throwable e) {
578c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // get the real cause of the exception.
579c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            Throwable t = e;
580c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            while (t.getCause() != null) {
581c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                t = t.getCause();
582c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
583c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
58419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return ERROR_UNKNOWN.createResult(t.getMessage(), t);
585c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
586c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
587c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
588c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
589c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * Executes {@link View#measure(int, int)} on a given view with the given parameters (used
590c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * to create measure specs with {@link MeasureSpec#makeMeasureSpec(int, int)}.
591c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     *
592c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * if <var>measuredView</var> is non null, the method returns a {@link Pair} of (width, height)
593c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * for the view (using {@link View#getMeasuredWidth()} and {@link View#getMeasuredHeight()}).
594c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     *
595c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @param viewToMeasure the view on which to execute measure().
596c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @param measuredView if non null, the view to query for its measured width/height.
597c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @param width the width to use in the MeasureSpec.
598c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @param widthMode the MeasureSpec mode to use for the width.
599c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @param height the height to use in the MeasureSpec.
600c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @param heightMode the MeasureSpec mode to use for the height.
601c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     * @return the measured width/height if measuredView is non-null, null otherwise.
602c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet     */
603c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet    private Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
604c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet            int width, int widthMode, int height, int heightMode) {
605c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet        int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode);
606c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet        int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode);
607c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet        viewToMeasure.measure(w_spec, h_spec);
608c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
609c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet        if (measuredView != null) {
610c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet            return Pair.of(measuredView.getMeasuredWidth(), measuredView.getMeasuredHeight());
611c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet        }
612c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
613c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet        return null;
614c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet    }
615c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet
616c5aeac7f157e3cb9e29ab8c126f74e26493501f5Xavier Ducrohet    /**
6172eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * Animate an object
6182eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * <p>
6192eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
6202eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *
6212eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
6222eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
623e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
624bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * @see RenderSession#animate(Object, String, boolean, IAnimationListener)
6252eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet     */
62619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public Result animate(Object targetObject, String animationName,
6272eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            boolean isFrameworkAnimation, IAnimationListener listener) {
6282eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        checkLock();
6292eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
630b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        BridgeContext context = getContext();
631b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
6322eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        // find the animation file.
633ffb42f6c5043de226f02318a1311669d35a90711Xavier Ducrohet        ResourceValue animationResource = null;
6342eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        int animationId = 0;
6352eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        if (isFrameworkAnimation) {
636b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            animationResource = context.getRenderResources().getFrameworkResource(
63735ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet                    ResourceType.ANIMATOR, animationName);
6382eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            if (animationResource != null) {
639b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet                animationId = Bridge.getResourceId(ResourceType.ANIMATOR, animationName);
6402eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            }
6412eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        } else {
642b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet            animationResource = context.getRenderResources().getProjectResource(
64335ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet                    ResourceType.ANIMATOR, animationName);
6442eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            if (animationResource != null) {
645b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                animationId = context.getProjectCallback().getResourceId(
64635ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet                        ResourceType.ANIMATOR, animationName);
6472eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            }
6482eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        }
6492eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
6502eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        if (animationResource != null) {
6512eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            try {
652b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                Animator anim = AnimatorInflater.loadAnimator(context, animationId);
6532eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet                if (anim != null) {
6542eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet                    anim.setTarget(targetObject);
6552eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
656e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    new PlayAnimationThread(anim, this, animationName, listener).start();
6572eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
65819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet                    return SUCCESS.createResult();
6592eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet                }
6602eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            } catch (Exception e) {
661c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet                // get the real cause of the exception.
662c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet                Throwable t = e;
663c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet                while (t.getCause() != null) {
664c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet                    t = t.getCause();
665c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet                }
666c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
66719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet                return ERROR_UNKNOWN.createResult(t.getMessage(), t);
6682eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet            }
6692eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet        }
6702eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
67119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet        return ERROR_ANIM_NOT_FOUND.createResult();
672c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet    }
673c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
674e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    /**
675e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * Insert a new child into an existing parent.
676e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * <p>
677e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
678e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
679e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
680e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
681e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
682bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener)
683e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     */
68419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml,
685e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            final int index, IAnimationListener listener) {
686c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        checkLock();
687c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
688b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        BridgeContext context = getContext();
689b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet
690c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        // create a block parser for the XML
69102d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet        BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
69202d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet                childXml, context, false /* platformResourceFlag */);
693c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
694c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        // inflate the child without adding it to the root since we want to control where it'll
695c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        // get added. We do pass the parentView however to ensure that the layoutParams will
696c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        // be created correctly.
697e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/);
69802d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet        blockParser.ensurePopped();
699c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
700e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        invalidateRenderingSize();
701e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
702e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        if (listener != null) {
703e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            new AnimationThread(this, "insertChild", listener) {
704e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
705e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                @Override
70619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet                public Result preAnimation() {
707e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    parentView.setLayoutTransition(new LayoutTransition());
708e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    return addView(parentView, child, index);
709e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                }
710e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
711e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                @Override
712e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                public void postAnimation() {
713e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    parentView.setLayoutTransition(null);
714e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                }
715e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            }.start();
716e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
717e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            // always return success since the real status will come through the listener.
71819a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult(child);
7199eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet        }
7209eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet
721e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        // add it to the parentView in the correct location
72219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet        Result result = addView(parentView, child, index);
723e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        if (result.isSuccess() == false) {
724e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            return result;
725e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
726c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
7275a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet        result = render(false /*freshRender*/);
728c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet        if (result.isSuccess()) {
729e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            result = result.getCopyWithData(child);
730c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet        }
731c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet
732c8aec064f9f304c88f61c8c1aa3d60521b92177aXavier Ducrohet        return result;
733c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet    }
734c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
735e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    /**
736e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * Adds a given view to a given parent at a given index.
737e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
738e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @param parent the parent to receive the view
739e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @param view the view to add to the parent
740e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @param index the index where to do the add.
741e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
74219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     * @return a Result with {@link Status#SUCCESS} or
74319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
744e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *     adding views.
745e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     */
74619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    private Result addView(ViewGroup parent, View view, int index) {
747e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        try {
748e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            parent.addView(view, index);
74919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult();
750e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        } catch (UnsupportedOperationException e) {
751e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            // looks like this is a view class that doesn't support children manipulation!
75219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
753e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
754e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    }
755e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
756e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    /**
757e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * Moves a view to a new parent at a given location
758e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * <p>
759e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
760e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
761e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
762e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
763e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
764bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener)
765e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     */
7662b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet    public Result moveChild(final ViewGroup newParentView, final View childView, final int index,
767479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            Map<String, String> layoutParamsMap, final IAnimationListener listener) {
768c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        checkLock();
769c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
770e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        invalidateRenderingSize();
771e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
77201811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet        LayoutParams layoutParams = null;
773e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        if (layoutParamsMap != null) {
774e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            // need to create a new LayoutParams object for the new parent.
7752b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet            layoutParams = newParentView.generateLayoutParams(
776e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    new BridgeLayoutParamsMapAttributes(layoutParamsMap));
777e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
7789eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet
7792b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet        // get the current parent of the view that needs to be moved.
7802b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet        final ViewGroup previousParent = (ViewGroup) childView.getParent();
7812b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
782e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        if (listener != null) {
783e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            final LayoutParams params = layoutParams;
78401811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet
785479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            // there is no support for animating views across layouts, so in case the new and old
786479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            // parent views are different we fake the animation through a no animation thread.
787479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            if (previousParent != newParentView) {
788479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                new Thread("not animated moveChild") {
789479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    @Override
790479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    public void run() {
791479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        Result result = moveView(previousParent, newParentView, childView, index,
792479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                                params);
793479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        if (result.isSuccess() == false) {
794479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            listener.done(result);
795479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        }
796479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
797479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // ready to do the work, acquire the scene.
798479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        result = acquire(250);
799479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        if (result.isSuccess() == false) {
800479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            listener.done(result);
801479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            return;
802479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        }
803479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
804479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        try {
8055a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet                            result = render(false /*freshRender*/);
806479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            if (result.isSuccess()) {
807479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                                listener.onNewFrame(RenderSessionImpl.this.getSession());
808479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            }
809479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        } finally {
810479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            release();
811479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        }
812479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
813479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        listener.done(result);
8142b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                    }
815479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                }.start();
816479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            } else {
817479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                new AnimationThread(this, "moveChild", listener) {
8182b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
819479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    @Override
820479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    public Result preAnimation() {
821479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // set up the transition for the parent.
822479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        LayoutTransition transition = new LayoutTransition();
823479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        previousParent.setLayoutTransition(transition);
8247550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet
825479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // tweak the animation durations and start delays (to match the duration of
826479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // animation playing just before).
827479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // Note: Cannot user Animation.setDuration() directly. Have to set it
828479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // on the LayoutTransition.
829479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        transition.setDuration(LayoutTransition.DISAPPEARING, 100);
830479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // CHANGE_DISAPPEARING plays after DISAPPEARING
831479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100);
83201811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet
833479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100);
834479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
835479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100);
836479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        // CHANGE_APPEARING plays after CHANGE_APPEARING
837479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        transition.setStartDelay(LayoutTransition.APPEARING, 100);
838479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
839479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        transition.setDuration(LayoutTransition.APPEARING, 100);
840479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
841479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        return moveView(previousParent, newParentView, childView, index, params);
842479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    }
843479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
844479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    @Override
845479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    public void postAnimation() {
846479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        previousParent.setLayoutTransition(null);
847479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        newParentView.setLayoutTransition(null);
848479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    }
849479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                }.start();
850479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            }
851e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
852e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            // always return success since the real status will come through the listener.
85319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult(layoutParams);
854c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        }
855c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
8562b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet        Result result = moveView(previousParent, newParentView, childView, index, layoutParams);
857e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        if (result.isSuccess() == false) {
858e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            return result;
859e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
860c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
8615a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet        result = render(false /*freshRender*/);
86201811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet        if (layoutParams != null && result.isSuccess()) {
863e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            result = result.getCopyWithData(layoutParams);
86401811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet        }
86501811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet
86601811aa86279af1b341a4fff344d66c0ebdd63daXavier Ducrohet        return result;
867c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet    }
868c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
869e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    /**
870e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * Moves a View from its current parent to a new given parent at a new given location, with
871e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * an optional new {@link LayoutParams} instance
872e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
8732b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet     * @param previousParent the previous parent, still owning the child at the time of the call.
8742b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet     * @param newParent the new parent
875479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet     * @param movedView the view to move
876e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @param index the new location in the new parent
877e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @param params an option (can be null) {@link LayoutParams} instance.
878e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
87919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     * @return a Result with {@link Status#SUCCESS} or
88019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
881e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *     adding views.
882e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     */
883479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet    private Result moveView(ViewGroup previousParent, final ViewGroup newParent,
884479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            final View movedView, final int index, final LayoutParams params) {
8859eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet        try {
8862b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet            // check if there is a transition on the previousParent.
887479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            LayoutTransition previousTransition = previousParent.getLayoutTransition();
888479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet            if (previousTransition != null) {
8897550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // in this case there is an animation. This means we have to wait for the child's
8907550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // parent reference to be null'ed out so that we can add it to the new parent.
8917550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // It is technically removed right before the DISAPPEARING animation is done (if
8927550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // the animation of this type is not null, otherwise it's after which is impossible
8937550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // to handle).
8947550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // Because there is no move animation, if the new parent is the same as the old
8957550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before
8967550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // adding the child or the child will appear in its new location before the
8977550ec1d8e526c4ae8c0bb08b06e1b6e799eacecXavier Ducrohet                // other children have made room for it.
8982b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
8992b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                // add a listener to the transition to be notified of the actual removal.
900479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                previousTransition.addTransitionListener(new TransitionListener() {
901479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    private int mChangeDisappearingCount = 0;
9022b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
90346d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet                    @Override
9042b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                    public void startTransition(LayoutTransition transition, ViewGroup container,
9052b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                            View view, int transitionType) {
906479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
907479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            mChangeDisappearingCount++;
908479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        }
9092b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                    }
910e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
91146d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet                    @Override
9122b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                    public void endTransition(LayoutTransition transition, ViewGroup container,
9132b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                            View view, int transitionType) {
914479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
915479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                            mChangeDisappearingCount--;
916479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        }
917479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet
918479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING &&
919479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                                mChangeDisappearingCount == 0) {
9202b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                            // add it to the parentView in the correct location
9212b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                            if (params != null) {
922479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                                newParent.addView(movedView, index, params);
9232b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                            } else {
924479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                                newParent.addView(movedView, index);
9252b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                            }
9262b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                        }
9272b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                    }
9282b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                });
9292b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
9302b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                // remove the view from the current parent.
931479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                previousParent.removeView(movedView);
9322b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
9332b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                // and return since adding the view to the new parent is done in the listener.
9342b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                return SUCCESS.createResult();
935e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            } else {
9362b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                // standard code with no animation. pretty simple.
937479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                previousParent.removeView(movedView);
938e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
9392b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                // add it to the parentView in the correct location
9402b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                if (params != null) {
941479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    newParent.addView(movedView, index, params);
9422b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                } else {
943479101a9b4142d21d42351684bc9bc65ec3471beXavier Ducrohet                    newParent.addView(movedView, index);
9442b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                }
9452b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet
9462b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet                return SUCCESS.createResult();
9472b9c38ab62abc8d5b2f956e961087f259caf25ffXavier Ducrohet            }
9489eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet        } catch (UnsupportedOperationException e) {
9499eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet            // looks like this is a view class that doesn't support children manipulation!
95019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
951c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        }
952e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    }
953e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
954e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    /**
955e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * Removes a child from its current parent.
956e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * <p>
957e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * {@link #acquire(long)} must have been called before this.
958e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
959e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @throws IllegalStateException if the current context is different than the one owned by
960e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *      the scene, or if {@link #acquire(long)} was not called.
961e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
962bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * @see RenderSession#removeChild(Object, IAnimationListener)
963e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     */
96419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public Result removeChild(final View childView, IAnimationListener listener) {
965e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        checkLock();
966c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
9679eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet        invalidateRenderingSize();
9689eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet
969e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        final ViewGroup parent = (ViewGroup) childView.getParent();
970e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
971e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        if (listener != null) {
972e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            new AnimationThread(this, "moveChild", listener) {
973e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
974e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                @Override
97519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet                public Result preAnimation() {
976e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    parent.setLayoutTransition(new LayoutTransition());
977e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    return removeView(parent, childView);
978e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                }
979e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
980e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                @Override
981e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                public void postAnimation() {
982e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                    parent.setLayoutTransition(null);
983e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet                }
984e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            }.start();
985e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
986e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            // always return success since the real status will come through the listener.
98719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult();
988e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
989e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
99019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet        Result result = removeView(parent, childView);
991e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        if (result.isSuccess() == false) {
992e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            return result;
993e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
994e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
9955a82d8c58bf91c357c37a82b9f5e5c26f676d847Xavier Ducrohet        return render(false /*freshRender*/);
9962eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    }
9972eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
9982eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet    /**
999e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * Removes a given view from its current parent.
1000e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
1001e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     * @param view the view to remove from its parent
1002e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *
100319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     * @return a Result with {@link Status#SUCCESS} or
100419a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
1005e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     *     adding views.
1006e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet     */
100719a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    private Result removeView(ViewGroup parent, View view) {
1008e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        try {
1009e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            parent.removeView(view);
101019a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return SUCCESS.createResult();
1011e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        } catch (UnsupportedOperationException e) {
1012e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet            // looks like this is a view class that doesn't support children manipulation!
101319a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
1014e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet        }
1015e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet    }
1016e1179ea065392485a6e3bf1e28a1242179cd48b0Xavier Ducrohet
10172eea6fab1cbb0a5c8f913491c2d622c904759893Xavier Ducrohet
101816584225125acba18b74920b902c798dfead0328Xavier Ducrohet    private void findBackground(RenderResources resources) {
1019b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        if (getParams().isBgColorOverridden() == false) {
102001b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet            mWindowBackground = resources.findItemInTheme("windowBackground",
102101b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet                    true /*isFrameworkAttr*/);
102216584225125acba18b74920b902c798dfead0328Xavier Ducrohet            if (mWindowBackground != null) {
102316584225125acba18b74920b902c798dfead0328Xavier Ducrohet                mWindowBackground = resources.resolveResValue(mWindowBackground);
102416584225125acba18b74920b902c798dfead0328Xavier Ducrohet            }
102516584225125acba18b74920b902c798dfead0328Xavier Ducrohet        }
102616584225125acba18b74920b902c798dfead0328Xavier Ducrohet    }
1027c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1028891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet    private boolean hasSoftwareButtons() {
1029891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet        return getParams().getHardwareConfig().hasSoftwareButtons();
103016584225125acba18b74920b902c798dfead0328Xavier Ducrohet    }
1031c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
103216584225125acba18b74920b902c798dfead0328Xavier Ducrohet    private void findStatusBar(RenderResources resources, DisplayMetrics metrics) {
1033891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet        boolean windowFullscreen = getBooleanThemeValue(resources,
1034891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                "windowFullscreen", false /*defaultValue*/);
103516584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1036891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet        if (windowFullscreen == false && mWindowIsFloating == false) {
1037891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            // default value
1038891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT;
103916584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1040891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            // get the real value
1041891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
1042891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    "status_bar_height");
104316584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1044891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            if (value != null) {
1045891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                TypedValue typedValue = ResourceHelper.getValue("status_bar_height",
1046891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                        value.getValue(), true /*requireUnit*/);
1047891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                if (typedValue != null) {
1048891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    // compute the pixel value based on the display metrics
1049891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    mStatusBarSize = (int)typedValue.getDimension(metrics);
105016584225125acba18b74920b902c798dfead0328Xavier Ducrohet                }
105116584225125acba18b74920b902c798dfead0328Xavier Ducrohet            }
105216584225125acba18b74920b902c798dfead0328Xavier Ducrohet        }
105316584225125acba18b74920b902c798dfead0328Xavier Ducrohet    }
105416584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1055bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    private void findActionBar(RenderResources resources, DisplayMetrics metrics) {
1056bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        if (mWindowIsFloating) {
1057bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            return;
105816584225125acba18b74920b902c798dfead0328Xavier Ducrohet        }
105916584225125acba18b74920b902c798dfead0328Xavier Ducrohet
106016584225125acba18b74920b902c798dfead0328Xavier Ducrohet        boolean windowActionBar = getBooleanThemeValue(resources,
106116584225125acba18b74920b902c798dfead0328Xavier Ducrohet                "windowActionBar", true /*defaultValue*/);
106216584225125acba18b74920b902c798dfead0328Xavier Ducrohet
106316584225125acba18b74920b902c798dfead0328Xavier Ducrohet        // if there's a value and it's false (default is true)
106416584225125acba18b74920b902c798dfead0328Xavier Ducrohet        if (windowActionBar) {
1065c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1066c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // default size of the window title bar
1067bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            mActionBarSize = DEFAULT_TITLE_BAR_HEIGHT;
1068c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1069c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // get value from the theme.
107001b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet            ResourceValue value = resources.findItemInTheme("actionBarSize",
107101b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet                    true /*isFrameworkAttr*/);
1072c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1073c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // resolve it
107416584225125acba18b74920b902c798dfead0328Xavier Ducrohet            value = resources.resolveResValue(value);
1075c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1076c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            if (value != null) {
1077c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                // get the numerical value, if available
107804ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet                TypedValue typedValue = ResourceHelper.getValue("actionBarSize", value.getValue(),
107904ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet                        true /*requireUnit*/);
1080c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                if (typedValue != null) {
1081c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    // compute the pixel value based on the display metrics
1082bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    mActionBarSize = (int)typedValue.getDimension(metrics);
1083c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                }
1084c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
1085bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        } else {
1086bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            // action bar overrides title bar so only look for this one if action bar is hidden
1087bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            boolean windowNoTitle = getBooleanThemeValue(resources,
1088bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    "windowNoTitle", false /*defaultValue*/);
1089c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1090bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            if (windowNoTitle == false) {
109116584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1092bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                // default size of the window title bar
1093bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                mTitleBarSize = DEFAULT_TITLE_BAR_HEIGHT;
109416584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1095bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                // get value from the theme.
109601b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet                ResourceValue value = resources.findItemInTheme("windowTitleSize",
109701b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet                        true /*isFrameworkAttr*/);
109816584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1099bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                // resolve it
1100bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                value = resources.resolveResValue(value);
1101c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1102bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                if (value != null) {
1103bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    // get the numerical value, if available
110404ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet                    TypedValue typedValue = ResourceHelper.getValue("windowTitleSize",
110504ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet                            value.getValue(), true /*requireUnit*/);
1106bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    if (typedValue != null) {
1107bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                        // compute the pixel value based on the display metrics
1108bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                        mTitleBarSize = (int)typedValue.getDimension(metrics);
1109bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    }
111016584225125acba18b74920b902c798dfead0328Xavier Ducrohet                }
111116584225125acba18b74920b902c798dfead0328Xavier Ducrohet            }
1112bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
111316584225125acba18b74920b902c798dfead0328Xavier Ducrohet        }
111416584225125acba18b74920b902c798dfead0328Xavier Ducrohet    }
111516584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1116891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet    private void findNavigationBar(RenderResources resources, DisplayMetrics metrics) {
1117891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet        if (hasSoftwareButtons() && mWindowIsFloating == false) {
1118c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1119c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // default value
1120891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            mNavigationBarSize = 48; // ??
1121891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
1122891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            HardwareConfig hardwareConfig = getParams().getHardwareConfig();
1123891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
1124891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            boolean barOnBottom = true;
1125891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
1126891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            if (hardwareConfig.getOrientation() == ScreenOrientation.LANDSCAPE) {
1127891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                // compute the dp of the screen.
1128891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                int shortSize = hardwareConfig.getScreenHeight();
1129891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
1130891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                // compute in dp
1131891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / hardwareConfig.getDensity().getDpiValue();
1132891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
1133891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                if (shortSizeDp < 600) {
1134891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    // 0-599dp: "phone" UI with bar on the side
1135891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    barOnBottom = false;
1136891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                } else {
1137891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    // 600+dp: "tablet" UI with bar on the bottom
1138891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    barOnBottom = true;
1139891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                }
1140891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            }
1141891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet
1142891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            if (barOnBottom) {
1143891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                mNavigationBarOrientation = LinearLayout.HORIZONTAL;
1144891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            } else {
1145891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                mNavigationBarOrientation = LinearLayout.VERTICAL;
1146891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet            }
1147c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1148d1d6fafc7fc63543b10552dadf202dd6fa40fe6bXavier Ducrohet            // get the real value
114935ea7cd4c0c89122fda0b57af20061645082ffb9Xavier Ducrohet            ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
1150891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    barOnBottom ? "navigation_bar_height" : "navigation_bar_width");
115116584225125acba18b74920b902c798dfead0328Xavier Ducrohet
1152c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            if (value != null) {
1153891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                TypedValue typedValue = ResourceHelper.getValue("navigation_bar_height",
115404ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet                        value.getValue(), true /*requireUnit*/);
1155c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                if (typedValue != null) {
1156c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    // compute the pixel value based on the display metrics
1157891b703f7b1e0e396d16477cc66a286da7161b49Xavier Ducrohet                    mNavigationBarSize = (int)typedValue.getDimension(metrics);
1158c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                }
1159c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
116016584225125acba18b74920b902c798dfead0328Xavier Ducrohet        }
116116584225125acba18b74920b902c798dfead0328Xavier Ducrohet    }
116216584225125acba18b74920b902c798dfead0328Xavier Ducrohet
116301b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet    /**
116401b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     * Looks for a attribute in the current theme. The attribute is in the android
116501b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     * namespace.
116601b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     *
116701b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     * @param resources the render resources
116801b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     * @param name the name of the attribute
116901b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     * @param defaultValue the default value.
117001b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     * @return the value of the attribute or the default one if not found.
117101b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet     */
117216584225125acba18b74920b902c798dfead0328Xavier Ducrohet    private boolean getBooleanThemeValue(RenderResources resources,
117316584225125acba18b74920b902c798dfead0328Xavier Ducrohet            String name, boolean defaultValue) {
117416584225125acba18b74920b902c798dfead0328Xavier Ducrohet
117516584225125acba18b74920b902c798dfead0328Xavier Ducrohet        // get the title bar flag from the current theme.
117601b6c755dbcf24e71192dc44757e2eea2a426091Xavier Ducrohet        ResourceValue value = resources.findItemInTheme(name, true /*isFrameworkAttr*/);
117716584225125acba18b74920b902c798dfead0328Xavier Ducrohet
117816584225125acba18b74920b902c798dfead0328Xavier Ducrohet        // because it may reference something else, we resolve it.
117916584225125acba18b74920b902c798dfead0328Xavier Ducrohet        value = resources.resolveResValue(value);
1180c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
118116584225125acba18b74920b902c798dfead0328Xavier Ducrohet        // if there's no value, return the default.
118216584225125acba18b74920b902c798dfead0328Xavier Ducrohet        if (value == null || value.getValue() == null) {
118316584225125acba18b74920b902c798dfead0328Xavier Ducrohet            return defaultValue;
1184c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1185c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
118616584225125acba18b74920b902c798dfead0328Xavier Ducrohet        return XmlUtils.convertValueToBoolean(value.getValue(), defaultValue);
1187c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
1188c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1189c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
1190c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * Post process on a view hierachy that was just inflated.
1191c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * <p/>At the moment this only support TabHost: If {@link TabHost} is detected, look for the
1192c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically
1193c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * based on the content of the {@link FrameLayout}.
1194c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * @param view the root view to process.
1195c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * @param projectCallback callback to the project.
1196c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     */
1197c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private void postInflateProcess(View view, IProjectCallback projectCallback)
1198c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            throws PostInflateException {
1199c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        if (view instanceof TabHost) {
1200c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            setupTabHost((TabHost)view, projectCallback);
120131fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet        } else if (view instanceof QuickContactBadge) {
120231fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet            QuickContactBadge badge = (QuickContactBadge) view;
120331fd1cf7697ef777b41c7a6a20e37ff5d573d732Xavier Ducrohet            badge.setImageToDefault();
12042fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet        } else if (view instanceof AdapterView<?>) {
12052fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            // get the view ID.
12062fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            int id = view.getId();
12072fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12082fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            BridgeContext context = getContext();
12092fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12102fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            // get a ResourceReference from the integer ID.
12112fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            ResourceReference listRef = context.resolveId(id);
12122fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12132fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            if (listRef != null) {
12142fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                SessionParams params = getParams();
12152fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                AdapterBinding binding = params.getAdapterBindings().get(listRef);
12162fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12172fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                // if there was no adapter binding, trying to get it from the call back.
12182fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                if (binding == null) {
12192fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    binding = params.getProjectCallback().getAdapterBinding(listRef,
12202fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            context.getViewKey(view), view);
12212fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                }
12222fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12232fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                if (binding != null) {
12242fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12252fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    if (view instanceof AbsListView) {
12262fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        if ((binding.getFooterCount() > 0 || binding.getHeaderCount() > 0) &&
12272fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                view instanceof ListView) {
12282fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            ListView list = (ListView) view;
12292fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12302fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            boolean skipCallbackParser = false;
12312fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12322fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            int count = binding.getHeaderCount();
12332fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            for (int i = 0 ; i < count ; i++) {
12342fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                Pair<View, Boolean> pair = context.inflateView(
12352fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        binding.getHeaderAt(i),
12362fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        list, false /*attachToRoot*/, skipCallbackParser);
12372fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                if (pair.getFirst() != null) {
12382fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                    list.addHeaderView(pair.getFirst());
12392fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                }
12402fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12412fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                skipCallbackParser |= pair.getSecond();
12422fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            }
12432fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12442fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            count = binding.getFooterCount();
12452fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            for (int i = 0 ; i < count ; i++) {
12462fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                Pair<View, Boolean> pair = context.inflateView(
12472fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        binding.getFooterAt(i),
12482fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        list, false /*attachToRoot*/, skipCallbackParser);
12492fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                if (pair.getFirst() != null) {
12502fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                    list.addFooterView(pair.getFirst());
12512fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                }
12522fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12532fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                skipCallbackParser |= pair.getSecond();
12542fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            }
12552fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        }
12562fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet
12572fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        if (view instanceof ExpandableListView) {
12582fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            ((ExpandableListView) view).setAdapter(
12592fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                    new FakeExpandableAdapter(
12602fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                            listRef, binding, params.getProjectCallback()));
12612fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        } else {
12622fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                            ((AbsListView) view).setAdapter(
12632fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                    new FakeAdapter(
12642fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                            listRef, binding, params.getProjectCallback()));
12652fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        }
12662fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    } else if (view instanceof AbsSpinner) {
12672fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                        ((AbsSpinner) view).setAdapter(
12682fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                new FakeAdapter(
12692fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                                        listRef, binding, params.getProjectCallback()));
12702fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                    }
12712fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet                }
12722fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet            }
1273c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        } else if (view instanceof ViewGroup) {
1274c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            ViewGroup group = (ViewGroup)view;
1275c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            final int count = group.getChildCount();
1276c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            for (int c = 0 ; c < count ; c++) {
1277c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                View child = group.getChildAt(c);
1278c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                postInflateProcess(child, projectCallback);
1279c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
1280c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1281c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
1282c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1283c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
1284c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * Sets up a {@link TabHost} object.
1285c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * @param tabHost the TabHost to setup.
1286c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * @param projectCallback The project callback object to access the project R class.
1287c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * @throws PostInflateException
1288c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     */
1289c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    private void setupTabHost(TabHost tabHost, IProjectCallback projectCallback)
1290c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            throws PostInflateException {
1291c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        // look for the TabWidget, and the FrameLayout. They have their own specific names
1292c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        View v = tabHost.findViewById(android.R.id.tabs);
1293c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1294c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        if (v == null) {
1295c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            throw new PostInflateException(
1296c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    "TabHost requires a TabWidget with id \"android:id/tabs\".\n");
1297c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1298c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1299c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        if ((v instanceof TabWidget) == false) {
1300c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            throw new PostInflateException(String.format(
1301c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    "TabHost requires a TabWidget with id \"android:id/tabs\".\n" +
1302c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName()));
1303c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1304c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1305c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        v = tabHost.findViewById(android.R.id.tabcontent);
1306c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1307c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        if (v == null) {
1308c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            // TODO: see if we can fake tabs even without the FrameLayout (same below when the framelayout is empty)
1309c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            throw new PostInflateException(
1310c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    "TabHost requires a FrameLayout with id \"android:id/tabcontent\".");
1311c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1312c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1313c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        if ((v instanceof FrameLayout) == false) {
1314c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            throw new PostInflateException(String.format(
1315c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" +
1316c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet                    "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName()));
1317c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1318c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1319c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        FrameLayout content = (FrameLayout)v;
1320c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1321c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        // now process the content of the framelayout and dynamically create tabs for it.
1322c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        final int count = content.getChildCount();
1323c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1324c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        // this must be called before addTab() so that the TabHost searches its TabWidget
1325c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        // and FrameLayout.
1326c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        tabHost.setup();
1327c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1328796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye        if (count == 0) {
1329796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye            // Create a dummy child to get a single tab
1330796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye            TabSpec spec = tabHost.newTabSpec("tag").setIndicator("Tab Label",
1331796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                    tabHost.getResources().getDrawable(android.R.drawable.ic_menu_info_details))
1332796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                    .setContent(new TabHost.TabContentFactory() {
133346d43ccfd8cef75b4315828073c094cf1efb05ffXavier Ducrohet                        @Override
1334796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                        public View createTabContent(String tag) {
1335b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                            return new LinearLayout(getContext());
1336796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                        }
1337796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                    });
1338796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye            tabHost.addTab(spec);
1339796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye            return;
1340796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye        } else {
1341796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye            // for each child of the framelayout, add a new TabSpec
1342796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye            for (int i = 0 ; i < count ; i++) {
1343796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                View child = content.getChildAt(i);
1344796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                String tabSpec = String.format("tab_spec%d", i+1);
1345796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                int id = child.getId();
1346b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet                Pair<ResourceType, String> resource = projectCallback.resolveResourceId(id);
1347796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                String name;
1348796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                if (resource != null) {
1349b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet                    name = resource.getSecond();
1350796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                } else {
1351796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                    name = String.format("Tab %d", i+1); // default name if id is unresolved.
1352796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                }
1353796992a942f3508a15ee62d34d6c7ec5de045d83Tor Norbye                tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id));
1354c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            }
1355c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1356c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
1357c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
135805b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet    private List<ViewInfo> startVisitingViews(View view, int offset, boolean setExtendedInfo) {
1359bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        if (view == null) {
1360bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            return null;
1361bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        }
1362bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
1363bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        // adjust the offset to this view.
1364bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        offset += view.getTop();
1365bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
1366bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        if (view == mContentRoot) {
136705b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet            return visitAllChildren(mContentRoot, offset, setExtendedInfo);
1368bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        }
1369bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
1370bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        // otherwise, look for mContentRoot in the children
1371bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        if (view instanceof ViewGroup) {
1372bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            ViewGroup group = ((ViewGroup) view);
1373bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
1374bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            for (int i = 0; i < group.getChildCount(); i++) {
137505b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet                List<ViewInfo> list = startVisitingViews(group.getChildAt(i), offset,
137605b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet                        setExtendedInfo);
1377bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                if (list != null) {
1378bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                    return list;
1379bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet                }
1380bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet            }
1381bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        }
1382bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet
1383bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet        return null;
1384bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    }
1385c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1386c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    /**
1387c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * Visits a View and its children and generate a {@link ViewInfo} containing the
1388c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * bounds of all the views.
1389c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     * @param view the root View
1390bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * @param offset an offset for the view bounds.
139105b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet     * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
1392c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet     */
139305b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet    private ViewInfo visit(View view, int offset, boolean setExtendedInfo) {
1394c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        if (view == null) {
1395c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            return null;
1396c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1397c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1398c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        ViewInfo result = new ViewInfo(view.getClass().getName(),
1399b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet                getContext().getViewKey(view),
140016584225125acba18b74920b902c798dfead0328Xavier Ducrohet                view.getLeft(), view.getTop() + offset, view.getRight(), view.getBottom() + offset,
1401cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet                view, view.getLayoutParams());
1402c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
140305b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet        if (setExtendedInfo) {
140405b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet            MarginLayoutParams marginParams = null;
140505b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet            LayoutParams params = view.getLayoutParams();
140605b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet            if (params instanceof MarginLayoutParams) {
140705b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet                marginParams = (MarginLayoutParams) params;
140805b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet            }
140905b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet            result.setExtendedInfo(view.getBaseline(),
141005b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet                    marginParams != null ? marginParams.leftMargin : 0,
141105b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet                    marginParams != null ? marginParams.topMargin : 0,
141205b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet                    marginParams != null ? marginParams.rightMargin : 0,
141305b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet                    marginParams != null ? marginParams.bottomMargin : 0);
141405b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet        }
141505b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet
1416c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        if (view instanceof ViewGroup) {
1417c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet            ViewGroup group = ((ViewGroup) view);
141805b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet            result.setChildren(visitAllChildren(group, 0 /*offset*/, setExtendedInfo));
1419c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        }
1420c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1421c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        return result;
1422c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
1423c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
1424bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet    /**
1425bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * Visits all the children of a given ViewGroup generate a list of {@link ViewInfo}
1426bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * containing the bounds of all the views.
1427bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * @param view the root View
1428bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     * @param offset an offset for the view bounds.
142905b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet     * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
1430bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet     */
143105b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet    private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset,
143205b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet            boolean setExtendedInfo) {
14337d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet        if (viewGroup == null) {
14347d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet            return null;
14357d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet        }
14367d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet
14377d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet        List<ViewInfo> children = new ArrayList<ViewInfo>();
14387d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet        for (int i = 0; i < viewGroup.getChildCount(); i++) {
143905b7b69c6c5d418e18db644feed1ec2ca83291ccXavier Ducrohet            children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo));
14407d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet        }
14417d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet        return children;
14427d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet    }
14437d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet
14447d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet
14459eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet    private void invalidateRenderingSize() {
14469eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet        mMeasuredScreenWidth = mMeasuredScreenHeight = -1;
14479eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet    }
14489eb6d412af6859b6c0bb969c76bbfc48eec8fd4bXavier Ducrohet
1449c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    public BufferedImage getImage() {
1450c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet        return mImage;
1451c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
1452c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet
145316584225125acba18b74920b902c798dfead0328Xavier Ducrohet    public boolean isAlphaChannelImage() {
145416584225125acba18b74920b902c798dfead0328Xavier Ducrohet        return mIsAlphaChannelImage;
145516584225125acba18b74920b902c798dfead0328Xavier Ducrohet    }
145616584225125acba18b74920b902c798dfead0328Xavier Ducrohet
14577d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet    public List<ViewInfo> getViewInfos() {
14587d7016e72431ad7ee595d857a19231c69efeb6deXavier Ducrohet        return mViewInfoList;
1459c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet    }
1460cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet
146119a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public Map<String, String> getDefaultProperties(Object viewObject) {
1462b0d34f9c99cbd43e8238c5952b19d032f02dd168Xavier Ducrohet        return getContext().getDefaultPropMap(viewObject);
1463cf52390eee4c9ae792ef63af1528b2e71b33a04fXavier Ducrohet    }
1464c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
146519a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public void setScene(RenderSession session) {
146619a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet        mScene = session;
1467c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet    }
1468c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet
146919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohet    public RenderSession getSession() {
1470c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet        return mScene;
1471c14e7dd8ba15f517a5402ad802377b1d60784416Xavier Ducrohet    }
1472c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet}
1473