GalleryActionBar.java revision a2ce811cb505d579112f5e3c4ecb030d8252371e
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 17package com.android.gallery3d.app; 18 19import android.annotation.TargetApi; 20import android.app.ActionBar; 21import android.app.ActionBar.OnMenuVisibilityListener; 22import android.app.ActionBar.OnNavigationListener; 23import android.app.Activity; 24import android.app.AlertDialog; 25import android.content.Context; 26import android.content.DialogInterface; 27import android.content.Intent; 28import android.content.res.Resources; 29import android.view.LayoutInflater; 30import android.view.Menu; 31import android.view.MenuItem; 32import android.view.View; 33import android.view.ViewGroup; 34import android.widget.BaseAdapter; 35import android.widget.ShareActionProvider; 36import android.widget.TextView; 37import android.widget.TwoLineListItem; 38 39import com.android.gallery3d.R; 40import com.android.gallery3d.common.ApiHelper; 41 42import java.util.ArrayList; 43 44public class GalleryActionBar implements OnNavigationListener { 45 @SuppressWarnings("unused") 46 private static final String TAG = "GalleryActionBar"; 47 48 private ClusterRunner mClusterRunner; 49 private CharSequence[] mTitles; 50 private ArrayList<Integer> mActions; 51 private Context mContext; 52 private LayoutInflater mInflater; 53 private AbstractGalleryActivity mActivity; 54 private ActionBar mActionBar; 55 private int mCurrentIndex; 56 private ClusterAdapter mAdapter = new ClusterAdapter(); 57 58 private AlbumModeAdapter mAlbumModeAdapter; 59 private OnAlbumModeSelectedListener mAlbumModeListener; 60 private CharSequence [] mAlbumModes; 61 public static final int ALBUM_FILMSTRIP_MODE_SELECTED = 0; 62 public static final int ALBUM_GRID_MODE_SELECTED = 1; 63 64 public interface ClusterRunner { 65 public void doCluster(int id); 66 } 67 68 public interface OnAlbumModeSelectedListener { 69 public void onAlbumModeSelected(int mode); 70 } 71 72 private static class ActionItem { 73 public int action; 74 public boolean enabled; 75 public boolean visible; 76 public int spinnerTitle; 77 public int dialogTitle; 78 public int clusterBy; 79 80 public ActionItem(int action, boolean applied, boolean enabled, int title, 81 int clusterBy) { 82 this(action, applied, enabled, title, title, clusterBy); 83 } 84 85 public ActionItem(int action, boolean applied, boolean enabled, int spinnerTitle, 86 int dialogTitle, int clusterBy) { 87 this.action = action; 88 this.enabled = enabled; 89 this.spinnerTitle = spinnerTitle; 90 this.dialogTitle = dialogTitle; 91 this.clusterBy = clusterBy; 92 this.visible = true; 93 } 94 } 95 96 private static final ActionItem[] sClusterItems = new ActionItem[] { 97 new ActionItem(FilterUtils.CLUSTER_BY_ALBUM, true, false, R.string.albums, 98 R.string.group_by_album), 99 new ActionItem(FilterUtils.CLUSTER_BY_LOCATION, true, false, 100 R.string.locations, R.string.location, R.string.group_by_location), 101 new ActionItem(FilterUtils.CLUSTER_BY_TIME, true, false, R.string.times, 102 R.string.time, R.string.group_by_time), 103 new ActionItem(FilterUtils.CLUSTER_BY_FACE, true, false, R.string.people, 104 R.string.group_by_faces), 105 new ActionItem(FilterUtils.CLUSTER_BY_TAG, true, false, R.string.tags, 106 R.string.group_by_tags) 107 }; 108 109 private class ClusterAdapter extends BaseAdapter { 110 111 @Override 112 public int getCount() { 113 return sClusterItems.length; 114 } 115 116 @Override 117 public Object getItem(int position) { 118 return sClusterItems[position]; 119 } 120 121 @Override 122 public long getItemId(int position) { 123 return sClusterItems[position].action; 124 } 125 126 @Override 127 public View getView(int position, View convertView, ViewGroup parent) { 128 if (convertView == null) { 129 convertView = mInflater.inflate(R.layout.action_bar_text, 130 parent, false); 131 } 132 TextView view = (TextView) convertView; 133 view.setText(sClusterItems[position].spinnerTitle); 134 return convertView; 135 } 136 } 137 138 private class AlbumModeAdapter extends BaseAdapter { 139 @Override 140 public int getCount() { 141 return mAlbumModes.length; 142 } 143 144 @Override 145 public Object getItem(int position) { 146 return mAlbumModes[position]; 147 } 148 149 @Override 150 public long getItemId(int position) { 151 return position; 152 } 153 154 @Override 155 public View getView(int position, View convertView, ViewGroup parent) { 156 if (convertView == null) { 157 convertView = mInflater.inflate(R.layout.action_bar_two_line_text, 158 parent, false); 159 } 160 TwoLineListItem view = (TwoLineListItem) convertView; 161 view.getText1().setText(mActionBar.getTitle()); 162 view.getText2().setText((CharSequence) getItem(position)); 163 return convertView; 164 } 165 166 @Override 167 public View getDropDownView(int position, View convertView, ViewGroup parent) { 168 if (convertView == null) { 169 convertView = mInflater.inflate(R.layout.action_bar_text, 170 parent, false); 171 } 172 TextView view = (TextView) convertView; 173 view.setText((CharSequence) getItem(position)); 174 return convertView; 175 } 176 } 177 178 public static String getClusterByTypeString(Context context, int type) { 179 for (ActionItem item : sClusterItems) { 180 if (item.action == type) { 181 return context.getString(item.clusterBy); 182 } 183 } 184 return null; 185 } 186 187 public GalleryActionBar(AbstractGalleryActivity activity) { 188 mActionBar = activity.getActionBar(); 189 mContext = activity.getAndroidContext(); 190 mActivity = activity; 191 mInflater = ((Activity) mActivity).getLayoutInflater(); 192 mCurrentIndex = 0; 193 } 194 195 private void createDialogData() { 196 ArrayList<CharSequence> titles = new ArrayList<CharSequence>(); 197 mActions = new ArrayList<Integer>(); 198 for (ActionItem item : sClusterItems) { 199 if (item.enabled && item.visible) { 200 titles.add(mContext.getString(item.dialogTitle)); 201 mActions.add(item.action); 202 } 203 } 204 mTitles = new CharSequence[titles.size()]; 205 titles.toArray(mTitles); 206 } 207 208 public int getHeight() { 209 return mActionBar != null ? mActionBar.getHeight() : 0; 210 } 211 212 public void setClusterItemEnabled(int id, boolean enabled) { 213 for (ActionItem item : sClusterItems) { 214 if (item.action == id) { 215 item.enabled = enabled; 216 return; 217 } 218 } 219 } 220 221 public void setClusterItemVisibility(int id, boolean visible) { 222 for (ActionItem item : sClusterItems) { 223 if (item.action == id) { 224 item.visible = visible; 225 return; 226 } 227 } 228 } 229 230 public int getClusterTypeAction() { 231 return sClusterItems[mCurrentIndex].action; 232 } 233 234 public void enableClusterMenu(int action, ClusterRunner runner) { 235 if (mActionBar != null) { 236 // Don't set cluster runner until action bar is ready. 237 mClusterRunner = null; 238 mActionBar.setListNavigationCallbacks(mAdapter, this); 239 mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); 240 setSelectedAction(action); 241 mClusterRunner = runner; 242 } 243 } 244 245 // The only use case not to hideMenu in this method is to ensure 246 // all elements disappear at the same time when exiting gallery. 247 // hideMenu should always be true in all other cases. 248 public void disableClusterMenu(boolean hideMenu) { 249 if (mActionBar != null) { 250 mClusterRunner = null; 251 if (hideMenu) { 252 mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); 253 } 254 } 255 } 256 257 public void enableAlbumModeMenu(int selected, OnAlbumModeSelectedListener listener) { 258 if (mActionBar != null) { 259 if (mAlbumModeAdapter == null) { 260 // Initialize the album mode options if they haven't been already 261 Resources res = mActivity.getResources(); 262 mAlbumModes = new CharSequence[] { 263 res.getString(R.string.switch_photo_filmstrip), 264 res.getString(R.string.switch_photo_grid)}; 265 mAlbumModeAdapter = new AlbumModeAdapter(); 266 } 267 mAlbumModeListener = null; 268 mActionBar.setListNavigationCallbacks(mAlbumModeAdapter, this); 269 mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); 270 mActionBar.setSelectedNavigationItem(selected); 271 mAlbumModeListener = listener; 272 } 273 } 274 275 public void disableAlbumModeMenu(boolean hideMenu) { 276 if (mActionBar != null) { 277 mAlbumModeListener = null; 278 if (hideMenu) { 279 mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); 280 } 281 } 282 } 283 284 public void showClusterDialog(final ClusterRunner clusterRunner) { 285 createDialogData(); 286 final ArrayList<Integer> actions = mActions; 287 new AlertDialog.Builder(mContext).setTitle(R.string.group_by).setItems( 288 mTitles, new DialogInterface.OnClickListener() { 289 @Override 290 public void onClick(DialogInterface dialog, int which) { 291 // Need to lock rendering when operations invoked by system UI (main thread) are 292 // modifying slot data used in GL thread for rendering. 293 mActivity.getGLRoot().lockRenderThread(); 294 try { 295 clusterRunner.doCluster(actions.get(which).intValue()); 296 } finally { 297 mActivity.getGLRoot().unlockRenderThread(); 298 } 299 } 300 }).create().show(); 301 } 302 303 @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) 304 private void setHomeButtonEnabled(boolean enabled) { 305 if (mActionBar != null) mActionBar.setHomeButtonEnabled(enabled); 306 } 307 308 public void setDisplayOptions(boolean displayHomeAsUp, boolean showTitle) { 309 if (mActionBar == null) return; 310 int options = 0; 311 if (displayHomeAsUp) options |= ActionBar.DISPLAY_HOME_AS_UP; 312 if (showTitle) options |= ActionBar.DISPLAY_SHOW_TITLE; 313 314 mActionBar.setDisplayOptions(options, 315 ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE); 316 mActionBar.setHomeButtonEnabled(displayHomeAsUp); 317 } 318 319 public void setTitle(String title) { 320 if (mActionBar != null) mActionBar.setTitle(title); 321 } 322 323 public void setTitle(int titleId) { 324 if (mActionBar != null) { 325 mActionBar.setTitle(mContext.getString(titleId)); 326 } 327 } 328 329 public void setSubtitle(String title) { 330 if (mActionBar != null) mActionBar.setSubtitle(title); 331 } 332 333 public void show() { 334 if (mActionBar != null) mActionBar.show(); 335 } 336 337 public void hide() { 338 if (mActionBar != null) mActionBar.hide(); 339 } 340 341 public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) { 342 if (mActionBar != null) mActionBar.addOnMenuVisibilityListener(listener); 343 } 344 345 public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) { 346 if (mActionBar != null) mActionBar.removeOnMenuVisibilityListener(listener); 347 } 348 349 public boolean setSelectedAction(int type) { 350 if (mActionBar == null) return false; 351 352 for (int i = 0, n = sClusterItems.length; i < n; i++) { 353 ActionItem item = sClusterItems[i]; 354 if (item.action == type) { 355 mActionBar.setSelectedNavigationItem(i); 356 mCurrentIndex = i; 357 return true; 358 } 359 } 360 return false; 361 } 362 363 @Override 364 public boolean onNavigationItemSelected(int itemPosition, long itemId) { 365 if (itemPosition != mCurrentIndex && mClusterRunner != null 366 || mAlbumModeListener != null) { 367 // Need to lock rendering when operations invoked by system UI (main thread) are 368 // modifying slot data used in GL thread for rendering. 369 mActivity.getGLRoot().lockRenderThread(); 370 try { 371 if (mAlbumModeListener != null) { 372 mAlbumModeListener.onAlbumModeSelected(itemPosition); 373 } else { 374 mClusterRunner.doCluster(sClusterItems[itemPosition].action); 375 } 376 } finally { 377 mActivity.getGLRoot().unlockRenderThread(); 378 } 379 } 380 return false; 381 } 382 383 private Menu mActionBarMenu; 384 private ShareActionProvider mSharePanoramaActionProvider; 385 private ShareActionProvider mShareActionProvider; 386 387 public void createActionBarMenu(int menuRes, Menu menu) { 388 mActivity.getMenuInflater().inflate(menuRes, menu); 389 mActionBarMenu = menu; 390 391 MenuItem item = menu.findItem(R.id.action_share_panorama); 392 if (item != null) { 393 mSharePanoramaActionProvider = (ShareActionProvider) 394 item.getActionProvider(); 395 mSharePanoramaActionProvider 396 .setShareHistoryFileName("panorama_share_history.xml"); 397 } 398 399 item = menu.findItem(R.id.action_share); 400 if (item != null) { 401 mShareActionProvider = (ShareActionProvider) 402 item.getActionProvider(); 403 mShareActionProvider 404 .setShareHistoryFileName("share_history.xml"); 405 } 406 } 407 408 public Menu getMenu() { 409 return mActionBarMenu; 410 } 411 412 public void setShareIntents(Intent sharePanoramaIntent, Intent shareIntent) { 413 if (mSharePanoramaActionProvider != null) { 414 mSharePanoramaActionProvider.setShareIntent(sharePanoramaIntent); 415 } 416 if (mShareActionProvider != null) { 417 mShareActionProvider.setShareIntent(shareIntent); 418 } 419 } 420} 421