OLD | NEW |
(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.stack; |
| 6 |
| 7 import android.content.Context; |
| 8 import android.content.res.Resources; |
| 9 |
| 10 import com.google.android.apps.chrome.R; |
| 11 |
| 12 import org.chromium.base.annotations.SuppressFBWarnings; |
| 13 import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation; |
| 14 import org.chromium.chrome.browser.compositor.layouts.Layout.Orientation; |
| 15 import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab; |
| 16 |
| 17 /** |
| 18 * StackTab is used to keep track of a thumbnail's bitmap and position and to |
| 19 * draw itself onto the GL canvas at the desired Y Offset. |
| 20 * @VisibleForTesting |
| 21 */ |
| 22 @SuppressFBWarnings("MS_PKGPROTECT") |
| 23 public class StackTab implements ChromeAnimation.Animatable<StackTab.Property> { |
| 24 /** |
| 25 * Properties that can be animated by using a |
| 26 * {@link org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Ani
matable}. |
| 27 */ |
| 28 enum Property { |
| 29 SCALE, |
| 30 SCROLL_OFFSET, |
| 31 ALPHA, |
| 32 X_IN_STACK_INFLUENCE, |
| 33 X_IN_STACK_OFFSET, |
| 34 X_OUT_OF_STACK, |
| 35 Y_IN_STACK_INFLUENCE, |
| 36 Y_IN_STACK_OFFSET, |
| 37 Y_OUT_OF_STACK, |
| 38 DISCARD_AMOUNT |
| 39 } |
| 40 |
| 41 // Cached values from values/dimens.xml |
| 42 public static float sStackedTabVisibleSize; // stacked_tab_visible_size |
| 43 public static float sStackBufferWidth; // stack_buffer_width |
| 44 public static float sStackBufferHeight; // stack_buffer_height |
| 45 |
| 46 // Positioner selector |
| 47 private float mXInStackInfluence = 1.0f; |
| 48 private float mYInStackInfluence = 1.0f; |
| 49 |
| 50 // In stack positioner |
| 51 private float mScrollOffset = 0.0f; |
| 52 private float mXInStackOffset = 0.0f; |
| 53 private float mYInStackOffset = 0.0f; |
| 54 |
| 55 // Out of stack positioner |
| 56 private float mXOutOfStack = 0.0f; |
| 57 private float mYOutOfStack = 0.0f; |
| 58 |
| 59 // Values that get animated |
| 60 private float mAlpha = 1.0f; |
| 61 private float mScale = 1.0f; |
| 62 private float mDiscardAmount = 0.0f; // This might alter position, rotation
and alpha |
| 63 |
| 64 // Discard states |
| 65 private float mDiscardOriginX; |
| 66 private float mDiscardOriginY; |
| 67 private boolean mDiscardFromClick; |
| 68 |
| 69 // The index of the tab in the stack |
| 70 private int mIndex; |
| 71 |
| 72 // True if the tab is currently being removed (while animating). |
| 73 protected boolean mDying = false; |
| 74 |
| 75 // The visibility sorting value is used to determine the importance of the t
ab for |
| 76 // texture allocation. It is computed from the area and its position in the
stack. |
| 77 // Larger values will have more priority for acquiring texture. Negative val
ues "often" |
| 78 // means that the tab is not visible at all (but there are no guaranty and i
t's fine). |
| 79 private float mCachedVisibleArea = 0; // Intermediate value |
| 80 private float mCachedIndexDistance = 0; // Intermediate value |
| 81 private float mCacheStackVisibility = 1.0f; // Intermediate value |
| 82 private long mVisiblitySortingValue = 0; // Sorting value based on visible a
rea. |
| 83 private int mOrderSortingValue = 0; // Sorting value based on distance to se
lection. |
| 84 |
| 85 private LayoutTab mLayoutTab; |
| 86 |
| 87 /** |
| 88 * @param tab The tab this instance is supposed to draw. |
| 89 */ |
| 90 public StackTab(LayoutTab tab) { |
| 91 mLayoutTab = tab; |
| 92 } |
| 93 |
| 94 /** |
| 95 * @param index The new index in the stack layout. |
| 96 */ |
| 97 public void setNewIndex(int index) { |
| 98 mIndex = index; |
| 99 } |
| 100 |
| 101 /** |
| 102 * @return The index in the stack layout. |
| 103 */ |
| 104 public int getIndex() { |
| 105 return mIndex; |
| 106 } |
| 107 |
| 108 /** |
| 109 * @return The {@link LayoutTab} this instance is supposed to draw. |
| 110 */ |
| 111 public LayoutTab getLayoutTab() { |
| 112 return mLayoutTab; |
| 113 } |
| 114 |
| 115 /** |
| 116 * Set the {@link LayoutTab} this instance is supposed to draw. |
| 117 */ |
| 118 public void setLayoutTab(LayoutTab tab) { |
| 119 mLayoutTab = tab; |
| 120 } |
| 121 |
| 122 /** |
| 123 * @return The id of the tab, same as the id from the Tab in TabModel. |
| 124 */ |
| 125 public int getId() { |
| 126 return mLayoutTab.getId(); |
| 127 } |
| 128 |
| 129 /** |
| 130 * @param y The vertical translation to be applied after the placement in th
e stack. |
| 131 */ |
| 132 public void setYInStackOffset(float y) { |
| 133 mYInStackOffset = y; |
| 134 } |
| 135 |
| 136 /** |
| 137 * @return The vertical translation applied after the placement in the stack
. |
| 138 */ |
| 139 public float getYInStackOffset() { |
| 140 return mYInStackOffset; |
| 141 } |
| 142 |
| 143 /** |
| 144 * @param x The horizontal translation to be applied after the placement in
the stack. |
| 145 */ |
| 146 public void setXInStackOffset(float x) { |
| 147 mXInStackOffset = x; |
| 148 } |
| 149 |
| 150 /** |
| 151 * @return The horizontal translation applied after the placement in the sta
ck. |
| 152 */ |
| 153 public float getXInStackOffset() { |
| 154 return mXInStackOffset; |
| 155 } |
| 156 |
| 157 /** |
| 158 * @param y The vertical absolute position when out of stack. |
| 159 */ |
| 160 public void setYOutOfStack(float y) { |
| 161 mYOutOfStack = y; |
| 162 } |
| 163 |
| 164 /** |
| 165 * @return The vertical absolute position when out of stack. |
| 166 */ |
| 167 public float getYOutOfStack() { |
| 168 return mYOutOfStack; |
| 169 } |
| 170 |
| 171 /** |
| 172 * @param x The horizontal absolute position when out of stack. |
| 173 */ |
| 174 public void setXOutOfStack(float x) { |
| 175 mXOutOfStack = x; |
| 176 } |
| 177 |
| 178 /** |
| 179 * @return The horizontal absolute position when out of stack. |
| 180 */ |
| 181 public float getXOutOfStack() { |
| 182 return mXOutOfStack; |
| 183 } |
| 184 |
| 185 /** |
| 186 * Set the transparency value for all of the tab (the contents, |
| 187 * border, etc...). For components that allow specifying |
| 188 * their own alpha values, it will use the min of these two fields. |
| 189 * |
| 190 * @param f The transparency value for the tab. |
| 191 */ |
| 192 public void setAlpha(float f) { |
| 193 mAlpha = f; |
| 194 } |
| 195 |
| 196 /** |
| 197 * @return The transparency value for all of the tab components. |
| 198 */ |
| 199 public float getAlpha() { |
| 200 return mAlpha; |
| 201 } |
| 202 |
| 203 /** |
| 204 * @param xInStackInfluence The horizontal blend value between instack |
| 205 * and out of stack pacement [0 .. 1]. |
| 206 */ |
| 207 public void setXInStackInfluence(float xInStackInfluence) { |
| 208 mXInStackInfluence = xInStackInfluence; |
| 209 } |
| 210 |
| 211 /** |
| 212 * @return The horizontal blend value between instack and out of stack pacem
ent [0 .. 1]. |
| 213 */ |
| 214 public float getXInStackInfluence() { |
| 215 return mXInStackInfluence; |
| 216 } |
| 217 |
| 218 /** |
| 219 * @param yInStackInfluence The vertical blend value between instack |
| 220 * and out of stack pacement [0 .. 1]. |
| 221 */ |
| 222 public void setYInStackInfluence(float yInStackInfluence) { |
| 223 mYInStackInfluence = yInStackInfluence; |
| 224 } |
| 225 |
| 226 /** |
| 227 * @return The verical blend value between instack and out of stack pacement
[0 .. 1]. |
| 228 */ |
| 229 public float getYInStackInfluence() { |
| 230 return mYInStackInfluence; |
| 231 } |
| 232 |
| 233 /** |
| 234 * @param scale The scale to apply to the tab, compared to the parent. |
| 235 */ |
| 236 public void setScale(float scale) { |
| 237 mScale = scale; |
| 238 } |
| 239 |
| 240 /** |
| 241 * @return The scale to apply to the tab, compared to the parent. |
| 242 */ |
| 243 public float getScale() { |
| 244 return mScale; |
| 245 } |
| 246 |
| 247 /** |
| 248 * @param offset The offset of the tab along the scrolling direction in scro
ll space. |
| 249 */ |
| 250 public void setScrollOffset(float offset) { |
| 251 mScrollOffset = offset; |
| 252 } |
| 253 |
| 254 /** |
| 255 * @return The offset of the tab along the scrolling direction in scroll spa
ce. |
| 256 */ |
| 257 public float getScrollOffset() { |
| 258 return mScrollOffset; |
| 259 } |
| 260 |
| 261 /** |
| 262 * @param amount The amount of discard displacement. 0 is no discard. Negati
ve is discard |
| 263 * on the left. Positive is discard on the right. |
| 264 */ |
| 265 public void setDiscardAmount(float amount) { |
| 266 mDiscardAmount = amount; |
| 267 } |
| 268 |
| 269 /** |
| 270 * @param deltaAmount The amount of delta discard to be added to the current
discard amount. |
| 271 */ |
| 272 public void addToDiscardAmount(float deltaAmount) { |
| 273 mDiscardAmount += deltaAmount; |
| 274 } |
| 275 |
| 276 /** |
| 277 * @return The amount of discard displacement. 0 is no discard. Negative is
discard |
| 278 * on the left. Positive is discard on the right. |
| 279 */ |
| 280 public float getDiscardAmount() { |
| 281 return mDiscardAmount; |
| 282 } |
| 283 |
| 284 /** |
| 285 * @param x The x coordinate in tab space of where the discard transforms sh
ould originate. |
| 286 */ |
| 287 public void setDiscardOriginX(float x) { |
| 288 mDiscardOriginX = x; |
| 289 } |
| 290 |
| 291 /** |
| 292 * @param y The y coordinate in tab space of where the discard transforms sh
ould originate. |
| 293 */ |
| 294 public void setDiscardOriginY(float y) { |
| 295 mDiscardOriginY = y; |
| 296 } |
| 297 |
| 298 /** |
| 299 * @return The x coordinate in tab space of where the discard transforms sho
uld originate. |
| 300 */ |
| 301 public float getDiscardOriginX() { |
| 302 return mDiscardOriginX; |
| 303 } |
| 304 |
| 305 /** |
| 306 * @return The y coordinate in tab space of where the discard transforms sho
uld originate. |
| 307 */ |
| 308 public float getDiscardOriginY() { |
| 309 return mDiscardOriginY; |
| 310 } |
| 311 |
| 312 /** |
| 313 * @param fromClick Whether or not this discard was from a click event. |
| 314 */ |
| 315 public void setDiscardFromClick(boolean fromClick) { |
| 316 mDiscardFromClick = fromClick; |
| 317 } |
| 318 |
| 319 /** |
| 320 * @return Whether or not this discard was from a click event. |
| 321 */ |
| 322 public boolean getDiscardFromClick() { |
| 323 return mDiscardFromClick; |
| 324 } |
| 325 |
| 326 /** |
| 327 * @param dying True if the Tab/ContentView will be destroyed, and we are st
ill animating its |
| 328 * visible representation. |
| 329 */ |
| 330 public void setDying(boolean dying) { |
| 331 mDying = dying; |
| 332 } |
| 333 |
| 334 /** |
| 335 * @return True if the Tab/ContentView is destroyed, but we are still animat
ing its |
| 336 * visible representation. |
| 337 */ |
| 338 public boolean isDying() { |
| 339 return mDying; |
| 340 } |
| 341 |
| 342 /** |
| 343 * The scroll space does not map linearly to the screen so it creates a nice
slow down |
| 344 * effect at the top of the screen while scrolling. |
| 345 * Warps x so it matches y(x) = x - warpSize on the positive side and 0 on t
he negative side |
| 346 * with a smooth transition between [0, 2 * warpSize]. |
| 347 * @see #screenToScroll(float, float) |
| 348 * |
| 349 * [-oo, 0] -> 0 |
| 350 * [0, 2 * warpSize] -> warpSize * ((x-warpSize) / 2 * warpSize + 0.5) ^ 2. |
| 351 * [2 * warpSize, +oo] -> x |
| 352 * @param x The offset in scroll space. |
| 353 * @param warpSize The size in scroll space of the slow down effect. |
| 354 * @return The offset on screen corresponding to the scroll space of
fset. |
| 355 */ |
| 356 public static float scrollToScreen(float x, float warpSize) { |
| 357 if (x <= 0) return 0; |
| 358 if (x >= 2 * warpSize) return x - warpSize; |
| 359 x = (x - warpSize) / (2.0f * warpSize) + 0.5f; |
| 360 return x * x * warpSize; |
| 361 } |
| 362 |
| 363 /** |
| 364 * Unwarps x so it matches the above warp function. |
| 365 * @see #scrollToScreen(float, float) |
| 366 * |
| 367 * [-oo, 0] -> -warpSize |
| 368 * [0, warpSize] -> 2 * warpSize * sqrt(x / warpSize). |
| 369 * [warpSize, +oo] -> x + warpSize |
| 370 * @param x The screen space offset. |
| 371 * @param warpSize The size in scroll space of the slow down effect. |
| 372 * @return The offset in scroll space corresponding to the offset on
screen. |
| 373 */ |
| 374 public static float screenToScroll(float x, float warpSize) { |
| 375 if (x <= 0) return 0; |
| 376 if (x >= warpSize) return x + warpSize; |
| 377 return (float) Math.sqrt(x * warpSize) * 2; |
| 378 } |
| 379 |
| 380 /** |
| 381 * @param orientation The orientation to choose to get the size. |
| 382 * @return The size of the content along the provided orientation
. |
| 383 */ |
| 384 public float getSizeInScrollDirection(int orientation) { |
| 385 if (orientation == Orientation.PORTRAIT) { |
| 386 return mLayoutTab.getScaledContentHeight(); |
| 387 } else { |
| 388 return mLayoutTab.getScaledContentWidth(); |
| 389 } |
| 390 } |
| 391 |
| 392 /** |
| 393 * Helper function that gather the static constants from values/dimens.xml. |
| 394 * @param context The Android Context. |
| 395 */ |
| 396 public static void resetDimensionConstants(Context context) { |
| 397 Resources res = context.getResources(); |
| 398 final float pxToDp = 1.0f / res.getDisplayMetrics().density; |
| 399 sStackedTabVisibleSize = |
| 400 res.getDimensionPixelOffset(R.dimen.stacked_tab_visible_size) *
pxToDp; |
| 401 sStackBufferWidth = res.getDimensionPixelOffset(R.dimen.stack_buffer_wid
th) * pxToDp; |
| 402 sStackBufferHeight = res.getDimensionPixelOffset(R.dimen.stack_buffer_he
ight) * pxToDp; |
| 403 } |
| 404 |
| 405 /** |
| 406 * Reset the offset to factory default. |
| 407 */ |
| 408 public void resetOffset() { |
| 409 mXInStackInfluence = 1.0f; |
| 410 mYInStackInfluence = 1.0f; |
| 411 mScrollOffset = 0.0f; |
| 412 mXInStackOffset = 0.0f; |
| 413 mYInStackOffset = 0.0f; |
| 414 mXOutOfStack = 0.0f; |
| 415 mYOutOfStack = 0.0f; |
| 416 mDiscardOriginX = 0.f; |
| 417 mDiscardOriginY = 0.f; |
| 418 mDiscardFromClick = false; |
| 419 } |
| 420 |
| 421 /** |
| 422 * Updates the cached visible area value to be used to sort tabs by visibili
ty. |
| 423 * @param referenceIndex The index that has the highest priority. |
| 424 */ |
| 425 public void updateVisiblityValue(int referenceIndex) { |
| 426 mCachedVisibleArea = mLayoutTab.computeVisibleArea(); |
| 427 mCachedIndexDistance = Math.abs(mIndex - referenceIndex); |
| 428 mOrderSortingValue = computeOrderSortingValue(mCachedIndexDistance, mCac
heStackVisibility); |
| 429 mVisiblitySortingValue = computeVisibilitySortingValue( |
| 430 mCachedVisibleArea, mOrderSortingValue, mCacheStackVisibility); |
| 431 } |
| 432 |
| 433 /** |
| 434 * Updates the cached visible area value to be used to sort tabs by visibili
ty. |
| 435 * @param stackVisibility Multiplier that represents how much the stack fi
lls the screen. |
| 436 */ |
| 437 public void updateStackVisiblityValue(float stackVisibility) { |
| 438 mCacheStackVisibility = stackVisibility; |
| 439 mOrderSortingValue = computeOrderSortingValue(mCachedIndexDistance, mCac
heStackVisibility); |
| 440 mVisiblitySortingValue = computeVisibilitySortingValue( |
| 441 mCachedVisibleArea, mOrderSortingValue, mCacheStackVisibility); |
| 442 } |
| 443 |
| 444 /** |
| 445 * Computes the visibility sorting value based on the tab visible area, its
distance to the |
| 446 * central index and the overall visibility of the stack. |
| 447 * The '-index' index factor need to be smaller for stack that have small vi
sibility. |
| 448 * Multiplying by a small stackVisibility makes it bigger (because it is neg
ative), hence the |
| 449 * division. To avoid dividing by 0 it need to be offset a bit. 0.1f is the
'a bit' part of |
| 450 * the explanation. |
| 451 */ |
| 452 private static long computeVisibilitySortingValue( |
| 453 float area, float orderSortingValue, float stackVisibility) { |
| 454 return (long) (area * stackVisibility - orderSortingValue); |
| 455 } |
| 456 |
| 457 /** |
| 458 * @return The cached visible sorting value. Call updateCachedVisibleArea to
update it. |
| 459 */ |
| 460 public long getVisiblitySortingValue() { |
| 461 return mVisiblitySortingValue; |
| 462 } |
| 463 |
| 464 /** |
| 465 * Computes the ordering value only based on the distance of the tab to the
center one. |
| 466 * Low values have higher priority. |
| 467 */ |
| 468 private static int computeOrderSortingValue(float indexDistance, float stack
Visibility) { |
| 469 return (int) ((indexDistance + 1) / (0.1f + 0.9f * stackVisibility)); |
| 470 } |
| 471 |
| 472 /** |
| 473 * @return The cached order sorting value. Used to sort based on the tab ord
ering rather than |
| 474 * visible area. |
| 475 */ |
| 476 public int getOrderSortingValue() { |
| 477 return mOrderSortingValue; |
| 478 } |
| 479 |
| 480 /** |
| 481 * Callback for |
| 482 * {@link org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Ani
matable} |
| 483 * |
| 484 * @param prop The property to set |
| 485 * @param val The value to set it to |
| 486 */ |
| 487 @Override |
| 488 public void setProperty(Property prop, float val) { |
| 489 switch (prop) { |
| 490 case SCALE: |
| 491 setScale(val); |
| 492 break; |
| 493 case SCROLL_OFFSET: |
| 494 setScrollOffset(val); |
| 495 break; |
| 496 case ALPHA: |
| 497 setAlpha(val); |
| 498 break; |
| 499 case X_IN_STACK_INFLUENCE: |
| 500 setXInStackInfluence(val); |
| 501 break; |
| 502 case X_IN_STACK_OFFSET: |
| 503 setXInStackOffset(val); |
| 504 break; |
| 505 case X_OUT_OF_STACK: |
| 506 setXOutOfStack(val); |
| 507 break; |
| 508 case Y_IN_STACK_INFLUENCE: |
| 509 setYInStackInfluence(val); |
| 510 break; |
| 511 case Y_IN_STACK_OFFSET: |
| 512 setYInStackOffset(val); |
| 513 break; |
| 514 case Y_OUT_OF_STACK: |
| 515 setYOutOfStack(val); |
| 516 break; |
| 517 case DISCARD_AMOUNT: |
| 518 setDiscardAmount(val); |
| 519 break; |
| 520 } |
| 521 } |
| 522 } |
OLD | NEW |