create changelog entry
[debian/openrocket] / android-libraries / ActionBarSherlock / src / com / actionbarsherlock / internal / widget / ActionBarContainer.java
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
17 package com.actionbarsherlock.internal.widget;
18
19 import android.content.Context;
20 import android.content.res.TypedArray;
21 import android.graphics.Canvas;
22 import android.graphics.drawable.Drawable;
23 import android.util.AttributeSet;
24 import android.view.MotionEvent;
25 import android.view.View;
26 import android.view.ViewGroup;
27
28 import com.actionbarsherlock.R;
29 import com.actionbarsherlock.app.ActionBar;
30 import com.actionbarsherlock.internal.nineoldandroids.widget.NineFrameLayout;
31
32 /**
33  * This class acts as a container for the action bar view and action mode context views.
34  * It applies special styles as needed to help handle animated transitions between them.
35  * @hide
36  */
37 public class ActionBarContainer extends NineFrameLayout {
38     private boolean mIsTransitioning;
39     private View mTabContainer;
40     private ActionBarView mActionBarView;
41
42     private Drawable mBackground;
43     private Drawable mStackedBackground;
44     private Drawable mSplitBackground;
45     private boolean mIsSplit;
46     private boolean mIsStacked;
47
48     public ActionBarContainer(Context context) {
49         this(context, null);
50     }
51
52     public ActionBarContainer(Context context, AttributeSet attrs) {
53         super(context, attrs);
54
55         setBackgroundDrawable(null);
56
57         TypedArray a = context.obtainStyledAttributes(attrs,
58                 R.styleable.SherlockActionBar);
59         mBackground = a.getDrawable(R.styleable.SherlockActionBar_background);
60         mStackedBackground = a.getDrawable(
61                 R.styleable.SherlockActionBar_backgroundStacked);
62
63         if (getId() == R.id.abs__split_action_bar) {
64             mIsSplit = true;
65             mSplitBackground = a.getDrawable(
66                     R.styleable.SherlockActionBar_backgroundSplit);
67         }
68         a.recycle();
69
70         setWillNotDraw(mIsSplit ? mSplitBackground == null :
71                 mBackground == null && mStackedBackground == null);
72     }
73
74     @Override
75     public void onFinishInflate() {
76         super.onFinishInflate();
77         mActionBarView = (ActionBarView) findViewById(R.id.abs__action_bar);
78     }
79
80     public void setPrimaryBackground(Drawable bg) {
81         mBackground = bg;
82         invalidate();
83     }
84
85     public void setStackedBackground(Drawable bg) {
86         mStackedBackground = bg;
87         invalidate();
88     }
89
90     public void setSplitBackground(Drawable bg) {
91         mSplitBackground = bg;
92         invalidate();
93     }
94
95     /**
96      * Set the action bar into a "transitioning" state. While transitioning
97      * the bar will block focus and touch from all of its descendants. This
98      * prevents the user from interacting with the bar while it is animating
99      * in or out.
100      *
101      * @param isTransitioning true if the bar is currently transitioning, false otherwise.
102      */
103     public void setTransitioning(boolean isTransitioning) {
104         mIsTransitioning = isTransitioning;
105         setDescendantFocusability(isTransitioning ? FOCUS_BLOCK_DESCENDANTS
106                 : FOCUS_AFTER_DESCENDANTS);
107     }
108
109     @Override
110     public boolean onInterceptTouchEvent(MotionEvent ev) {
111         return mIsTransitioning || super.onInterceptTouchEvent(ev);
112     }
113
114     @Override
115     public boolean onTouchEvent(MotionEvent ev) {
116         super.onTouchEvent(ev);
117
118         // An action bar always eats touch events.
119         return true;
120     }
121
122     @Override
123     public boolean onHoverEvent(MotionEvent ev) {
124         super.onHoverEvent(ev);
125
126         // An action bar always eats hover events.
127         return true;
128     }
129
130     public void setTabContainer(ScrollingTabContainerView tabView) {
131         if (mTabContainer != null) {
132             removeView(mTabContainer);
133         }
134         mTabContainer = tabView;
135         if (tabView != null) {
136             addView(tabView);
137             final ViewGroup.LayoutParams lp = tabView.getLayoutParams();
138             lp.width = LayoutParams.MATCH_PARENT;
139             lp.height = LayoutParams.WRAP_CONTENT;
140             tabView.setAllowCollapse(false);
141         }
142     }
143
144     public View getTabContainer() {
145         return mTabContainer;
146     }
147
148     @Override
149     public void onDraw(Canvas canvas) {
150         if (getWidth() == 0 || getHeight() == 0) {
151             return;
152         }
153
154         if (mIsSplit) {
155             if (mSplitBackground != null) mSplitBackground.draw(canvas);
156         } else {
157             if (mBackground != null) {
158                 mBackground.draw(canvas);
159             }
160             if (mStackedBackground != null && mIsStacked) {
161                 mStackedBackground.draw(canvas);
162             }
163         }
164     }
165
166     //This causes the animation reflection to fail on pre-HC platforms
167     //@Override
168     //public android.view.ActionMode startActionModeForChild(View child, android.view.ActionMode.Callback callback) {
169     //    // No starting an action mode for an action bar child! (Where would it go?)
170     //    return null;
171     //}
172
173     @Override
174     public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
175         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
176
177         if (mActionBarView == null) return;
178
179         final LayoutParams lp = (LayoutParams) mActionBarView.getLayoutParams();
180         final int actionBarViewHeight = mActionBarView.isCollapsed() ? 0 :
181                 mActionBarView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
182
183         if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
184             final int mode = MeasureSpec.getMode(heightMeasureSpec);
185             if (mode == MeasureSpec.AT_MOST) {
186                 final int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
187                 setMeasuredDimension(getMeasuredWidth(),
188                         Math.min(actionBarViewHeight + mTabContainer.getMeasuredHeight(),
189                                 maxHeight));
190             }
191         }
192     }
193
194     @Override
195     public void onLayout(boolean changed, int l, int t, int r, int b) {
196         super.onLayout(changed, l, t, r, b);
197
198         final boolean hasTabs = mTabContainer != null && mTabContainer.getVisibility() != GONE;
199
200         if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
201             final int containerHeight = getMeasuredHeight();
202             final int tabHeight = mTabContainer.getMeasuredHeight();
203
204             if ((mActionBarView.getDisplayOptions() & ActionBar.DISPLAY_SHOW_HOME) == 0) {
205                 // Not showing home, put tabs on top.
206                 final int count = getChildCount();
207                 for (int i = 0; i < count; i++) {
208                     final View child = getChildAt(i);
209
210                     if (child == mTabContainer) continue;
211
212                     if (!mActionBarView.isCollapsed()) {
213                         child.offsetTopAndBottom(tabHeight);
214                     }
215                 }
216                 mTabContainer.layout(l, 0, r, tabHeight);
217             } else {
218                 mTabContainer.layout(l, containerHeight - tabHeight, r, containerHeight);
219             }
220         }
221
222         boolean needsInvalidate = false;
223         if (mIsSplit) {
224             if (mSplitBackground != null) {
225                 mSplitBackground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
226                 needsInvalidate = true;
227             }
228         } else {
229             if (mBackground != null) {
230                 mBackground.setBounds(mActionBarView.getLeft(), mActionBarView.getTop(),
231                         mActionBarView.getRight(), mActionBarView.getBottom());
232                 needsInvalidate = true;
233             }
234             if ((mIsStacked = hasTabs && mStackedBackground != null)) {
235                 mStackedBackground.setBounds(mTabContainer.getLeft(), mTabContainer.getTop(),
236                         mTabContainer.getRight(), mTabContainer.getBottom());
237                 needsInvalidate = true;
238             }
239         }
240
241         if (needsInvalidate) {
242             invalidate();
243         }
244     }
245 }