Home | History | Annotate | Download | only in stack
      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 distanceToPeekStart is 0, we directly start at the peek, otherwise the
     42      *                 first element transitions between 0 and distanceToPeekStart.
     43      *                 Visualization:
     44      *           ---------------------------------------------------   ---
     45      *          |                                                   |   |
     46      *          |                  FIRST ITEM                       |   | <- distanceToPeekStart
     47      *          |                                                   |   |
     48      *          |---------------------------------------------------|  ---  ---
     49      *          |__________________SECOND ITEM______________________|        |  <- peekSize
     50      *          |===================================================|       _|_
     51      *
     52      * @param distanceToPeekStart The distance to the start of the peak.
     53      * @param linearPart The interpolation factor between the linear and the quadratic amount taken.
     54      *                   This factor must be somewhere in [0 , 1]
     55      */
     56     PiecewiseLinearIndentationFunctor(int maxItemsInStack,
     57                                       int peekSize,
     58                                       int distanceToPeekStart,
     59                                       float linearPart) {
     60         super(maxItemsInStack, peekSize, distanceToPeekStart);
     61         mBaseValues = new ArrayList<Float>(maxItemsInStack+1);
     62         initBaseValues();
     63         mLinearPart = linearPart;
     64     }
     65 
     66     private void initBaseValues() {
     67         int sumOfSquares = getSumOfSquares(mMaxItemsInStack-1);
     68         int totalWeight = 0;
     69         mBaseValues.add(0.0f);
     70         for (int i = 0; i < mMaxItemsInStack - 1; i++) {
     71             totalWeight += (mMaxItemsInStack - i - 1) * (mMaxItemsInStack - i - 1);
     72             mBaseValues.add((float) totalWeight / sumOfSquares);
     73         }
     74     }
     75 
     76     /**
     77      * Get the sum of squares up to and including n, i.e sum(i * i, 1, n)
     78      *
     79      * @param n the maximum square to include
     80      * @return
     81      */
     82     private int getSumOfSquares(int n) {
     83         return n * (n + 1) * (2 * n + 1) / 6;
     84     }
     85 
     86     @Override
     87     public float getValue(float itemsBefore) {
     88         if (mStackStartsAtPeek) {
     89             // We directly start at the stack, so no initial interpolation.
     90             itemsBefore++;
     91         }
     92         if (itemsBefore < 0) {
     93             return 0;
     94         } else if (itemsBefore >= mMaxItemsInStack) {
     95             return mTotalTransitionDistance;
     96         }
     97         int below = (int) itemsBefore;
     98         float partialIn = itemsBefore - below;
     99 
    100         if (below == 0) {
    101             return mDistanceToPeekStart * partialIn;
    102         } else {
    103             float result = mDistanceToPeekStart;
    104             float progress = mBaseValues.get(below - 1) * (1 - partialIn)
    105                     + mBaseValues.get(below) * partialIn;
    106             result += (progress * (1 - mLinearPart)
    107                     + (itemsBefore - 1) / (mMaxItemsInStack - 1)  * mLinearPart) * mPeekSize;
    108             return result;
    109         }
    110     }
    111 }
    112