blob: 447a062e4713605fc30166b5164f653ed3099c57 [file] [log] [blame]
Adam Powell89e06452010-06-23 20:24:52 -07001/*
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
17package com.android.internal.app;
18
Adam Powell2c9c9fe2010-07-16 10:17:57 -070019import com.android.internal.view.menu.MenuBuilder;
Adam Powell2c9c9fe2010-07-16 10:17:57 -070020import com.android.internal.view.menu.MenuPopupHelper;
21import com.android.internal.view.menu.SubMenuBuilder;
Adam Powell89e06452010-06-23 20:24:52 -070022import com.android.internal.widget.ActionBarContextView;
23import com.android.internal.widget.ActionBarView;
24
25import android.app.ActionBar;
Adam Powell661c9082010-07-02 10:09:44 -070026import android.app.Activity;
Adam Powelldec9dfd2010-08-09 15:27:54 -070027import android.app.Dialog;
Adam Powell661c9082010-07-02 10:09:44 -070028import android.app.Fragment;
29import android.app.FragmentTransaction;
Adam Powelldec9dfd2010-08-09 15:27:54 -070030import android.content.Context;
Adam Powell89e06452010-06-23 20:24:52 -070031import android.graphics.drawable.Drawable;
Adam Powell0e94b512010-06-29 17:58:20 -070032import android.os.Handler;
Adam Powell6e346362010-07-23 10:18:23 -070033import android.view.ActionMode;
Adam Powell32555f32010-11-17 13:49:22 -080034import android.view.LayoutInflater;
Adam Powell89e06452010-06-23 20:24:52 -070035import android.view.Menu;
Adam Powell9168f0b2010-08-02 15:46:24 -070036import android.view.MenuInflater;
Adam Powell89e06452010-06-23 20:24:52 -070037import android.view.MenuItem;
38import android.view.View;
39import android.widget.LinearLayout;
40import android.widget.SpinnerAdapter;
41import android.widget.ViewAnimator;
42
Adam Powell29ed7572010-07-14 16:24:56 -070043import java.lang.ref.WeakReference;
Adam Powell661c9082010-07-02 10:09:44 -070044import java.util.ArrayList;
45
Adam Powell89e06452010-06-23 20:24:52 -070046/**
47 * ActionBarImpl is the ActionBar implementation used
48 * by devices of all screen sizes. If it detects a compatible decor,
49 * it will split contextual modes across both the ActionBarView at
50 * the top of the screen and a horizontal LinearLayout at the bottom
51 * which is normally hidden.
52 */
53public class ActionBarImpl extends ActionBar {
54 private static final int NORMAL_VIEW = 0;
55 private static final int CONTEXT_VIEW = 1;
Adam Powell661c9082010-07-02 10:09:44 -070056
Adam Powelldec9dfd2010-08-09 15:27:54 -070057 private Context mContext;
Adam Powell661c9082010-07-02 10:09:44 -070058 private Activity mActivity;
Adam Powelldec9dfd2010-08-09 15:27:54 -070059 private Dialog mDialog;
Adam Powell661c9082010-07-02 10:09:44 -070060
Adam Powell89e06452010-06-23 20:24:52 -070061 private ViewAnimator mAnimatorView;
62 private ActionBarView mActionView;
63 private ActionBarContextView mUpperContextView;
64 private LinearLayout mLowerContextView;
Adam Powell661c9082010-07-02 10:09:44 -070065
66 private ArrayList<TabImpl> mTabs = new ArrayList<TabImpl>();
67
Adam Powell661c9082010-07-02 10:09:44 -070068 private TabImpl mSelectedTab;
Adam Powell0c24a552010-11-03 16:44:11 -070069 private int mSavedTabPosition = INVALID_POSITION;
Adam Powell89e06452010-06-23 20:24:52 -070070
Adam Powell5d279772010-07-27 16:34:07 -070071 private ActionMode mActionMode;
Adam Powell89e06452010-06-23 20:24:52 -070072
Adam Powell8515ee82010-11-30 14:09:55 -080073 private boolean mLastMenuVisibility;
74 private ArrayList<OnMenuVisibilityListener> mMenuVisibilityListeners =
75 new ArrayList<OnMenuVisibilityListener>();
76
Adam Powell89e06452010-06-23 20:24:52 -070077 private static final int CONTEXT_DISPLAY_NORMAL = 0;
78 private static final int CONTEXT_DISPLAY_SPLIT = 1;
79
Adam Powell0c24a552010-11-03 16:44:11 -070080 private static final int INVALID_POSITION = -1;
81
Adam Powell89e06452010-06-23 20:24:52 -070082 private int mContextDisplayMode;
Adam Powell0e94b512010-06-29 17:58:20 -070083
Adam Powell3461b322010-07-14 11:34:43 -070084 private boolean mClosingContext;
85
Adam Powell0e94b512010-06-29 17:58:20 -070086 final Handler mHandler = new Handler();
87 final Runnable mCloseContext = new Runnable() {
88 public void run() {
89 mUpperContextView.closeMode();
90 if (mLowerContextView != null) {
91 mLowerContextView.removeAllViews();
92 }
Adam Powell3461b322010-07-14 11:34:43 -070093 mClosingContext = false;
Adam Powell0e94b512010-06-29 17:58:20 -070094 }
95 };
96
Adam Powell661c9082010-07-02 10:09:44 -070097 public ActionBarImpl(Activity activity) {
Adam Powell661c9082010-07-02 10:09:44 -070098 mActivity = activity;
Adam Powelldec9dfd2010-08-09 15:27:54 -070099 init(activity.getWindow().getDecorView());
100 }
101
102 public ActionBarImpl(Dialog dialog) {
103 mDialog = dialog;
104 init(dialog.getWindow().getDecorView());
105 }
106
107 private void init(View decor) {
108 mContext = decor.getContext();
Adam Powell89e06452010-06-23 20:24:52 -0700109 mActionView = (ActionBarView) decor.findViewById(com.android.internal.R.id.action_bar);
110 mUpperContextView = (ActionBarContextView) decor.findViewById(
111 com.android.internal.R.id.action_context_bar);
112 mLowerContextView = (LinearLayout) decor.findViewById(
113 com.android.internal.R.id.lower_action_context_bar);
114 mAnimatorView = (ViewAnimator) decor.findViewById(
115 com.android.internal.R.id.action_bar_animator);
Steve Block08f194b2010-08-24 18:20:48 +0100116
Adam Powell89e06452010-06-23 20:24:52 -0700117 if (mActionView == null || mUpperContextView == null || mAnimatorView == null) {
118 throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
119 "with a compatible window decor layout");
120 }
Adam Powell0e94b512010-06-29 17:58:20 -0700121
Steve Block08f194b2010-08-24 18:20:48 +0100122 mActionView.setContextView(mUpperContextView);
Adam Powell89e06452010-06-23 20:24:52 -0700123 mContextDisplayMode = mLowerContextView == null ?
124 CONTEXT_DISPLAY_NORMAL : CONTEXT_DISPLAY_SPLIT;
125 }
126
Adam Powell8515ee82010-11-30 14:09:55 -0800127 public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
128 mMenuVisibilityListeners.add(listener);
129 }
130
131 public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
132 mMenuVisibilityListeners.remove(listener);
133 }
134
135 public void dispatchMenuVisibilityChanged(boolean isVisible) {
136 if (isVisible == mLastMenuVisibility) {
137 return;
138 }
139 mLastMenuVisibility = isVisible;
140
141 final int count = mMenuVisibilityListeners.size();
142 for (int i = 0; i < count; i++) {
143 mMenuVisibilityListeners.get(i).onMenuVisibilityChanged(isVisible);
144 }
145 }
146
Adam Powella66c7b02010-07-28 15:28:25 -0700147 @Override
Adam Powella66c7b02010-07-28 15:28:25 -0700148 public void setTitle(int resId) {
Adam Powelldec9dfd2010-08-09 15:27:54 -0700149 setTitle(mContext.getString(resId));
Adam Powella66c7b02010-07-28 15:28:25 -0700150 }
151
152 @Override
153 public void setSubtitle(int resId) {
Adam Powelldec9dfd2010-08-09 15:27:54 -0700154 setSubtitle(mContext.getString(resId));
Adam Powella66c7b02010-07-28 15:28:25 -0700155 }
156
Adam Powell89e06452010-06-23 20:24:52 -0700157 public void setCustomNavigationMode(View view) {
Adam Powell661c9082010-07-02 10:09:44 -0700158 cleanupTabs();
Adam Powell9ab97872010-10-26 21:47:29 -0700159 setCustomView(view);
160 setDisplayOptions(DISPLAY_SHOW_CUSTOM, DISPLAY_SHOW_CUSTOM | DISPLAY_SHOW_TITLE);
161 mActionView.setNavigationMode(NAVIGATION_MODE_STANDARD);
Adam Powell89e06452010-06-23 20:24:52 -0700162 mActionView.setCallback(null);
163 }
Adam Powell0e94b512010-06-29 17:58:20 -0700164
Adam Powell8515ee82010-11-30 14:09:55 -0800165 public void setDropdownNavigationMode(SpinnerAdapter adapter, OnNavigationListener callback) {
Adam Powell17809772010-07-21 13:25:11 -0700166 setDropdownNavigationMode(adapter, callback, -1);
167 }
168
Adam Powell8515ee82010-11-30 14:09:55 -0800169 public void setDropdownNavigationMode(SpinnerAdapter adapter, OnNavigationListener callback,
Adam Powell17809772010-07-21 13:25:11 -0700170 int defaultSelectedPosition) {
Adam Powell661c9082010-07-02 10:09:44 -0700171 cleanupTabs();
Adam Powell9ab97872010-10-26 21:47:29 -0700172 setDisplayOptions(0, DISPLAY_SHOW_CUSTOM | DISPLAY_SHOW_TITLE);
173 mActionView.setNavigationMode(NAVIGATION_MODE_LIST);
174 setListNavigationCallbacks(adapter, callback);
Adam Powell17809772010-07-21 13:25:11 -0700175 if (defaultSelectedPosition >= 0) {
176 mActionView.setDropdownSelectedPosition(defaultSelectedPosition);
177 }
Adam Powell89e06452010-06-23 20:24:52 -0700178 }
Adam Powell0e94b512010-06-29 17:58:20 -0700179
180 public void setStandardNavigationMode() {
Adam Powell661c9082010-07-02 10:09:44 -0700181 cleanupTabs();
Adam Powell9ab97872010-10-26 21:47:29 -0700182 setDisplayOptions(DISPLAY_SHOW_TITLE, DISPLAY_SHOW_TITLE | DISPLAY_SHOW_CUSTOM);
Adam Powell0e94b512010-06-29 17:58:20 -0700183 mActionView.setNavigationMode(NAVIGATION_MODE_STANDARD);
184 mActionView.setCallback(null);
185 }
186
Adam Powell17809772010-07-21 13:25:11 -0700187 public void setSelectedNavigationItem(int position) {
188 switch (mActionView.getNavigationMode()) {
189 case NAVIGATION_MODE_TABS:
190 selectTab(mTabs.get(position));
191 break;
Adam Powell9ab97872010-10-26 21:47:29 -0700192 case NAVIGATION_MODE_LIST:
Adam Powell17809772010-07-21 13:25:11 -0700193 mActionView.setDropdownSelectedPosition(position);
194 break;
195 default:
196 throw new IllegalStateException(
Adam Powell9ab97872010-10-26 21:47:29 -0700197 "setSelectedNavigationIndex not valid for current navigation mode");
Adam Powell17809772010-07-21 13:25:11 -0700198 }
199 }
200
201 public int getSelectedNavigationItem() {
Adam Powell9ab97872010-10-26 21:47:29 -0700202 return getSelectedNavigationIndex();
203 }
204
205 public void removeAllTabs() {
206 cleanupTabs();
Adam Powell17809772010-07-21 13:25:11 -0700207 }
208
Adam Powell661c9082010-07-02 10:09:44 -0700209 private void cleanupTabs() {
210 if (mSelectedTab != null) {
211 selectTab(null);
212 }
Adam Powell2b6230e2010-09-07 17:55:25 -0700213 mTabs.clear();
Adam Powell0c24a552010-11-03 16:44:11 -0700214 mActionView.removeAllTabs();
215 mSavedTabPosition = INVALID_POSITION;
Adam Powell661c9082010-07-02 10:09:44 -0700216 }
217
Adam Powell0e94b512010-06-29 17:58:20 -0700218 public void setTitle(CharSequence title) {
219 mActionView.setTitle(title);
220 }
221
222 public void setSubtitle(CharSequence subtitle) {
223 mActionView.setSubtitle(subtitle);
224 }
225
Adam Powell89e06452010-06-23 20:24:52 -0700226 public void setDisplayOptions(int options) {
227 mActionView.setDisplayOptions(options);
228 }
Adam Powell0e94b512010-06-29 17:58:20 -0700229
Adam Powell89e06452010-06-23 20:24:52 -0700230 public void setDisplayOptions(int options, int mask) {
231 final int current = mActionView.getDisplayOptions();
232 mActionView.setDisplayOptions((options & mask) | (current & ~mask));
233 }
234
235 public void setBackgroundDrawable(Drawable d) {
236 mActionView.setBackgroundDrawable(d);
237 }
238
239 public View getCustomNavigationView() {
Adam Powellef704442010-11-16 14:48:22 -0800240 return getCustomView();
241 }
242
243 public View getCustomView() {
Adam Powell89e06452010-06-23 20:24:52 -0700244 return mActionView.getCustomNavigationView();
245 }
246
247 public CharSequence getTitle() {
248 return mActionView.getTitle();
249 }
250
251 public CharSequence getSubtitle() {
252 return mActionView.getSubtitle();
253 }
254
255 public int getNavigationMode() {
256 return mActionView.getNavigationMode();
257 }
258
259 public int getDisplayOptions() {
260 return mActionView.getDisplayOptions();
261 }
262
Adam Powell5d279772010-07-27 16:34:07 -0700263 public ActionMode startActionMode(ActionMode.Callback callback) {
264 if (mActionMode != null) {
265 mActionMode.finish();
Adam Powell6e346362010-07-23 10:18:23 -0700266 }
Adam Powell3461b322010-07-14 11:34:43 -0700267
268 // Don't wait for the close context mode animation to finish.
269 if (mClosingContext) {
270 mAnimatorView.clearAnimation();
271 mHandler.removeCallbacks(mCloseContext);
272 mCloseContext.run();
273 }
274
Adam Powell5d279772010-07-27 16:34:07 -0700275 ActionMode mode = new ActionModeImpl(callback);
Adam Powell6e346362010-07-23 10:18:23 -0700276 if (callback.onCreateActionMode(mode, mode.getMenu())) {
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700277 mode.invalidate();
278 mUpperContextView.initForMode(mode);
Adam Powell89e06452010-06-23 20:24:52 -0700279 mAnimatorView.setDisplayedChild(CONTEXT_VIEW);
280 if (mLowerContextView != null) {
281 // TODO animate this
282 mLowerContextView.setVisibility(View.VISIBLE);
283 }
Adam Powell5d279772010-07-27 16:34:07 -0700284 mActionMode = mode;
Adam Powellac695c62010-07-20 18:19:27 -0700285 return mode;
Adam Powell89e06452010-06-23 20:24:52 -0700286 }
Adam Powellac695c62010-07-20 18:19:27 -0700287 return null;
Adam Powell89e06452010-06-23 20:24:52 -0700288 }
289
Adam Powell661c9082010-07-02 10:09:44 -0700290 private void configureTab(Tab tab, int position) {
291 final TabImpl tabi = (TabImpl) tab;
Adam Powell2b6230e2010-09-07 17:55:25 -0700292 final ActionBar.TabListener callback = tabi.getCallback();
293
294 if (callback == null) {
295 throw new IllegalStateException("Action Bar Tab must have a Callback");
296 }
Adam Powell661c9082010-07-02 10:09:44 -0700297
298 tabi.setPosition(position);
299 mTabs.add(position, tabi);
300
Adam Powell81b89442010-11-02 17:58:56 -0700301 final int count = mTabs.size();
302 for (int i = position + 1; i < count; i++) {
303 mTabs.get(i).setPosition(i);
Adam Powell661c9082010-07-02 10:09:44 -0700304 }
Adam Powell661c9082010-07-02 10:09:44 -0700305 }
306
307 @Override
308 public void addTab(Tab tab) {
Adam Powell81b89442010-11-02 17:58:56 -0700309 addTab(tab, mTabs.isEmpty());
Adam Powell661c9082010-07-02 10:09:44 -0700310 }
311
312 @Override
Adam Powell2b6230e2010-09-07 17:55:25 -0700313 public void addTab(Tab tab, int position) {
Adam Powell81b89442010-11-02 17:58:56 -0700314 addTab(tab, position, mTabs.isEmpty());
315 }
316
317 @Override
318 public void addTab(Tab tab, boolean setSelected) {
319 mActionView.addTab(tab, setSelected);
320 configureTab(tab, mTabs.size());
321 if (setSelected) {
322 selectTab(tab);
323 }
324 }
325
326 @Override
327 public void addTab(Tab tab, int position, boolean setSelected) {
328 mActionView.addTab(tab, position, setSelected);
Adam Powell661c9082010-07-02 10:09:44 -0700329 configureTab(tab, position);
Adam Powell81b89442010-11-02 17:58:56 -0700330 if (setSelected) {
331 selectTab(tab);
332 }
Adam Powell661c9082010-07-02 10:09:44 -0700333 }
334
335 @Override
336 public Tab newTab() {
337 return new TabImpl();
338 }
339
340 @Override
341 public void removeTab(Tab tab) {
342 removeTabAt(tab.getPosition());
343 }
344
345 @Override
346 public void removeTabAt(int position) {
Adam Powell0c24a552010-11-03 16:44:11 -0700347 int selectedTabPosition = mSelectedTab != null
348 ? mSelectedTab.getPosition() : mSavedTabPosition;
Adam Powell661c9082010-07-02 10:09:44 -0700349 mActionView.removeTabAt(position);
350 mTabs.remove(position);
351
352 final int newTabCount = mTabs.size();
353 for (int i = position; i < newTabCount; i++) {
354 mTabs.get(i).setPosition(i);
355 }
356
Adam Powell0c24a552010-11-03 16:44:11 -0700357 if (selectedTabPosition == position) {
358 selectTab(mTabs.isEmpty() ? null : mTabs.get(Math.max(0, position - 1)));
359 }
Adam Powell661c9082010-07-02 10:09:44 -0700360 }
361
362 @Override
363 public void setTabNavigationMode() {
Adam Powelldec9dfd2010-08-09 15:27:54 -0700364 if (mActivity == null) {
365 throw new IllegalStateException(
366 "Tab navigation mode cannot be used outside of an Activity");
367 }
Adam Powell9ab97872010-10-26 21:47:29 -0700368 setDisplayOptions(0, DISPLAY_SHOW_TITLE | DISPLAY_SHOW_CUSTOM);
Adam Powell661c9082010-07-02 10:09:44 -0700369 mActionView.setNavigationMode(NAVIGATION_MODE_TABS);
370 }
371
372 @Override
Adam Powell661c9082010-07-02 10:09:44 -0700373 public void selectTab(Tab tab) {
Adam Powell0c24a552010-11-03 16:44:11 -0700374 if (getNavigationMode() != NAVIGATION_MODE_TABS) {
375 mSavedTabPosition = tab != null ? tab.getPosition() : INVALID_POSITION;
376 return;
377 }
378
379 final FragmentTransaction trans = mActivity.getFragmentManager().openTransaction()
380 .disallowAddToBackStack();
Adam Powell7f9b9052010-10-19 16:56:07 -0700381
382 if (mSelectedTab == tab) {
383 if (mSelectedTab != null) {
384 mSelectedTab.getCallback().onTabReselected(mSelectedTab, trans);
385 }
386 } else {
387 mActionView.setTabSelected(tab != null ? tab.getPosition() : Tab.INVALID_POSITION);
388 if (mSelectedTab != null) {
389 mSelectedTab.getCallback().onTabUnselected(mSelectedTab, trans);
390 }
391 mSelectedTab = (TabImpl) tab;
392 if (mSelectedTab != null) {
393 mSelectedTab.getCallback().onTabSelected(mSelectedTab, trans);
394 }
Adam Powell2b6230e2010-09-07 17:55:25 -0700395 }
396
397 if (!trans.isEmpty()) {
398 trans.commit();
399 }
400 }
401
402 @Override
403 public Tab getSelectedTab() {
404 return mSelectedTab;
Adam Powell661c9082010-07-02 10:09:44 -0700405 }
406
Adam Powell6b336f82010-08-10 20:13:01 -0700407 @Override
408 public int getHeight() {
409 return mActionView.getHeight();
410 }
411
412 @Override
413 public void show() {
414 // TODO animate!
415 mAnimatorView.setVisibility(View.VISIBLE);
416 }
417
418 @Override
419 public void hide() {
420 // TODO animate!
421 mAnimatorView.setVisibility(View.GONE);
422 }
423
424 public boolean isShowing() {
425 return mAnimatorView.getVisibility() == View.VISIBLE;
426 }
427
Adam Powell89e06452010-06-23 20:24:52 -0700428 /**
429 * @hide
430 */
Adam Powell5d279772010-07-27 16:34:07 -0700431 public class ActionModeImpl extends ActionMode implements MenuBuilder.Callback {
Adam Powell6e346362010-07-23 10:18:23 -0700432 private ActionMode.Callback mCallback;
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700433 private MenuBuilder mMenu;
Adam Powell29ed7572010-07-14 16:24:56 -0700434 private WeakReference<View> mCustomView;
Adam Powell89e06452010-06-23 20:24:52 -0700435
Adam Powell5d279772010-07-27 16:34:07 -0700436 public ActionModeImpl(ActionMode.Callback callback) {
Adam Powell89e06452010-06-23 20:24:52 -0700437 mCallback = callback;
Adam Powell4d9861e2010-08-17 11:14:40 -0700438 mMenu = new MenuBuilder(mActionView.getContext())
439 .setDefaultShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700440 mMenu.setCallback(this);
Adam Powell89e06452010-06-23 20:24:52 -0700441 }
Adam Powell9168f0b2010-08-02 15:46:24 -0700442
443 @Override
444 public MenuInflater getMenuInflater() {
Adam Powell4d9861e2010-08-17 11:14:40 -0700445 return new MenuInflater(mContext);
Adam Powell9168f0b2010-08-02 15:46:24 -0700446 }
447
Adam Powell89e06452010-06-23 20:24:52 -0700448 @Override
449 public Menu getMenu() {
450 return mMenu;
451 }
452
453 @Override
454 public void finish() {
Adam Powell5d279772010-07-27 16:34:07 -0700455 if (mActionMode != this) {
456 // Not the active action mode - no-op
Adam Powell93b6bc32010-07-22 11:36:35 -0700457 return;
458 }
459
Adam Powell6e346362010-07-23 10:18:23 -0700460 mCallback.onDestroyActionMode(this);
Adam Powell89e06452010-06-23 20:24:52 -0700461 mAnimatorView.setDisplayedChild(NORMAL_VIEW);
Adam Powell0e94b512010-06-29 17:58:20 -0700462
463 // Clear out the context mode views after the animation finishes
Adam Powell3461b322010-07-14 11:34:43 -0700464 mClosingContext = true;
Adam Powell0e94b512010-06-29 17:58:20 -0700465 mHandler.postDelayed(mCloseContext, mAnimatorView.getOutAnimation().getDuration());
466
Adam Powell89e06452010-06-23 20:24:52 -0700467 if (mLowerContextView != null && mLowerContextView.getVisibility() != View.GONE) {
468 // TODO Animate this
469 mLowerContextView.setVisibility(View.GONE);
470 }
Adam Powell5d279772010-07-27 16:34:07 -0700471 mActionMode = null;
Adam Powell89e06452010-06-23 20:24:52 -0700472 }
473
474 @Override
475 public void invalidate() {
Adam Powell6e346362010-07-23 10:18:23 -0700476 if (mCallback.onPrepareActionMode(this, mMenu)) {
Adam Powell89e06452010-06-23 20:24:52 -0700477 // Refresh content in both context views
478 }
479 }
480
481 @Override
482 public void setCustomView(View view) {
483 mUpperContextView.setCustomView(view);
Adam Powell29ed7572010-07-14 16:24:56 -0700484 mCustomView = new WeakReference<View>(view);
Adam Powell89e06452010-06-23 20:24:52 -0700485 }
486
487 @Override
488 public void setSubtitle(CharSequence subtitle) {
489 mUpperContextView.setSubtitle(subtitle);
490 }
491
492 @Override
493 public void setTitle(CharSequence title) {
494 mUpperContextView.setTitle(title);
495 }
Adam Powell29ed7572010-07-14 16:24:56 -0700496
497 @Override
Adam Powellc9ae2a22010-07-28 14:44:21 -0700498 public void setTitle(int resId) {
499 setTitle(mActivity.getString(resId));
500 }
501
502 @Override
503 public void setSubtitle(int resId) {
504 setSubtitle(mActivity.getString(resId));
505 }
506
507 @Override
Adam Powell29ed7572010-07-14 16:24:56 -0700508 public CharSequence getTitle() {
509 return mUpperContextView.getTitle();
510 }
511
512 @Override
513 public CharSequence getSubtitle() {
514 return mUpperContextView.getSubtitle();
515 }
Adam Powell89e06452010-06-23 20:24:52 -0700516
Adam Powell29ed7572010-07-14 16:24:56 -0700517 @Override
518 public View getCustomView() {
519 return mCustomView != null ? mCustomView.get() : null;
520 }
521
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700522 public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
Adam Powell6e346362010-07-23 10:18:23 -0700523 return mCallback.onActionItemClicked(this, item);
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700524 }
525
526 public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
527 }
528
529 public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
530 if (!subMenu.hasVisibleItems()) {
531 return true;
Adam Powell89e06452010-06-23 20:24:52 -0700532 }
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700533
Adam Powelldec9dfd2010-08-09 15:27:54 -0700534 new MenuPopupHelper(mContext, subMenu).show();
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700535 return true;
536 }
537
538 public void onCloseSubMenu(SubMenuBuilder menu) {
539 }
540
541 public void onMenuModeChange(MenuBuilder menu) {
Adam Powellf6148c52010-08-11 21:10:16 -0700542 invalidate();
Adam Powell8515ee82010-11-30 14:09:55 -0800543 mUpperContextView.openOverflowMenu();
Adam Powell2c9c9fe2010-07-16 10:17:57 -0700544 }
Adam Powell661c9082010-07-02 10:09:44 -0700545 }
546
547 /**
548 * @hide
549 */
550 public class TabImpl extends ActionBar.Tab {
Adam Powell2b6230e2010-09-07 17:55:25 -0700551 private ActionBar.TabListener mCallback;
552 private Object mTag;
Adam Powell661c9082010-07-02 10:09:44 -0700553 private Drawable mIcon;
554 private CharSequence mText;
555 private int mPosition;
Adam Powell2b6230e2010-09-07 17:55:25 -0700556 private View mCustomView;
Adam Powell661c9082010-07-02 10:09:44 -0700557
558 @Override
Adam Powell2b6230e2010-09-07 17:55:25 -0700559 public Object getTag() {
560 return mTag;
561 }
562
563 @Override
Adam Powell9ab97872010-10-26 21:47:29 -0700564 public Tab setTag(Object tag) {
Adam Powell2b6230e2010-09-07 17:55:25 -0700565 mTag = tag;
Adam Powell9ab97872010-10-26 21:47:29 -0700566 return this;
Adam Powell2b6230e2010-09-07 17:55:25 -0700567 }
568
569 public ActionBar.TabListener getCallback() {
570 return mCallback;
571 }
572
573 @Override
Adam Powell9ab97872010-10-26 21:47:29 -0700574 public Tab setTabListener(ActionBar.TabListener callback) {
Adam Powell2b6230e2010-09-07 17:55:25 -0700575 mCallback = callback;
Adam Powell9ab97872010-10-26 21:47:29 -0700576 return this;
Adam Powell2b6230e2010-09-07 17:55:25 -0700577 }
578
579 @Override
580 public View getCustomView() {
581 return mCustomView;
582 }
583
584 @Override
Adam Powell9ab97872010-10-26 21:47:29 -0700585 public Tab setCustomView(View view) {
Adam Powell2b6230e2010-09-07 17:55:25 -0700586 mCustomView = view;
Adam Powell9ab97872010-10-26 21:47:29 -0700587 return this;
Adam Powell661c9082010-07-02 10:09:44 -0700588 }
589
590 @Override
Adam Powell32555f32010-11-17 13:49:22 -0800591 public Tab setCustomView(int layoutResId) {
592 return setCustomView(LayoutInflater.from(mContext).inflate(layoutResId, null));
593 }
594
595 @Override
Adam Powell661c9082010-07-02 10:09:44 -0700596 public Drawable getIcon() {
597 return mIcon;
598 }
599
600 @Override
601 public int getPosition() {
602 return mPosition;
603 }
604
605 public void setPosition(int position) {
606 mPosition = position;
607 }
608
609 @Override
610 public CharSequence getText() {
611 return mText;
612 }
613
614 @Override
Adam Powell9ab97872010-10-26 21:47:29 -0700615 public Tab setIcon(Drawable icon) {
Adam Powell661c9082010-07-02 10:09:44 -0700616 mIcon = icon;
Adam Powell9ab97872010-10-26 21:47:29 -0700617 return this;
Adam Powell661c9082010-07-02 10:09:44 -0700618 }
619
620 @Override
Adam Powell32555f32010-11-17 13:49:22 -0800621 public Tab setIcon(int resId) {
622 return setIcon(mContext.getResources().getDrawable(resId));
623 }
624
625 @Override
Adam Powell9ab97872010-10-26 21:47:29 -0700626 public Tab setText(CharSequence text) {
Adam Powell661c9082010-07-02 10:09:44 -0700627 mText = text;
Adam Powell9ab97872010-10-26 21:47:29 -0700628 return this;
Adam Powell661c9082010-07-02 10:09:44 -0700629 }
630
631 @Override
Adam Powell32555f32010-11-17 13:49:22 -0800632 public Tab setText(int resId) {
633 return setText(mContext.getResources().getText(resId));
634 }
635
636 @Override
Adam Powell661c9082010-07-02 10:09:44 -0700637 public void select() {
638 selectTab(this);
Adam Powell89e06452010-06-23 20:24:52 -0700639 }
640 }
Adam Powell9ab97872010-10-26 21:47:29 -0700641
642 @Override
643 public void setCustomView(View view) {
644 mActionView.setCustomNavigationView(view);
645 }
646
647 @Override
648 public void setCustomView(View view, LayoutParams layoutParams) {
649 view.setLayoutParams(layoutParams);
650 mActionView.setCustomNavigationView(view);
651 }
652
653 @Override
Adam Powell8515ee82010-11-30 14:09:55 -0800654 public void setListNavigationCallbacks(SpinnerAdapter adapter, OnNavigationListener callback) {
Adam Powell9ab97872010-10-26 21:47:29 -0700655 mActionView.setDropdownAdapter(adapter);
656 mActionView.setCallback(callback);
657 }
658
659 @Override
660 public int getSelectedNavigationIndex() {
661 switch (mActionView.getNavigationMode()) {
662 case NAVIGATION_MODE_TABS:
Adam Powell04587962010-11-11 22:15:07 -0800663 return mSelectedTab != null ? mSelectedTab.getPosition() : -1;
Adam Powell9ab97872010-10-26 21:47:29 -0700664 case NAVIGATION_MODE_LIST:
665 return mActionView.getDropdownSelectedPosition();
666 default:
667 return -1;
668 }
669 }
670
671 @Override
672 public int getNavigationItemCount() {
673 switch (mActionView.getNavigationMode()) {
674 case NAVIGATION_MODE_TABS:
675 return mTabs.size();
676 case NAVIGATION_MODE_LIST:
677 SpinnerAdapter adapter = mActionView.getDropdownAdapter();
678 return adapter != null ? adapter.getCount() : 0;
679 default:
680 return 0;
681 }
682 }
683
684 @Override
Adam Powell0c24a552010-11-03 16:44:11 -0700685 public int getTabCount() {
686 return mTabs.size();
687 }
688
689 @Override
Adam Powell9ab97872010-10-26 21:47:29 -0700690 public void setNavigationMode(int mode) {
Adam Powell0c24a552010-11-03 16:44:11 -0700691 final int oldMode = mActionView.getNavigationMode();
692 switch (oldMode) {
693 case NAVIGATION_MODE_TABS:
694 mSavedTabPosition = getSelectedNavigationIndex();
695 selectTab(null);
696 break;
697 }
Adam Powell9ab97872010-10-26 21:47:29 -0700698 mActionView.setNavigationMode(mode);
Adam Powell0c24a552010-11-03 16:44:11 -0700699 switch (mode) {
700 case NAVIGATION_MODE_TABS:
701 if (mSavedTabPosition != INVALID_POSITION) {
702 setSelectedNavigationItem(mSavedTabPosition);
703 mSavedTabPosition = INVALID_POSITION;
704 }
705 break;
706 }
Adam Powell9ab97872010-10-26 21:47:29 -0700707 }
708
709 @Override
710 public Tab getTabAt(int index) {
711 return mTabs.get(index);
712 }
Adam Powell0c24a552010-11-03 16:44:11 -0700713
714 /**
715 * This fragment is added when we're keeping a back stack in a tab switch
716 * transaction. We use it to change the selected tab in the action bar view
717 * when we back out.
718 */
719 private class SwitchSelectedTabViewFragment extends Fragment {
720 private int mSelectedTabIndex;
721
722 public SwitchSelectedTabViewFragment(int oldSelectedTab) {
723 mSelectedTabIndex = oldSelectedTab;
724 }
725
726 @Override
727 public void onDetach() {
728 if (mSelectedTabIndex >= 0 && mSelectedTabIndex < getTabCount()) {
729 mActionView.setTabSelected(mSelectedTabIndex);
730 }
731 }
732 }
Adam Powell89e06452010-06-23 20:24:52 -0700733}