/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.systemui.statusbar.stack; import java.util.ArrayList; /** * A Functor which interpolates the stack distance linearly based on base values. * The base values are based on an interpolation between a linear function and a * quadratic function */ public class PiecewiseLinearIndentationFunctor extends StackIndentationFunctor { private final ArrayList mBaseValues; private final float mLinearPart; /** * @param maxItemsInStack The maximum number of items which should be visible at the same time, * i.e the function returns totalTransitionDistance for the element with * index maxItemsInStack * @param peekSize The visual appearance of this is how far the cards in the stack peek * out below the top card and it is measured in real pixels. * Note that the visual appearance does not necessarily always correspond to * the actual visual distance below the top card but is a maximum, * achieved when the next card just starts transitioning into the stack and * the stack is full. * If distanceToPeekStart is 0, we directly start at the peek, otherwise the * first element transitions between 0 and distanceToPeekStart. * Visualization: * --------------------------------------------------- --- * | | | * | FIRST ITEM | | <- distanceToPeekStart * | | | * |---------------------------------------------------| --- --- * |__________________SECOND ITEM______________________| | <- peekSize * |===================================================| _|_ * * @param distanceToPeekStart The distance to the start of the peak. * @param linearPart The interpolation factor between the linear and the quadratic amount taken. * This factor must be somewhere in [0 , 1] */ PiecewiseLinearIndentationFunctor(int maxItemsInStack, int peekSize, int distanceToPeekStart, float linearPart) { super(maxItemsInStack, peekSize, distanceToPeekStart); mBaseValues = new ArrayList(maxItemsInStack+1); initBaseValues(); mLinearPart = linearPart; } private void initBaseValues() { int sumOfSquares = getSumOfSquares(mMaxItemsInStack-1); int totalWeight = 0; mBaseValues.add(0.0f); for (int i = 0; i < mMaxItemsInStack - 1; i++) { totalWeight += (mMaxItemsInStack - i - 1) * (mMaxItemsInStack - i - 1); mBaseValues.add((float) totalWeight / sumOfSquares); } } /** * Get the sum of squares up to and including n, i.e sum(i * i, 1, n) * * @param n the maximum square to include * @return */ private int getSumOfSquares(int n) { return n * (n + 1) * (2 * n + 1) / 6; } @Override public float getValue(float itemsBefore) { if (mStackStartsAtPeek) { // We directly start at the stack, so no initial interpolation. itemsBefore++; } if (itemsBefore < 0) { return 0; } else if (itemsBefore >= mMaxItemsInStack) { return mTotalTransitionDistance; } int below = (int) itemsBefore; float partialIn = itemsBefore - below; if (below == 0) { return mDistanceToPeekStart * partialIn; } else { float result = mDistanceToPeekStart; float progress = mBaseValues.get(below - 1) * (1 - partialIn) + mBaseValues.get(below) * partialIn; result += (progress * (1 - mLinearPart) + (itemsBefore - 1) / (mMaxItemsInStack - 1) * mLinearPart) * mPeekSize; return result; } } }