GalleryActionBar.java revision 1336062985c9824d7fd796b1cebd5eaa8e4163ca
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.text.TextUtils.TruncateAt;
30import android.view.LayoutInflater;
31import android.view.Menu;
32import android.view.MenuItem;
33import android.view.View;
34import android.view.ViewGroup;
35import android.widget.BaseAdapter;
36import android.widget.ShareActionProvider;
37import android.widget.TextView;
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        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.getActionBar();
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.getMenuInflater().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