blob: 38b544f2cc019d4c3fa472d1bcafc5d8be944dbe [file] [log] [blame]
Selim Cinek67b22602014-03-10 15:40:16 +01001/*
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
17package com.android.systemui.statusbar.stack;
18
19import 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 */
26public 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}