create changelog entry
[debian/openrocket] / android-libraries / ActionBarSherlock / src / com / actionbarsherlock / internal / nineoldandroids / view / animation / AnimatorProxy.java
1 package com.actionbarsherlock.internal.nineoldandroids.view.animation;
2
3 import java.lang.ref.WeakReference;
4 import java.util.WeakHashMap;
5 import android.graphics.Matrix;
6 import android.graphics.RectF;
7 import android.os.Build;
8 import android.util.FloatMath;
9 import android.view.View;
10 import android.view.animation.Animation;
11 import android.view.animation.Transformation;
12
13 public final class AnimatorProxy extends Animation {
14     public static final boolean NEEDS_PROXY = Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB;
15
16     private static final WeakHashMap<View, AnimatorProxy> PROXIES =
17             new WeakHashMap<View, AnimatorProxy>();
18
19     public static AnimatorProxy wrap(View view) {
20         AnimatorProxy proxy = PROXIES.get(view);
21         if (proxy == null) {
22             proxy = new AnimatorProxy(view);
23             PROXIES.put(view, proxy);
24         }
25         return proxy;
26     }
27
28     private final WeakReference<View> mView;
29
30     private float mAlpha = 1;
31     private float mScaleX = 1;
32     private float mScaleY = 1;
33     private float mTranslationX;
34     private float mTranslationY;
35
36     private final RectF mBefore = new RectF();
37     private final RectF mAfter = new RectF();
38     private final Matrix mTempMatrix = new Matrix();
39
40     private AnimatorProxy(View view) {
41         setDuration(0); //perform transformation immediately
42         setFillAfter(true); //persist transformation beyond duration
43         view.setAnimation(this);
44         mView = new WeakReference<View>(view);
45     }
46
47     public float getAlpha() {
48         return mAlpha;
49     }
50     public void setAlpha(float alpha) {
51         if (mAlpha != alpha) {
52             mAlpha = alpha;
53             View view = mView.get();
54             if (view != null) {
55                 view.invalidate();
56             }
57         }
58     }
59     public float getScaleX() {
60         return mScaleX;
61     }
62     public void setScaleX(float scaleX) {
63         if (mScaleX != scaleX) {
64             prepareForUpdate();
65             mScaleX = scaleX;
66             invalidateAfterUpdate();
67         }
68     }
69     public float getScaleY() {
70         return mScaleY;
71     }
72     public void setScaleY(float scaleY) {
73         if (mScaleY != scaleY) {
74             prepareForUpdate();
75             mScaleY = scaleY;
76             invalidateAfterUpdate();
77         }
78     }
79     public int getScrollX() {
80         View view = mView.get();
81         if (view == null) {
82             return 0;
83         }
84         return view.getScrollX();
85     }
86     public void setScrollX(int value) {
87         View view = mView.get();
88         if (view != null) {
89             view.scrollTo(value, view.getScrollY());
90         }
91     }
92     public int getScrollY() {
93         View view = mView.get();
94         if (view == null) {
95             return 0;
96         }
97         return view.getScrollY();
98     }
99     public void setScrollY(int value) {
100         View view = mView.get();
101         if (view != null) {
102             view.scrollTo(view.getScrollY(), value);
103         }
104     }
105
106     public float getTranslationX() {
107         return mTranslationX;
108     }
109     public void setTranslationX(float translationX) {
110         if (mTranslationX != translationX) {
111             prepareForUpdate();
112             mTranslationX = translationX;
113             invalidateAfterUpdate();
114         }
115     }
116     public float getTranslationY() {
117         return mTranslationY;
118     }
119     public void setTranslationY(float translationY) {
120         if (mTranslationY != translationY) {
121             prepareForUpdate();
122             mTranslationY = translationY;
123             invalidateAfterUpdate();
124         }
125     }
126
127     private void prepareForUpdate() {
128         View view = mView.get();
129         if (view != null) {
130             computeRect(mBefore, view);
131         }
132     }
133     private void invalidateAfterUpdate() {
134         View view = mView.get();
135         if (view == null) {
136             return;
137         }
138         View parent = (View)view.getParent();
139         if (parent == null) {
140             return;
141         }
142
143         view.setAnimation(this);
144
145         final RectF after = mAfter;
146         computeRect(after, view);
147         after.union(mBefore);
148
149         parent.invalidate(
150                 (int) FloatMath.floor(after.left),
151                 (int) FloatMath.floor(after.top),
152                 (int) FloatMath.ceil(after.right),
153                 (int) FloatMath.ceil(after.bottom));
154     }
155
156     private void computeRect(final RectF r, View view) {
157         // compute current rectangle according to matrix transformation
158         final float w = view.getWidth();
159         final float h = view.getHeight();
160
161         // use a rectangle at 0,0 to make sure we don't run into issues with scaling
162         r.set(0, 0, w, h);
163
164         final Matrix m = mTempMatrix;
165         m.reset();
166         transformMatrix(m, view);
167         mTempMatrix.mapRect(r);
168
169         r.offset(view.getLeft(), view.getTop());
170
171         // Straighten coords if rotations flipped them
172         if (r.right < r.left) {
173             final float f = r.right;
174             r.right = r.left;
175             r.left = f;
176         }
177         if (r.bottom < r.top) {
178             final float f = r.top;
179             r.top = r.bottom;
180             r.bottom = f;
181         }
182     }
183
184     private void transformMatrix(Matrix m, View view) {
185         final float w = view.getWidth();
186         final float h = view.getHeight();
187
188         final float sX = mScaleX;
189         final float sY = mScaleY;
190         if ((sX != 1.0f) || (sY != 1.0f)) {
191             final float deltaSX = ((sX * w) - w) / 2f;
192             final float deltaSY = ((sY * h) - h) / 2f;
193             m.postScale(sX, sY);
194             m.postTranslate(-deltaSX, -deltaSY);
195         }
196         m.postTranslate(mTranslationX, mTranslationY);
197     }
198
199     @Override
200     protected void applyTransformation(float interpolatedTime, Transformation t) {
201         View view = mView.get();
202         if (view != null) {
203             t.setAlpha(mAlpha);
204             transformMatrix(t.getMatrix(), view);
205         }
206     }
207
208     @Override
209     public void reset() {
210         /* Do nothing. */
211     }
212 }