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