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 */
16package android.support.v7.internal.widget;
17
18import android.content.Context;
19import android.content.res.Configuration;
20import android.content.res.TypedArray;
21import android.os.Build;
22import android.support.v7.appcompat.R;
23import android.support.v7.internal.view.menu.ActionMenuPresenter;
24import android.support.v7.internal.view.menu.ActionMenuView;
25import android.util.AttributeSet;
26import android.view.View;
27import android.view.ViewGroup;
28import android.view.animation.Animation;
29import android.view.animation.AnimationUtils;
30
31abstract class AbsActionBarView extends ViewGroup {
32
33    protected ActionMenuView mMenuView;
34
35    protected ActionMenuPresenter mActionMenuPresenter;
36
37    protected ActionBarContainer mSplitView;
38
39    protected boolean mSplitActionBar;
40
41    protected boolean mSplitWhenNarrow;
42
43    protected int mContentHeight;
44
45    private static final int FADE_DURATION = 200;
46
47    AbsActionBarView(Context context) {
48        super(context);
49    }
50
51    AbsActionBarView(Context context, AttributeSet attrs) {
52        super(context, attrs);
53    }
54
55    AbsActionBarView(Context context, AttributeSet attrs, int defStyle) {
56        super(context, attrs, defStyle);
57    }
58
59    @Override
60    protected void onConfigurationChanged(Configuration newConfig) {
61        if (Build.VERSION.SDK_INT >= 8) {
62            super.onConfigurationChanged(newConfig);
63        }
64
65        // Action bar can change size on configuration changes.
66        // Reread the desired height from the theme-specified style.
67        TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.ActionBar,
68                R.attr.actionBarStyle, 0);
69        setContentHeight(a.getLayoutDimension(R.styleable.ActionBar_height, 0));
70        a.recycle();
71        if (mSplitWhenNarrow) {
72            setSplitActionBar(getContext().getResources().getBoolean(
73                    R.bool.abc_split_action_bar_is_narrow));
74        }
75        if (mActionMenuPresenter != null) {
76            mActionMenuPresenter.onConfigurationChanged(newConfig);
77        }
78    }
79
80    /**
81     * Sets whether the bar should be split right now, no questions asked.
82     *
83     * @param split true if the bar should split
84     */
85    public void setSplitActionBar(boolean split) {
86        mSplitActionBar = split;
87    }
88
89    /**
90     * Sets whether the bar should split if we enter a narrow screen configuration.
91     *
92     * @param splitWhenNarrow true if the bar should check to split after a config change
93     */
94    public void setSplitWhenNarrow(boolean splitWhenNarrow) {
95        mSplitWhenNarrow = splitWhenNarrow;
96    }
97
98    public void setContentHeight(int height) {
99        mContentHeight = height;
100        requestLayout();
101    }
102
103    public int getContentHeight() {
104        return mContentHeight;
105    }
106
107    public void setSplitView(ActionBarContainer splitView) {
108        mSplitView = splitView;
109    }
110
111    /**
112     * @return Current visibility or if animating, the visibility being animated to.
113     */
114    public int getAnimatedVisibility() {
115        return getVisibility();
116    }
117
118    public void animateToVisibility(int visibility) {
119        clearAnimation();
120
121        if (visibility != getVisibility()) {
122            Animation anim = AnimationUtils.loadAnimation(getContext(),
123                    visibility == View.VISIBLE ? R.anim.abc_fade_in : R.anim.abc_fade_out);
124
125            startAnimation(anim);
126            setVisibility(visibility);
127
128            if (mSplitView != null && mMenuView != null) {
129                mMenuView.startAnimation(anim);
130                mMenuView.setVisibility(visibility);
131            }
132        }
133    }
134
135    @Override
136    public void setVisibility(int visibility) {
137        if (visibility != getVisibility()) {
138            super.setVisibility(visibility);
139        }
140    }
141
142    public boolean showOverflowMenu() {
143        if (mActionMenuPresenter != null) {
144            return mActionMenuPresenter.showOverflowMenu();
145        }
146        return false;
147    }
148
149    public void postShowOverflowMenu() {
150        post(new Runnable() {
151            public void run() {
152                showOverflowMenu();
153            }
154        });
155    }
156
157    public boolean hideOverflowMenu() {
158        if (mActionMenuPresenter != null) {
159            return mActionMenuPresenter.hideOverflowMenu();
160        }
161        return false;
162    }
163
164    public boolean isOverflowMenuShowing() {
165        if (mActionMenuPresenter != null) {
166            return mActionMenuPresenter.isOverflowMenuShowing();
167        }
168        return false;
169    }
170
171    public boolean isOverflowReserved() {
172        return mActionMenuPresenter != null && mActionMenuPresenter.isOverflowReserved();
173    }
174
175    public void dismissPopupMenus() {
176        if (mActionMenuPresenter != null) {
177            mActionMenuPresenter.dismissPopupMenus();
178        }
179    }
180
181    protected int measureChildView(View child, int availableWidth, int childSpecHeight,
182            int spacing) {
183        child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
184                childSpecHeight);
185
186        availableWidth -= child.getMeasuredWidth();
187        availableWidth -= spacing;
188
189        return Math.max(0, availableWidth);
190    }
191
192    protected int positionChild(View child, int x, int y, int contentHeight) {
193        int childWidth = child.getMeasuredWidth();
194        int childHeight = child.getMeasuredHeight();
195        int childTop = y + (contentHeight - childHeight) / 2;
196
197        child.layout(x, childTop, x + childWidth, childTop + childHeight);
198
199        return childWidth;
200    }
201
202    protected int positionChildInverse(View child, int x, int y, int contentHeight) {
203        int childWidth = child.getMeasuredWidth();
204        int childHeight = child.getMeasuredHeight();
205        int childTop = y + (contentHeight - childHeight) / 2;
206
207        child.layout(x - childWidth, childTop, x, childTop + childHeight);
208
209        return childWidth;
210    }
211
212}
213