13954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes/*
23954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes * Copyright (C) 2013 The Android Open Source Project
33954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes *
43954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes * Licensed under the Apache License, Version 2.0 (the "License");
53954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes * you may not use this file except in compliance with the License.
63954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes * You may obtain a copy of the License at
73954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes *
83954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes *      http://www.apache.org/licenses/LICENSE-2.0
93954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes *
103954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes * Unless required by applicable law or agreed to in writing, software
113954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes * distributed under the License is distributed on an "AS IS" BASIS,
123954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes * See the License for the specific language governing permissions and
143954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes * limitations under the License.
153954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes */
163954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
173954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banespackage android.support.v7.app;
183954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
19d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banesimport android.content.Context;
203954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banesimport android.content.pm.ActivityInfo;
213954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banesimport android.content.pm.PackageManager;
223954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banesimport android.content.res.Configuration;
235a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banesimport android.content.res.TypedArray;
245a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banesimport android.os.Build;
253954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banesimport android.os.Bundle;
2645d973fcc4c43f5ea00cddd3d9b947d9e8d8fc4eChris Banesimport android.support.v4.app.ActionBarDrawerToggle;
27bb994e828a647d6ca3c2480293e7a6e3a4c19952Chris Banesimport android.support.v4.app.NavUtils;
285a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banesimport android.support.v7.appcompat.R;
295a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banesimport android.support.v7.internal.view.SupportMenuInflater;
30d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banesimport android.support.v7.view.ActionMode;
313954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banesimport android.util.Log;
3230837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.Menu;
3330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.MenuInflater;
3430837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.MenuItem;
353954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banesimport android.view.View;
363954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banesimport android.view.ViewGroup;
373954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
383954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banesabstract class ActionBarActivityDelegate {
393954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
403954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes    static final String METADATA_UI_OPTIONS = "android.support.UI_OPTIONS";
413954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes    static final String UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW = "splitActionBarWhenNarrow";
423954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
433954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes    private static final String TAG = "ActionBarActivityDelegate";
443954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
455a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes    static ActionBarActivityDelegate createDelegate(ActionBarActivity activity) {
465a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes        final int version = Build.VERSION.SDK_INT;
478fcdb874200960138b32eb3b276a801f619b69b1Chris Banes        if (version >= Build.VERSION_CODES.JELLY_BEAN) {
488fcdb874200960138b32eb3b276a801f619b69b1Chris Banes            return new ActionBarActivityDelegateJB(activity);
498fcdb874200960138b32eb3b276a801f619b69b1Chris Banes        } else if (version >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
505a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes            return new ActionBarActivityDelegateICS(activity);
518123e4b3d19031e34a60c0db202f0b3d100eb9d8Chris Banes        } else if (version >= Build.VERSION_CODES.HONEYCOMB) {
528123e4b3d19031e34a60c0db202f0b3d100eb9d8Chris Banes            return new ActionBarActivityDelegateHC(activity);
535a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes        } else {
54f2b7cd67036d78fd5b487b0a2dab28aee11d9c88Adam Powell            return new ActionBarActivityDelegateBase(activity);
555a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes        }
565a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes    }
575a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes
583954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes    final ActionBarActivity mActivity;
593954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
605a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes    private ActionBar mActionBar;
615a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes    private MenuInflater mMenuInflater;
625a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes
635a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes    // true if this activity has an action bar.
645a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes    boolean mHasActionBar;
655a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes    // true if this activity's action bar overlays other activity content.
665a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes    boolean mOverlayActionBar;
675a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes
68bb994e828a647d6ca3c2480293e7a6e3a4c19952Chris Banes    private boolean mEnableDefaultActionBarUp;
69bb994e828a647d6ca3c2480293e7a6e3a4c19952Chris Banes
703954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes    ActionBarActivityDelegate(ActionBarActivity activity) {
713954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes        mActivity = activity;
723954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes    }
733954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
743954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes    abstract ActionBar createSupportActionBar();
753954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
765a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes    final ActionBar getSupportActionBar() {
775a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes        // The Action Bar should be lazily created as mHasActionBar or mOverlayActionBar
785a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes        // could change after onCreate
795a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes        if (mHasActionBar || mOverlayActionBar) {
805a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes            if (mActionBar == null) {
815a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes                mActionBar = createSupportActionBar();
82bb994e828a647d6ca3c2480293e7a6e3a4c19952Chris Banes
83bb994e828a647d6ca3c2480293e7a6e3a4c19952Chris Banes                if (mEnableDefaultActionBarUp) {
84bb994e828a647d6ca3c2480293e7a6e3a4c19952Chris Banes                    mActionBar.setDisplayHomeAsUpEnabled(true);
85bb994e828a647d6ca3c2480293e7a6e3a4c19952Chris Banes                }
865a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes            }
875a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes        } else {
885a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes            // If we're not set to have a Action Bar, null it just in case it's been set
895a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes            mActionBar = null;
905a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes        }
915a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes        return mActionBar;
925a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes    }
935a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes
9403527a1c5ca870353671fd8b97a08a989fe62012Chris Banes    MenuInflater getMenuInflater() {
955a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes        if (mMenuInflater == null) {
96baf2251209e04f0dac4ec7e5d8c0bfc0014c4038Chris Banes            ActionBar ab = getSupportActionBar();
97baf2251209e04f0dac4ec7e5d8c0bfc0014c4038Chris Banes            if (ab != null) {
98baf2251209e04f0dac4ec7e5d8c0bfc0014c4038Chris Banes                mMenuInflater = new SupportMenuInflater(ab.getThemedContext());
99baf2251209e04f0dac4ec7e5d8c0bfc0014c4038Chris Banes            } else {
100baf2251209e04f0dac4ec7e5d8c0bfc0014c4038Chris Banes                mMenuInflater = new SupportMenuInflater(mActivity);
101baf2251209e04f0dac4ec7e5d8c0bfc0014c4038Chris Banes            }
1025a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes        }
1035a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes        return mMenuInflater;
1045a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes    }
1055a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes
1065a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes    void onCreate(Bundle savedInstanceState) {
1075a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes        TypedArray a = mActivity.obtainStyledAttributes(R.styleable.ActionBarWindow);
1085a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes
1095a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes        if (!a.hasValue(R.styleable.ActionBarWindow_windowActionBar)) {
1105a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes            a.recycle();
1115a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes            throw new IllegalStateException(
1125a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes                    "You need to use a Theme.AppCompat theme (or descendant) with this activity.");
1135a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes        }
1145a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes
1155a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes        mHasActionBar = a.getBoolean(R.styleable.ActionBarWindow_windowActionBar, false);
1165a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes        mOverlayActionBar = a.getBoolean(R.styleable.ActionBarWindow_windowActionBarOverlay, false);
1175a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes        a.recycle();
118bb994e828a647d6ca3c2480293e7a6e3a4c19952Chris Banes
119bb994e828a647d6ca3c2480293e7a6e3a4c19952Chris Banes        if (NavUtils.getParentActivityName(mActivity) != null) {
120bb994e828a647d6ca3c2480293e7a6e3a4c19952Chris Banes            if (mActionBar == null) {
121bb994e828a647d6ca3c2480293e7a6e3a4c19952Chris Banes                mEnableDefaultActionBarUp = true;
122bb994e828a647d6ca3c2480293e7a6e3a4c19952Chris Banes            } else {
123bb994e828a647d6ca3c2480293e7a6e3a4c19952Chris Banes                mActionBar.setDisplayHomeAsUpEnabled(true);
124bb994e828a647d6ca3c2480293e7a6e3a4c19952Chris Banes            }
125bb994e828a647d6ca3c2480293e7a6e3a4c19952Chris Banes        }
1265a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes    }
1273954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
1283954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes    abstract void onConfigurationChanged(Configuration newConfig);
1293954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
130a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes    abstract void onStop();
131a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes
132a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes    abstract void onPostResume();
133a1fae63dbeeef71c2daa25bfcaa2348bffc369aaChris Banes
1343954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes    abstract void setContentView(View v);
1353954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
1363954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes    abstract void setContentView(int resId);
1373954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
1383954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes    abstract void setContentView(View v, ViewGroup.LayoutParams lp);
1393954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
1403954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes    abstract void addContentView(View v, ViewGroup.LayoutParams lp);
1413954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
142904507029cd8ea2d070b6df0911b2dd36b7075a6Chris Banes    abstract void onTitleChanged(CharSequence title);
1433954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
1443954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes    abstract void supportInvalidateOptionsMenu();
1453954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
146ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes    abstract boolean supportRequestWindowFeature(int featureId);
147ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes
1483954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes    // Methods used to create and respond to options menu
1493954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes    abstract View onCreatePanelView(int featureId);
1503954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
15130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    abstract boolean onPreparePanel(int featureId, View view, Menu menu);
1523954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
1532bc5191a8cc331b404724759a015949a4b5499fbChris Banes    boolean onPrepareOptionsPanel(View view, Menu menu) {
1542bc5191a8cc331b404724759a015949a4b5499fbChris Banes        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
1552bc5191a8cc331b404724759a015949a4b5499fbChris Banes            // Call straight through to onPrepareOptionsMenu, bypassing super.onPreparePanel().
1562bc5191a8cc331b404724759a015949a4b5499fbChris Banes            // This is because Activity.onPreparePanel() on <v4.1 calls menu.hasVisibleItems(),
1572bc5191a8cc331b404724759a015949a4b5499fbChris Banes            // which interferes with the initially invisible items.
1582bc5191a8cc331b404724759a015949a4b5499fbChris Banes            return mActivity.onPrepareOptionsMenu(menu);
1592bc5191a8cc331b404724759a015949a4b5499fbChris Banes        }
1602bc5191a8cc331b404724759a015949a4b5499fbChris Banes        return mActivity.superOnPrepareOptionsPanel(view, menu);
1612bc5191a8cc331b404724759a015949a4b5499fbChris Banes    }
1622bc5191a8cc331b404724759a015949a4b5499fbChris Banes
16330837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    abstract boolean onCreatePanelMenu(int featureId, Menu menu);
1643954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
16530837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    abstract boolean onMenuItemSelected(int featureId, MenuItem item);
1663954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
167d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes    abstract boolean onBackPressed();
168d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes
169d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes    abstract ActionMode startSupportActionMode(ActionMode.Callback callback);
170d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes
17130837f1095c803f332f4a1c3f0917c8afdd50156Adam Powell    abstract void setSupportProgressBarVisibility(boolean visible);
172ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes
173ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes    abstract void setSupportProgressBarIndeterminateVisibility(boolean visible);
174ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes
175ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes    abstract void setSupportProgressBarIndeterminate(boolean indeterminate);
176ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes
177ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes    abstract void setSupportProgress(int progress);
178ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes
17945d973fcc4c43f5ea00cddd3d9b947d9e8d8fc4eChris Banes    abstract ActionBarDrawerToggle.Delegate getDrawerToggleDelegate();
18045d973fcc4c43f5ea00cddd3d9b947d9e8d8fc4eChris Banes
181d64322f4b9686fabfd5a03f402d50a8e3fe5adedChris Banes    abstract void onContentChanged();
182d64322f4b9686fabfd5a03f402d50a8e3fe5adedChris Banes
1833954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes    protected final String getUiOptionsFromMetadata() {
1843954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes        try {
1853954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes            PackageManager pm = mActivity.getPackageManager();
1863954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes            ActivityInfo info = pm.getActivityInfo(mActivity.getComponentName(),
1873954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes                    PackageManager.GET_META_DATA);
1883954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
1893954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes            String uiOptions = null;
1903954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes            if (info.metaData != null) {
1913954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes                uiOptions = info.metaData.getString(METADATA_UI_OPTIONS);
1923954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes            }
1933954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes            return uiOptions;
1943954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes        } catch (PackageManager.NameNotFoundException e) {
1953954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes            Log.e(TAG, "getUiOptionsFromMetadata: Activity '" + mActivity.getClass()
1963954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes                    .getSimpleName() + "' not in manifest");
1973954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes            return null;
1983954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes        }
1993954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes    }
2003954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes
201d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes    protected final Context getActionBarThemedContext() {
202d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes        Context context = mActivity;
203d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes
204d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes        // If we have an action bar, initialize the menu with a context themed from it.
2055a2bcc375e046c5b6644dcc4d331d3fca0778aedChris Banes        ActionBar ab = getSupportActionBar();
206d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes        if (ab != null) {
207d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes            context = ab.getThemedContext();
208d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes        }
209d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes        return context;
210d8222dedaacae30fa03bee346ebf42ee75b39928Chris Banes    }
2113954d59cb6073615ead9dd34cbdba9e16b8c5b6fChris Banes}
212