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