1/*
2 * Copyright (C) 2010 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.gallery3d.anim;
18
19import android.view.animation.Interpolator;
20
21import com.android.gallery3d.common.Utils;
22
23// Animation calculates a value according to the current input time.
24//
25// 1. First we need to use setDuration(int) to set the duration of the
26//    animation. The duration is in milliseconds.
27// 2. Then we should call start(). The actual start time is the first value
28//    passed to calculate(long).
29// 3. Each time we want to get an animation value, we call
30//    calculate(long currentTimeMillis) to ask the Animation to calculate it.
31//    The parameter passed to calculate(long) should be nonnegative.
32// 4. Use get() to get that value.
33//
34// In step 3, onCalculate(float progress) is called so subclasses can calculate
35// the value according to progress (progress is a value in [0,1]).
36//
37// Before onCalculate(float) is called, There is an optional interpolator which
38// can change the progress value. The interpolator can be set by
39// setInterpolator(Interpolator). If the interpolator is used, the value passed
40// to onCalculate may be (for example, the overshoot effect).
41//
42// The isActive() method returns true after the animation start() is called and
43// before calculate is passed a value which reaches the duration of the
44// animation.
45//
46// The start() method can be called again to restart the Animation.
47//
48abstract public class Animation {
49    private static final long ANIMATION_START = -1;
50    private static final long NO_ANIMATION = -2;
51
52    private long mStartTime = NO_ANIMATION;
53    private int mDuration;
54    private Interpolator mInterpolator;
55
56    public void setInterpolator(Interpolator interpolator) {
57        mInterpolator = interpolator;
58    }
59
60    public void setDuration(int duration) {
61        mDuration = duration;
62    }
63
64    public void start() {
65        mStartTime = ANIMATION_START;
66    }
67
68    public void setStartTime(long time) {
69        mStartTime = time;
70    }
71
72    public boolean isActive() {
73        return mStartTime != NO_ANIMATION;
74    }
75
76    public void forceStop() {
77        mStartTime = NO_ANIMATION;
78    }
79
80    public boolean calculate(long currentTimeMillis) {
81        if (mStartTime == NO_ANIMATION) return false;
82        if (mStartTime == ANIMATION_START) mStartTime = currentTimeMillis;
83        int elapse = (int) (currentTimeMillis - mStartTime);
84        float x = Utils.clamp((float) elapse / mDuration, 0f, 1f);
85        Interpolator i = mInterpolator;
86        onCalculate(i != null ? i.getInterpolation(x) : x);
87        if (elapse >= mDuration) mStartTime = NO_ANIMATION;
88        return mStartTime != NO_ANIMATION;
89    }
90
91    abstract protected void onCalculate(float progress);
92}
93