1/*
2 * Copyright (C) 2009 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.launcher2;
18
19import android.os.Handler;
20import android.os.SystemClock;
21
22/**
23 * Provides an animation between 0.0f and 1.0f over a given duration.
24 */
25class SymmetricalLinearTween {
26
27    private static final int FPS = 30;
28    private static final int FRAME_TIME = 1000 / FPS;
29
30    Handler mHandler;
31    int mDuration;
32    TweenCallback mCallback;
33
34    boolean mRunning;
35    long mBase;
36    boolean mDirection;
37    float mValue;
38
39    /**
40     * @param duration milliseconds duration
41     * @param callback callbacks
42     */
43    public SymmetricalLinearTween(boolean initial, int duration, TweenCallback callback) {
44        mValue = initial ? 1.0f : 0.0f;
45        mDirection = initial;
46        mDuration = duration;
47        mCallback = callback;
48        mHandler = new Handler();
49    }
50
51    /**
52     * Starts the tweening.
53     *
54     * @param direction If direction is true, the value goes towards 1.0f.  If direction
55     *                  is false, the value goes towards 0.0f.
56     */
57    public void start(boolean direction) {
58        start(direction, SystemClock.uptimeMillis());
59    }
60
61    /**
62     * Starts the tweening.
63     *
64     * @param direction If direction is true, the value goes towards 1.0f.  If direction
65     *                  is false, the value goes towards 0.0f.
66     * @param baseTime  The time to use as zero for this animation, in the
67     *                  {@link SystemClock.uptimeMillis} time base.  This allows you to
68     *                  synchronize multiple animations.
69     */
70    public void start(boolean direction, long baseTime) {
71        if (direction != mDirection) {
72            if (!mRunning) {
73                mBase = baseTime;
74                mRunning = true;
75                mCallback.onTweenStarted();
76                long next = SystemClock.uptimeMillis() + FRAME_TIME;
77                mHandler.postAtTime(mTick, next);
78            } else {
79                // reverse direction
80                long now = SystemClock.uptimeMillis();
81                long diff = now - mBase;
82                mBase = now + diff - mDuration;
83            }
84            mDirection = direction;
85        }
86    }
87
88    Runnable mTick = new Runnable() {
89        public void run() {
90            long base = mBase;
91            long now = SystemClock.uptimeMillis();
92            long diff = now-base;
93            int duration = mDuration;
94            float val = diff/(float)duration;
95            if (!mDirection) {
96                val = 1.0f - val;
97            }
98            if (val > 1.0f) {
99                val = 1.0f;
100            } else if (val < 0.0f) {
101                val = 0.0f;
102            }
103            float old = mValue;
104            mValue = val;
105            mCallback.onTweenValueChanged(val, old);
106            int frame = (int)(diff / FRAME_TIME);
107            long next = base + ((frame+1)*FRAME_TIME);
108            if (diff < duration) {
109                mHandler.postAtTime(this, next);
110            }
111            if (diff >= duration) {
112                mCallback.onTweenFinished();
113                mRunning = false;
114            }
115        }
116    };
117}
118
119