Selim Cinek | 67b2260 | 2014-03-10 15:40:16 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2014 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License |
| 15 | */ |
| 16 | |
| 17 | package com.android.systemui.statusbar.stack; |
| 18 | |
| 19 | import java.util.ArrayList; |
| 20 | |
| 21 | /** |
| 22 | * A Functor which interpolates the stack distance linearly based on base values. |
| 23 | * The base values are based on an interpolation between a linear function and a |
| 24 | * quadratic function |
| 25 | */ |
| 26 | public class PiecewiseLinearIndentationFunctor extends StackIndentationFunctor { |
| 27 | |
| 28 | private final ArrayList<Float> mBaseValues; |
| 29 | private final float mLinearPart; |
| 30 | |
| 31 | /** |
| 32 | * @param maxItemsInStack The maximum number of items which should be visible at the same time, |
| 33 | * i.e the function returns totalTransitionDistance for the element with |
| 34 | * index maxItemsInStack |
| 35 | * @param peekSize The visual appearance of this is how far the cards in the stack peek |
| 36 | * out below the top card and it is measured in real pixels. |
| 37 | * Note that the visual appearance does not necessarily always correspond to |
| 38 | * the actual visual distance below the top card but is a maximum, |
| 39 | * achieved when the next card just starts transitioning into the stack and |
| 40 | * the stack is full. |
| 41 | * If totalTransitionDistance is equal to this, we directly start at the peek, |
| 42 | * otherwise the first element transitions between 0 and |
| 43 | * totalTransitionDistance - peekSize. |
| 44 | * Visualization: |
| 45 | * --------------------------------------------------- --- |
| 46 | * | | | |
| 47 | * | FIRST ITEM | | <- totalTransitionDistance |
| 48 | * | | | |
| 49 | * |---------------------------------------------------| | --- |
| 50 | * |__________________SECOND ITEM______________________| | | <- peekSize |
| 51 | * |===================================================| _|_ _|_ |
| 52 | * |
| 53 | * @param totalTransitionDistance The total transition distance an element has to go through |
| 54 | * @param linearPart The interpolation factor between the linear and the quadratic amount taken. |
| 55 | * This factor must be somewhere in [0 , 1] |
| 56 | */ |
| 57 | PiecewiseLinearIndentationFunctor(int maxItemsInStack, |
| 58 | int peekSize, |
| 59 | int totalTransitionDistance, |
| 60 | float linearPart) { |
| 61 | super(maxItemsInStack, peekSize, totalTransitionDistance); |
| 62 | mBaseValues = new ArrayList<Float>(maxItemsInStack+1); |
| 63 | initBaseValues(); |
| 64 | mLinearPart = linearPart; |
| 65 | } |
| 66 | |
| 67 | private void initBaseValues() { |
| 68 | int sumOfSquares = getSumOfSquares(mMaxItemsInStack-1); |
| 69 | int totalWeight = 0; |
| 70 | mBaseValues.add(0.0f); |
| 71 | for (int i = 0; i < mMaxItemsInStack - 1; i++) { |
| 72 | totalWeight += (mMaxItemsInStack - i - 1) * (mMaxItemsInStack - i - 1); |
| 73 | mBaseValues.add((float) totalWeight / sumOfSquares); |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | /** |
| 78 | * Get the sum of squares up to and including n, i.e sum(i * i, 1, n) |
| 79 | * |
| 80 | * @param n the maximum square to include |
| 81 | * @return |
| 82 | */ |
| 83 | private int getSumOfSquares(int n) { |
| 84 | return n * (n + 1) * (2 * n + 1) / 6; |
| 85 | } |
| 86 | |
| 87 | @Override |
| 88 | public float getValue(float itemsBefore) { |
| 89 | if (mStackStartsAtPeek) { |
| 90 | // We directly start at the stack, so no initial interpolation. |
| 91 | itemsBefore++; |
| 92 | } |
| 93 | if (itemsBefore < 0) { |
| 94 | return 0; |
| 95 | } else if (itemsBefore >= mMaxItemsInStack) { |
| 96 | return mTotalTransitionDistance; |
| 97 | } |
| 98 | int below = (int) itemsBefore; |
| 99 | float partialIn = itemsBefore - below; |
| 100 | |
| 101 | if (below == 0) { |
| 102 | return mDistanceToPeekStart * partialIn; |
| 103 | } else { |
| 104 | float result = mDistanceToPeekStart; |
| 105 | float progress = mBaseValues.get(below - 1) * (1 - partialIn) |
| 106 | + mBaseValues.get(below) * partialIn; |
| 107 | result += (progress * (1 - mLinearPart) |
| 108 | + (itemsBefore - 1) / (mMaxItemsInStack - 1) * mLinearPart) * mPeekSize; |
| 109 | return result; |
| 110 | } |
| 111 | } |
| 112 | } |