create changelog entry
[debian/openrocket] / android-libraries / ActionBarSherlock / src / com / actionbarsherlock / internal / widget / AbsActionBarView.java
1 /*
2  * Copyright (C) 2011 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 package com.actionbarsherlock.internal.widget;
17
18 import android.content.Context;
19 import android.content.res.Configuration;
20 import android.content.res.TypedArray;
21 import android.os.Build;
22 import android.util.AttributeSet;
23 import android.view.View;
24 import android.view.animation.DecelerateInterpolator;
25 import android.view.animation.Interpolator;
26
27 import com.actionbarsherlock.R;
28 import com.actionbarsherlock.internal.nineoldandroids.animation.Animator;
29 import com.actionbarsherlock.internal.nineoldandroids.animation.AnimatorSet;
30 import com.actionbarsherlock.internal.nineoldandroids.animation.ObjectAnimator;
31 import com.actionbarsherlock.internal.nineoldandroids.view.NineViewGroup;
32 import com.actionbarsherlock.internal.view.menu.ActionMenuPresenter;
33 import com.actionbarsherlock.internal.view.menu.ActionMenuView;
34
35 import static com.actionbarsherlock.internal.ResourcesCompat.getResources_getBoolean;
36
37 public abstract class AbsActionBarView extends NineViewGroup {
38     protected ActionMenuView mMenuView;
39     protected ActionMenuPresenter mActionMenuPresenter;
40     protected ActionBarContainer mSplitView;
41     protected boolean mSplitActionBar;
42     protected boolean mSplitWhenNarrow;
43     protected int mContentHeight;
44
45     final Context mContext;
46
47     protected Animator mVisibilityAnim;
48     protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener();
49
50     private static final /*Time*/Interpolator sAlphaInterpolator = new DecelerateInterpolator();
51
52     private static final int FADE_DURATION = 200;
53
54     public AbsActionBarView(Context context) {
55         super(context);
56         mContext = context;
57     }
58
59     public AbsActionBarView(Context context, AttributeSet attrs) {
60         super(context, attrs);
61         mContext = context;
62     }
63
64     public AbsActionBarView(Context context, AttributeSet attrs, int defStyle) {
65         super(context, attrs, defStyle);
66         mContext = context;
67     }
68
69     /*
70      * Must be public so we can dispatch pre-2.2 via ActionBarImpl.
71      */
72     @Override
73     public void onConfigurationChanged(Configuration newConfig) {
74         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
75             super.onConfigurationChanged(newConfig);
76         } else if (mMenuView != null) {
77             mMenuView.onConfigurationChanged(newConfig);
78         }
79
80         // Action bar can change size on configuration changes.
81         // Reread the desired height from the theme-specified style.
82         TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.SherlockActionBar,
83                 R.attr.actionBarStyle, 0);
84         setContentHeight(a.getLayoutDimension(R.styleable.SherlockActionBar_height, 0));
85         a.recycle();
86         if (mSplitWhenNarrow) {
87             setSplitActionBar(getResources_getBoolean(getContext(),
88                     R.bool.abs__split_action_bar_is_narrow));
89         }
90         if (mActionMenuPresenter != null) {
91             mActionMenuPresenter.onConfigurationChanged(newConfig);
92         }
93     }
94
95     /**
96      * Sets whether the bar should be split right now, no questions asked.
97      * @param split true if the bar should split
98      */
99     public void setSplitActionBar(boolean split) {
100         mSplitActionBar = split;
101     }
102
103     /**
104      * Sets whether the bar should split if we enter a narrow screen configuration.
105      * @param splitWhenNarrow true if the bar should check to split after a config change
106      */
107     public void setSplitWhenNarrow(boolean splitWhenNarrow) {
108         mSplitWhenNarrow = splitWhenNarrow;
109     }
110
111     public void setContentHeight(int height) {
112         mContentHeight = height;
113         requestLayout();
114     }
115
116     public int getContentHeight() {
117         return mContentHeight;
118     }
119
120     public void setSplitView(ActionBarContainer splitView) {
121         mSplitView = splitView;
122     }
123
124     /**
125      * @return Current visibility or if animating, the visibility being animated to.
126      */
127     public int getAnimatedVisibility() {
128         if (mVisibilityAnim != null) {
129             return mVisAnimListener.mFinalVisibility;
130         }
131         return getVisibility();
132     }
133
134     public void animateToVisibility(int visibility) {
135         if (mVisibilityAnim != null) {
136             mVisibilityAnim.cancel();
137         }
138         if (visibility == VISIBLE) {
139             if (getVisibility() != VISIBLE) {
140                 setAlpha(0);
141                 if (mSplitView != null && mMenuView != null) {
142                     mMenuView.setAlpha(0);
143                 }
144             }
145             ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1);
146             anim.setDuration(FADE_DURATION);
147             anim.setInterpolator(sAlphaInterpolator);
148             if (mSplitView != null && mMenuView != null) {
149                 AnimatorSet set = new AnimatorSet();
150                 ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 1);
151                 splitAnim.setDuration(FADE_DURATION);
152                 set.addListener(mVisAnimListener.withFinalVisibility(visibility));
153                 set.play(anim).with(splitAnim);
154                 set.start();
155             } else {
156                 anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
157                 anim.start();
158             }
159         } else {
160             ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0);
161             anim.setDuration(FADE_DURATION);
162             anim.setInterpolator(sAlphaInterpolator);
163             if (mSplitView != null && mMenuView != null) {
164                 AnimatorSet set = new AnimatorSet();
165                 ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 0);
166                 splitAnim.setDuration(FADE_DURATION);
167                 set.addListener(mVisAnimListener.withFinalVisibility(visibility));
168                 set.play(anim).with(splitAnim);
169                 set.start();
170             } else {
171                 anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
172                 anim.start();
173             }
174         }
175     }
176
177     @Override
178     public void setVisibility(int visibility) {
179         if (mVisibilityAnim != null) {
180             mVisibilityAnim.end();
181         }
182         super.setVisibility(visibility);
183     }
184
185     public boolean showOverflowMenu() {
186         if (mActionMenuPresenter != null) {
187             return mActionMenuPresenter.showOverflowMenu();
188         }
189         return false;
190     }
191
192     public void postShowOverflowMenu() {
193         post(new Runnable() {
194             public void run() {
195                 showOverflowMenu();
196             }
197         });
198     }
199
200     public boolean hideOverflowMenu() {
201         if (mActionMenuPresenter != null) {
202             return mActionMenuPresenter.hideOverflowMenu();
203         }
204         return false;
205     }
206
207     public boolean isOverflowMenuShowing() {
208         if (mActionMenuPresenter != null) {
209             return mActionMenuPresenter.isOverflowMenuShowing();
210         }
211         return false;
212     }
213
214     public boolean isOverflowReserved() {
215         return mActionMenuPresenter != null && mActionMenuPresenter.isOverflowReserved();
216     }
217
218     public void dismissPopupMenus() {
219         if (mActionMenuPresenter != null) {
220             mActionMenuPresenter.dismissPopupMenus();
221         }
222     }
223
224     protected int measureChildView(View child, int availableWidth, int childSpecHeight,
225             int spacing) {
226         child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
227                 childSpecHeight);
228
229         availableWidth -= child.getMeasuredWidth();
230         availableWidth -= spacing;
231
232         return Math.max(0, availableWidth);
233     }
234
235     protected int positionChild(View child, int x, int y, int contentHeight) {
236         int childWidth = child.getMeasuredWidth();
237         int childHeight = child.getMeasuredHeight();
238         int childTop = y + (contentHeight - childHeight) / 2;
239
240         child.layout(x, childTop, x + childWidth, childTop + childHeight);
241
242         return childWidth;
243     }
244
245     protected int positionChildInverse(View child, int x, int y, int contentHeight) {
246         int childWidth = child.getMeasuredWidth();
247         int childHeight = child.getMeasuredHeight();
248         int childTop = y + (contentHeight - childHeight) / 2;
249
250         child.layout(x - childWidth, childTop, x, childTop + childHeight);
251
252         return childWidth;
253     }
254
255     protected class VisibilityAnimListener implements Animator.AnimatorListener {
256         private boolean mCanceled = false;
257         int mFinalVisibility;
258
259         public VisibilityAnimListener withFinalVisibility(int visibility) {
260             mFinalVisibility = visibility;
261             return this;
262         }
263
264         @Override
265         public void onAnimationStart(Animator animation) {
266             setVisibility(VISIBLE);
267             mVisibilityAnim = animation;
268             mCanceled = false;
269         }
270
271         @Override
272         public void onAnimationEnd(Animator animation) {
273             if (mCanceled) return;
274
275             mVisibilityAnim = null;
276             setVisibility(mFinalVisibility);
277             if (mSplitView != null && mMenuView != null) {
278                 mMenuView.setVisibility(mFinalVisibility);
279             }
280         }
281
282         @Override
283         public void onAnimationCancel(Animator animation) {
284             mCanceled = true;
285         }
286
287         @Override
288         public void onAnimationRepeat(Animator animation) {
289         }
290     }
291 }