Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(463)

Side by Side Diff: chrome/android/java_staging/src/org/chromium/chrome/browser/compositor/layouts/phone/SimpleAnimationLayout.java

Issue 1141283003: Upstream oodles of Chrome for Android code into Chromium. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: final patch? Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.chrome.browser.compositor.layouts.phone;
6
7 import android.content.Context;
8 import android.graphics.Rect;
9 import android.view.animation.Interpolator;
10
11 import org.chromium.chrome.browser.compositor.LayerTitleCache;
12 import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Animatable ;
13 import org.chromium.chrome.browser.compositor.layouts.Layout;
14 import org.chromium.chrome.browser.compositor.layouts.LayoutRenderHost;
15 import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost;
16 import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
17 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
18 import org.chromium.chrome.browser.compositor.layouts.eventfilter.EventFilter;
19 import org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack;
20 import org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation ;
21 import org.chromium.chrome.browser.compositor.scene_layer.SceneLayer;
22 import org.chromium.chrome.browser.compositor.scene_layer.TabListSceneLayer;
23 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
24 import org.chromium.chrome.browser.tabmodel.TabModel;
25 import org.chromium.ui.interpolators.BakedBezierInterpolator;
26 import org.chromium.ui.resources.ResourceManager;
27
28 import java.util.Arrays;
29 import java.util.LinkedList;
30
31 /**
32 * This class handles animating the opening of new tabs.
33 */
34 public class SimpleAnimationLayout
35 extends Layout implements Animatable<SimpleAnimationLayout.Property> {
36 /**
37 * Animation properties
38 */
39 public enum Property { DISCARD_AMOUNT }
40
41 /** Duration of the first step of the background animation: zooming out, rot ating in */
42 private static final long BACKGROUND_STEP1_DURATION = 300;
43 /** Duration of the second step of the background animation: pause */
44 private static final long BACKGROUND_STEP2_DURATION = 150;
45 /** Duration of the third step of the background animation: zooming in, slid ing out */
46 private static final long BACKGROUND_STEP3_DURATION = 300;
47 /** Start time offset of the third step of the background animation */
48 private static final long BACKGROUND_STEP3_START =
49 BACKGROUND_STEP1_DURATION + BACKGROUND_STEP2_DURATION;
50 /** Percentage of the screen covered by the new tab */
51 private static final float BACKGROUND_COVER_PCTG = 0.5f;
52
53 /** The time duration of the animation */
54 protected static final int FOREGROUND_ANIMATION_DURATION = 300;
55
56 /** The time duration of the animation */
57 protected static final int TAB_CLOSED_ANIMATION_DURATION = 250;
58
59 /**
60 * A cached {@link LayoutTab} representation of the currently closing tab. I f it's not
61 * null, it means tabClosing() has been called to start animation setup but
62 * tabClosed() has not yet been called to finish animation startup
63 */
64 private LayoutTab mClosedTab;
65
66 private LayoutTab mAnimatedTab;
67 private final TabListSceneLayer mSceneLayer;
68
69 /**
70 * Creates an instance of the {@link SimpleAnimationLayout}.
71 * @param context The current Android's context.
72 * @param updateHost The {@link LayoutUpdateHost} view for this layout.
73 * @param renderHost The {@link LayoutRenderHost} view for this layout.
74 * @param eventFilter The {@link EventFilter} that is needed for this view.
75 */
76 public SimpleAnimationLayout(Context context, LayoutUpdateHost updateHost,
77 LayoutRenderHost renderHost, EventFilter eventFilter) {
78 super(context, updateHost, renderHost, eventFilter);
79 mSceneLayer = new TabListSceneLayer();
80 }
81
82 @Override
83 public int getSizingFlags() {
84 return SizingFlags.HELPER_SUPPORTS_FULLSCREEN;
85 }
86
87 @Override
88 public void show(long time, boolean animate) {
89 super.show(time, animate);
90 reset();
91 }
92
93 @Override
94 public boolean handlesTabCreating() {
95 return true;
96 }
97
98 @Override
99 public boolean handlesTabClosing() {
100 return true;
101 }
102
103 @Override
104 protected void updateLayout(long time, long dt) {
105 super.updateLayout(time, dt);
106 if (mLayoutTabs == null) return;
107 boolean needUpdate = false;
108 for (int i = mLayoutTabs.length - 1; i >= 0; i--) {
109 needUpdate = mLayoutTabs[i].updateSnap(dt) || needUpdate;
110 }
111 if (needUpdate) requestUpdate();
112 }
113
114 @Override
115 public void onTabCreating(int sourceTabId) {
116 super.onTabCreating(sourceTabId);
117 reset();
118
119 // Make sure any currently running animations can't influence tab if we are reusing it.
120 forceAnimationToFinish();
121
122 ensureSourceTabCreated(sourceTabId);
123 }
124
125 private void ensureSourceTabCreated(int sourceTabId) {
126 if (mLayoutTabs != null && mLayoutTabs.length == 1
127 && mLayoutTabs[0].getId() == sourceTabId) {
128 return;
129 }
130 // Just draw the source tab on the screen.
131 TabModel sourceModel = mTabModelSelector.getModelForTabId(sourceTabId);
132 if (sourceModel == null) return;
133 LayoutTab sourceLayoutTab =
134 createLayoutTab(sourceTabId, sourceModel.isIncognito(), NO_CLOSE _BUTTON, NO_TITLE);
135 sourceLayoutTab.setBorderAlpha(0.0f);
136
137 mLayoutTabs = new LayoutTab[] {sourceLayoutTab};
138 updateCacheVisibleIds(new LinkedList<Integer>(Arrays.asList(sourceTabId) ));
139 }
140
141 @Override
142 public void onTabCreated(long time, int id, int index, int sourceId, boolean newIsIncognito,
143 boolean background, float originX, float originY) {
144 super.onTabCreated(time, id, index, sourceId, newIsIncognito, background , originX, originY);
145 ensureSourceTabCreated(sourceId);
146 if (background && mLayoutTabs != null && mLayoutTabs.length > 0) {
147 tabCreatedInBackground(id, sourceId, newIsIncognito, originX, origin Y);
148 } else {
149 tabCreatedInForeground(id, sourceId, newIsIncognito, originX, origin Y);
150 }
151 }
152
153 /**
154 * Animate opening a tab in the foreground.
155 *
156 * @param id The id of the new tab to animate.
157 * @param sourceId The id of the tab that spawned this new tab.
158 * @param newIsIncognito true if the new tab is an incognito tab.
159 * @param originX The X coordinate of the last touch down event that spawned this tab.
160 * @param originY The Y coordinate of the last touch down event that spawned this tab.
161 */
162 private void tabCreatedInForeground(
163 int id, int sourceId, boolean newIsIncognito, float originX, float o riginY) {
164 LayoutTab newLayoutTab = createLayoutTab(id, newIsIncognito, NO_CLOSE_BU TTON, NO_TITLE);
165 if (mLayoutTabs == null || mLayoutTabs.length == 0) {
166 mLayoutTabs = new LayoutTab[] {newLayoutTab};
167 } else {
168 mLayoutTabs = new LayoutTab[] {mLayoutTabs[0], newLayoutTab};
169 }
170 updateCacheVisibleIds(new LinkedList<Integer>(Arrays.asList(id, sourceId )));
171
172 newLayoutTab.setBorderAlpha(0.0f);
173 newLayoutTab.setStaticToViewBlend(1.f);
174
175 forceAnimationToFinish();
176
177 Interpolator interpolator = BakedBezierInterpolator.TRANSFORM_CURVE;
178 addToAnimation(newLayoutTab, LayoutTab.Property.SCALE, 0.f, 1.f,
179 FOREGROUND_ANIMATION_DURATION, 0, false, interpolator);
180 addToAnimation(newLayoutTab, LayoutTab.Property.ALPHA, 0.f, 1.f,
181 FOREGROUND_ANIMATION_DURATION, 0, false, interpolator);
182 addToAnimation(newLayoutTab, LayoutTab.Property.X, originX, 0.f,
183 FOREGROUND_ANIMATION_DURATION, 0, false, interpolator);
184 addToAnimation(newLayoutTab, LayoutTab.Property.Y, originY, 0.f,
185 FOREGROUND_ANIMATION_DURATION, 0, false, interpolator);
186
187 mTabModelSelector.selectModel(newIsIncognito);
188 startHiding(id, false);
189 }
190
191 /**
192 * Animate opening a tab in the background.
193 *
194 * @param id The id of the new tab to animate.
195 * @param sourceId The id of the tab that spawned this new tab.
196 * @param newIsIncognito true if the new tab is an incognito tab.
197 * @param originX The X screen coordinate in dp of the last touch dow n event that spawned
198 * this tab.
199 * @param originY The Y screen coordinate in dp of the last touch dow n event that spawned
200 * this tab.
201 */
202 private void tabCreatedInBackground(
203 int id, int sourceId, boolean newIsIncognito, float originX, float o riginY) {
204 LayoutTab newLayoutTab = createLayoutTab(id, newIsIncognito, NO_CLOSE_BU TTON, NEED_TITLE);
205 // mLayoutTabs should already have the source tab from tabCreating().
206 assert mLayoutTabs.length == 1;
207 LayoutTab sourceLayoutTab = mLayoutTabs[0];
208 mLayoutTabs = new LayoutTab[] {sourceLayoutTab, newLayoutTab};
209 updateCacheVisibleIds(new LinkedList<Integer>(Arrays.asList(id, sourceId )));
210
211 forceAnimationToFinish();
212
213 newLayoutTab.setBorderAlpha(0.0f);
214 final float scale = StackAnimation.SCALE_AMOUNT;
215 final float margin = Math.min(getWidth(), getHeight()) * (1.0f - scale) / 2.0f;
216
217 // Step 1: zoom out the source tab and bring in the new tab
218 addToAnimation(sourceLayoutTab, LayoutTab.Property.SCALE, 1.0f, scale,
219 BACKGROUND_STEP1_DURATION, 0, false, BakedBezierInterpolator.TRA NSFORM_CURVE);
220 addToAnimation(sourceLayoutTab, LayoutTab.Property.X, 0.0f, margin,
221 BACKGROUND_STEP1_DURATION, 0, false, BakedBezierInterpolator.TRA NSFORM_CURVE);
222 addToAnimation(sourceLayoutTab, LayoutTab.Property.Y, 0.0f, margin,
223 BACKGROUND_STEP1_DURATION, 0, false, BakedBezierInterpolator.TRA NSFORM_CURVE);
224 addToAnimation(sourceLayoutTab, LayoutTab.Property.BORDER_SCALE, 1.0f / scale, 1.0f,
225 BACKGROUND_STEP1_DURATION, 0, false, BakedBezierInterpolator.TRA NSFORM_CURVE);
226 addToAnimation(sourceLayoutTab, LayoutTab.Property.BORDER_ALPHA, 0.0f, 1 .0f,
227 BACKGROUND_STEP1_DURATION, 0, false, BakedBezierInterpolator.TRA NSFORM_CURVE);
228
229 float pauseX = margin;
230 float pauseY = margin;
231 if (getOrientation() == Orientation.PORTRAIT) {
232 pauseY = BACKGROUND_COVER_PCTG * getHeight();
233 } else {
234 pauseX = BACKGROUND_COVER_PCTG * getWidth();
235 }
236
237 addToAnimation(newLayoutTab, LayoutTab.Property.ALPHA, 0.0f, 1.0f,
238 BACKGROUND_STEP1_DURATION / 2, 0, false, BakedBezierInterpolator .FADE_IN_CURVE);
239 addToAnimation(newLayoutTab, LayoutTab.Property.SCALE, 0.f, scale,
240 BACKGROUND_STEP1_DURATION, 0, false, BakedBezierInterpolator.FAD E_IN_CURVE);
241 addToAnimation(newLayoutTab, LayoutTab.Property.X, originX, pauseX,
242 BACKGROUND_STEP1_DURATION, 0, false, BakedBezierInterpolator.FAD E_IN_CURVE);
243 addToAnimation(newLayoutTab, LayoutTab.Property.Y, originY, pauseY,
244 BACKGROUND_STEP1_DURATION, 0, false, BakedBezierInterpolator.FAD E_IN_CURVE);
245
246 // step 2: pause and admire the nice tabs
247
248 // step 3: zoom in the source tab and slide down the new tab
249 addToAnimation(sourceLayoutTab, LayoutTab.Property.SCALE, scale, 1.0f,
250 BACKGROUND_STEP3_DURATION, BACKGROUND_STEP3_START, true,
251 BakedBezierInterpolator.TRANSFORM_CURVE);
252 addToAnimation(sourceLayoutTab, LayoutTab.Property.X, margin, 0.0f,
253 BACKGROUND_STEP3_DURATION, BACKGROUND_STEP3_START, true,
254 BakedBezierInterpolator.TRANSFORM_CURVE);
255 addToAnimation(sourceLayoutTab, LayoutTab.Property.Y, margin, 0.0f,
256 BACKGROUND_STEP3_DURATION, BACKGROUND_STEP3_START, true,
257 BakedBezierInterpolator.TRANSFORM_CURVE);
258 addToAnimation(sourceLayoutTab, LayoutTab.Property.BORDER_SCALE, 1.0f, 1 .0f / scale,
259 BACKGROUND_STEP3_DURATION, BACKGROUND_STEP3_START, true,
260 BakedBezierInterpolator.TRANSFORM_CURVE);
261 addToAnimation(sourceLayoutTab, LayoutTab.Property.BORDER_ALPHA, 1.0f, 0 .0f,
262 BACKGROUND_STEP3_DURATION, BACKGROUND_STEP3_START, true,
263 BakedBezierInterpolator.TRANSFORM_CURVE);
264
265 addToAnimation(newLayoutTab, LayoutTab.Property.ALPHA, 1.f, 0.f, BACKGRO UND_STEP3_DURATION,
266 BACKGROUND_STEP3_START, true, BakedBezierInterpolator.FADE_OUT_C URVE);
267 if (getOrientation() == Orientation.PORTRAIT) {
268 addToAnimation(newLayoutTab, LayoutTab.Property.Y, pauseY, getHeight (),
269 BACKGROUND_STEP3_DURATION, BACKGROUND_STEP3_START, true,
270 BakedBezierInterpolator.FADE_OUT_CURVE);
271 } else {
272 addToAnimation(newLayoutTab, LayoutTab.Property.X, pauseX, getWidth( ),
273 BACKGROUND_STEP3_DURATION, BACKGROUND_STEP3_START, true,
274 BakedBezierInterpolator.FADE_OUT_CURVE);
275 }
276
277 mTabModelSelector.selectModel(newIsIncognito);
278 startHiding(sourceId, false);
279 }
280
281 /**
282 * Set up for the tab closing animation
283 */
284 @Override
285 public void onTabClosing(long time, int id) {
286 reset();
287
288 // Make sure any currently running animations can't influence tab if we are reusing it.
289 forceAnimationToFinish();
290
291 // Create the {@link LayoutTab} for the tab before it is destroyed.
292 TabModel model = mTabModelSelector.getModelForTabId(id);
293 if (model != null) {
294 mClosedTab = createLayoutTab(id, model.isIncognito(), NO_CLOSE_BUTTO N, NO_TITLE);
295 mClosedTab.setBorderAlpha(0.0f);
296 mLayoutTabs = new LayoutTab[] {mClosedTab};
297 updateCacheVisibleIds(new LinkedList<Integer>(Arrays.asList(id)));
298 } else {
299 mLayoutTabs = null;
300 mClosedTab = null;
301 }
302 // Only close the id at the end when we are done querying the model.
303 super.onTabClosing(time, id);
304 }
305
306 /**
307 * Animate the closing of a tab
308 */
309 @Override
310 public void onTabClosed(long time, int id, int nextId, boolean incognito) {
311 super.onTabClosed(time, id, nextId, incognito);
312
313 if (mClosedTab != null) {
314 TabModel nextModel = mTabModelSelector.getModelForTabId(nextId);
315 if (nextModel != null) {
316 LayoutTab nextLayoutTab =
317 createLayoutTab(nextId, nextModel.isIncognito(), NO_CLOS E_BUTTON, NO_TITLE);
318 nextLayoutTab.setDrawDecoration(false);
319
320 mLayoutTabs = new LayoutTab[] {nextLayoutTab, mClosedTab};
321 updateCacheVisibleIds(
322 new LinkedList<Integer>(Arrays.asList(nextId, mClosedTab .getId())));
323 } else {
324 mLayoutTabs = new LayoutTab[] {mClosedTab};
325 }
326
327 forceAnimationToFinish();
328 mAnimatedTab = mClosedTab;
329 addToAnimation(this, Property.DISCARD_AMOUNT, 0, getDiscardRange(),
330 TAB_CLOSED_ANIMATION_DURATION, 0, false,
331 BakedBezierInterpolator.FADE_OUT_CURVE);
332
333 mClosedTab = null;
334 if (nextModel != null) {
335 mTabModelSelector.selectModel(nextModel.isIncognito());
336 }
337 }
338 startHiding(nextId, false);
339 }
340
341 /**
342 * Updates the position, scale, rotation and alpha values of mAnimatedTab.
343 *
344 * @param discard The value that specify how far along are we in the discard animation. 0 is
345 * filling the screen. Valid values are [-range .. range] whe re range is
346 * computed by {@link SimpleAnimationLayout#getDiscardRange() }.
347 */
348 private void setDiscardAmount(float discard) {
349 if (mAnimatedTab != null) {
350 final float range = getDiscardRange();
351 final float scale = Stack.computeDiscardScale(discard, range, true);
352
353 final float deltaX = mAnimatedTab.getOriginalContentWidth();
354 final float deltaY = mAnimatedTab.getOriginalContentHeight() / 2.f;
355 mAnimatedTab.setX(deltaX * (1.f - scale));
356 mAnimatedTab.setY(deltaY * (1.f - scale));
357 mAnimatedTab.setScale(scale);
358 mAnimatedTab.setBorderScale(scale);
359 mAnimatedTab.setAlpha(Stack.computeDiscardAlpha(discard, range));
360 }
361 }
362
363 /**
364 * @return The range of the discard amount.
365 */
366 private float getDiscardRange() {
367 return Math.min(getWidth(), getHeight()) * Stack.DISCARD_RANGE_SCREEN;
368 }
369
370 @Override
371 public boolean onUpdateAnimation(long time, boolean jumpToEnd) {
372 return super.onUpdateAnimation(time, jumpToEnd) && mClosedTab == null;
373 }
374
375 /**
376 * Resets the internal state.
377 */
378 private void reset() {
379 mLayoutTabs = null;
380 mAnimatedTab = null;
381 mClosedTab = null;
382 }
383
384 /**
385 * Sets a property for an animation.
386 * @param prop The property to update
387 * @param value New value of the property
388 */
389 @Override
390 public void setProperty(Property prop, float value) {
391 switch (prop) {
392 case DISCARD_AMOUNT:
393 setDiscardAmount(value);
394 break;
395 default:
396 }
397 }
398
399 @Override
400 protected SceneLayer getSceneLayer() {
401 return mSceneLayer;
402 }
403
404 @Override
405 protected void updateSceneLayer(Rect viewport, Rect contentViewport,
406 LayerTitleCache layerTitleCache, TabContentManager tabContentManager ,
407 ResourceManager resourceManager, ChromeFullscreenManager fullscreenM anager) {
408 super.updateSceneLayer(viewport, contentViewport, layerTitleCache, tabCo ntentManager,
409 resourceManager, fullscreenManager);
410 assert mSceneLayer != null;
411 mSceneLayer.pushLayers(getContext(), viewport, contentViewport, this, la yerTitleCache,
412 tabContentManager, resourceManager);
413 }
414 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698