GalleryActionBar.java revision ee899c09c88e5b054397ac44ad20e5055cd24f39
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.Activity; 21import android.app.AlertDialog; 22import android.content.Context; 23import android.content.DialogInterface; 24import android.content.Intent; 25import android.content.res.Resources; 26import android.text.TextUtils.TruncateAt; 27import android.view.LayoutInflater; 28import android.view.View; 29import android.view.ViewGroup; 30import android.widget.BaseAdapter; 31import android.widget.TextView; 32 33import com.actionbarsherlock.app.ActionBar; 34import com.actionbarsherlock.app.ActionBar.OnMenuVisibilityListener; 35import com.actionbarsherlock.app.ActionBar.OnNavigationListener; 36import com.actionbarsherlock.view.Menu; 37import com.actionbarsherlock.view.MenuItem; 38import com.actionbarsherlock.widget.ShareActionProvider; 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 private View getView(CharSequence label, View convertView, 155 ViewGroup parent, boolean ellipsize) { 156 if (convertView == null) { 157 convertView = mInflater.inflate(R.layout.action_bar_text, 158 parent, false); 159 } 160 TextView view = (TextView) convertView; 161 view.setEllipsize(ellipsize ? TruncateAt.END : null); 162 view.setText(label); 163 return convertView; 164 } 165 166 @Override 167 public View getView(int position, View convertView, ViewGroup parent) { 168 return getView(mActionBar.getTitle(), convertView, parent, true); 169 } 170 171 @Override 172 public View getDropDownView(int position, View convertView, ViewGroup parent) { 173 return getView((CharSequence) getItem(position), convertView, parent, false); 174 } 175 } 176 177 public static String getClusterByTypeString(Context context, int type) { 178 for (ActionItem item : sClusterItems) { 179 if (item.action == type) { 180 return context.getString(item.clusterBy); 181 } 182 } 183 return null; 184 } 185 186 public GalleryActionBar(AbstractGalleryActivity activity) { 187 mActionBar = activity.getSupportActionBar(); 188 mContext = activity.getAndroidContext(); 189 mActivity = activity; 190 mInflater = ((Activity) mActivity).getLayoutInflater(); 191 mCurrentIndex = 0; 192 } 193 194 private void createDialogData() { 195 ArrayList<CharSequence> titles = new ArrayList<CharSequence>(); 196 mActions = new ArrayList<Integer>(); 197 for (ActionItem item : sClusterItems) { 198 if (item.enabled && item.visible) { 199 titles.add(mContext.getString(item.dialogTitle)); 200 mActions.add(item.action); 201 } 202 } 203 mTitles = new CharSequence[titles.size()]; 204 titles.toArray(mTitles); 205 } 206 207 public int getHeight() { 208 return mActionBar != null ? mActionBar.getHeight() : 0; 209 } 210 211 public void setClusterItemEnabled(int id, boolean enabled) { 212 for (ActionItem item : sClusterItems) { 213 if (item.action == id) { 214 item.enabled = enabled; 215 return; 216 } 217 } 218 } 219 220 public void setClusterItemVisibility(int id, boolean visible) { 221 for (ActionItem item : sClusterItems) { 222 if (item.action == id) { 223 item.visible = visible; 224 return; 225 } 226 } 227 } 228 229 public int getClusterTypeAction() { 230 return sClusterItems[mCurrentIndex].action; 231 } 232 233 public void enableClusterMenu(int action, ClusterRunner runner) { 234 if (mActionBar != null) { 235 // Don't set cluster runner until action bar is ready. 236 mClusterRunner = null; 237 mActionBar.setListNavigationCallbacks(mAdapter, this); 238 mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); 239 setSelectedAction(action); 240 mClusterRunner = runner; 241 } 242 } 243 244 // The only use case not to hideMenu in this method is to ensure 245 // all elements disappear at the same time when exiting gallery. 246 // hideMenu should always be true in all other cases. 247 public void disableClusterMenu(boolean hideMenu) { 248 if (mActionBar != null) { 249 mClusterRunner = null; 250 if (hideMenu) { 251 mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); 252 } 253 } 254 } 255 256 public void enableAlbumModeMenu(int selected, OnAlbumModeSelectedListener listener) { 257 if (mActionBar != null) { 258 if (mAlbumModeAdapter == null) { 259 // Initialize the album mode options if they haven't been already 260 Resources res = mActivity.getResources(); 261 mAlbumModes = new CharSequence[] { 262 res.getString(R.string.switch_photo_filmstrip), 263 res.getString(R.string.switch_photo_grid)}; 264 mAlbumModeAdapter = new AlbumModeAdapter(); 265 } 266 mAlbumModeListener = null; 267 mActionBar.setListNavigationCallbacks(mAlbumModeAdapter, this); 268 mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); 269 mActionBar.setSelectedNavigationItem(selected); 270 mAlbumModeListener = listener; 271 } 272 } 273 274 public void disableAlbumModeMenu(boolean hideMenu) { 275 if (mActionBar != null) { 276 mAlbumModeListener = null; 277 if (hideMenu) { 278 mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); 279 } 280 } 281 } 282 283 public void showClusterDialog(final ClusterRunner clusterRunner) { 284 createDialogData(); 285 final ArrayList<Integer> actions = mActions; 286 new AlertDialog.Builder(mContext).setTitle(R.string.group_by).setItems( 287 mTitles, new DialogInterface.OnClickListener() { 288 @Override 289 public void onClick(DialogInterface dialog, int which) { 290 // Need to lock rendering when operations invoked by system UI (main thread) are 291 // modifying slot data used in GL thread for rendering. 292 mActivity.getGLRoot().lockRenderThread(); 293 try { 294 clusterRunner.doCluster(actions.get(which).intValue()); 295 } finally { 296 mActivity.getGLRoot().unlockRenderThread(); 297 } 298 } 299 }).create().show(); 300 } 301 302 @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) 303 private void setHomeButtonEnabled(boolean enabled) { 304 if (mActionBar != null) mActionBar.setHomeButtonEnabled(enabled); 305 } 306 307 public void setDisplayOptions(boolean displayHomeAsUp, boolean showTitle) { 308 if (mActionBar == null) return; 309 int options = 0; 310 if (displayHomeAsUp) options |= ActionBar.DISPLAY_HOME_AS_UP; 311 if (showTitle) options |= ActionBar.DISPLAY_SHOW_TITLE; 312 313 mActionBar.setDisplayOptions(options, 314 ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE); 315 mActionBar.setHomeButtonEnabled(displayHomeAsUp); 316 } 317 318 public void setTitle(String title) { 319 if (mActionBar != null) mActionBar.setTitle(title); 320 } 321 322 public void setTitle(int titleId) { 323 if (mActionBar != null) { 324 mActionBar.setTitle(mContext.getString(titleId)); 325 } 326 } 327 328 public void setSubtitle(String title) { 329 if (mActionBar != null) mActionBar.setSubtitle(title); 330 } 331 332 public void show() { 333 if (mActionBar != null) mActionBar.show(); 334 } 335 336 public void hide() { 337 if (mActionBar != null) mActionBar.hide(); 338 } 339 340 public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) { 341 if (mActionBar != null) mActionBar.addOnMenuVisibilityListener(listener); 342 } 343 344 public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) { 345 if (mActionBar != null) mActionBar.removeOnMenuVisibilityListener(listener); 346 } 347 348 public boolean setSelectedAction(int type) { 349 if (mActionBar == null) return false; 350 351 for (int i = 0, n = sClusterItems.length; i < n; i++) { 352 ActionItem item = sClusterItems[i]; 353 if (item.action == type) { 354 mActionBar.setSelectedNavigationItem(i); 355 mCurrentIndex = i; 356 return true; 357 } 358 } 359 return false; 360 } 361 362 @Override 363 public boolean onNavigationItemSelected(int itemPosition, long itemId) { 364 if (itemPosition != mCurrentIndex && mClusterRunner != null 365 || mAlbumModeListener != null) { 366 // Need to lock rendering when operations invoked by system UI (main thread) are 367 // modifying slot data used in GL thread for rendering. 368 mActivity.getGLRoot().lockRenderThread(); 369 try { 370 if (mAlbumModeListener != null) { 371 mAlbumModeListener.onAlbumModeSelected(itemPosition); 372 } else { 373 mClusterRunner.doCluster(sClusterItems[itemPosition].action); 374 } 375 } finally { 376 mActivity.getGLRoot().unlockRenderThread(); 377 } 378 } 379 return false; 380 } 381 382 private Menu mActionBarMenu; 383 private MenuItem mSharePanoramaMenuItem; 384 private MenuItem mShareMenuItem; 385 private ShareActionProvider mSharePanoramaActionProvider; 386 private ShareActionProvider mShareActionProvider; 387 388 public void createActionBarMenu(int menuRes, Menu menu) { 389 mActivity.getSupportMenuInflater().inflate(menuRes, menu); 390 mActionBarMenu = menu; 391 392 mSharePanoramaMenuItem = menu.findItem(R.id.action_share_panorama); 393 mSharePanoramaActionProvider = (ShareActionProvider) 394 mSharePanoramaMenuItem.getActionProvider(); 395 mSharePanoramaActionProvider.setShareHistoryFileName("panorama_share_history.xml"); 396 397 mShareMenuItem = menu.findItem(R.id.action_share); 398 mShareActionProvider = (ShareActionProvider) 399 mShareMenuItem.getActionProvider(); 400 mShareActionProvider.setShareHistoryFileName("share_history.xml"); 401 } 402 403 public Menu getMenu() { 404 return mActionBarMenu; 405 } 406 407 public void setShareIntents(Intent sharePanoramaIntent, Intent shareIntent) { 408 // if panorama sharing is enabled, rename share to share as photo, 409 // and move it to overflow 410 if (mSharePanoramaMenuItem != null) { 411 if (sharePanoramaIntent != null) { 412 mActivity.invalidateOptionsMenu(); 413 mShareMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); 414 mShareMenuItem.setTitle( 415 mContext.getResources().getString(R.string.share_as_photo)); 416 } else { 417 mSharePanoramaMenuItem.setVisible(false); 418 mShareMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); 419 mShareMenuItem.setTitle( 420 mContext.getResources().getString(R.string.share)); 421 } 422 mSharePanoramaActionProvider.setShareIntent(sharePanoramaIntent); 423 } 424 if (mShareMenuItem != null) { 425 mShareActionProvider.setShareIntent(shareIntent); 426 } 427 } 428} 429