GalleryActionBar.java revision b21b8e58a604f6c701245d84b141b5b87663192b
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.view.LayoutInflater;
26import android.view.View;
27import android.view.ViewGroup;
28import android.widget.BaseAdapter;
29import android.widget.TextView;
30
31import com.actionbarsherlock.app.ActionBar;
32import com.actionbarsherlock.app.ActionBar.OnMenuVisibilityListener;
33import com.actionbarsherlock.app.ActionBar.OnNavigationListener;
34import com.actionbarsherlock.view.Menu;
35import com.actionbarsherlock.view.MenuItem;
36import com.actionbarsherlock.widget.ShareActionProvider;
37import com.android.gallery3d.R;
38import com.android.gallery3d.common.ApiHelper;
39
40import java.util.ArrayList;
41
42public class GalleryActionBar implements OnNavigationListener {
43    @SuppressWarnings("unused")
44    private static final String TAG = "GalleryActionBar";
45
46    private ClusterRunner mClusterRunner;
47    private CharSequence[] mTitles;
48    private ArrayList<Integer> mActions;
49    private Context mContext;
50    private LayoutInflater mInflater;
51    private AbstractGalleryActivity mActivity;
52    private ActionBar mActionBar;
53    private int mCurrentIndex;
54    private ClusterAdapter mAdapter = new ClusterAdapter();
55
56    public interface ClusterRunner {
57        public void doCluster(int id);
58    }
59
60    private static class ActionItem {
61        public int action;
62        public boolean enabled;
63        public boolean visible;
64        public int spinnerTitle;
65        public int dialogTitle;
66        public int clusterBy;
67
68        public ActionItem(int action, boolean applied, boolean enabled, int title,
69                int clusterBy) {
70            this(action, applied, enabled, title, title, clusterBy);
71        }
72
73        public ActionItem(int action, boolean applied, boolean enabled, int spinnerTitle,
74                int dialogTitle, int clusterBy) {
75            this.action = action;
76            this.enabled = enabled;
77            this.spinnerTitle = spinnerTitle;
78            this.dialogTitle = dialogTitle;
79            this.clusterBy = clusterBy;
80            this.visible = true;
81        }
82    }
83
84    private static final ActionItem[] sClusterItems = new ActionItem[] {
85        new ActionItem(FilterUtils.CLUSTER_BY_ALBUM, true, false, R.string.albums,
86                R.string.group_by_album),
87        new ActionItem(FilterUtils.CLUSTER_BY_LOCATION, true, false,
88                R.string.locations, R.string.location, R.string.group_by_location),
89        new ActionItem(FilterUtils.CLUSTER_BY_TIME, true, false, R.string.times,
90                R.string.time, R.string.group_by_time),
91        new ActionItem(FilterUtils.CLUSTER_BY_FACE, true, false, R.string.people,
92                R.string.group_by_faces),
93        new ActionItem(FilterUtils.CLUSTER_BY_TAG, true, false, R.string.tags,
94                R.string.group_by_tags)
95    };
96
97    private class ClusterAdapter extends BaseAdapter {
98
99        @Override
100        public int getCount() {
101            return sClusterItems.length;
102        }
103
104        @Override
105        public Object getItem(int position) {
106            return sClusterItems[position];
107        }
108
109        @Override
110        public long getItemId(int position) {
111            return sClusterItems[position].action;
112        }
113
114        @Override
115        public View getView(int position, View convertView, ViewGroup parent) {
116            if (convertView == null) {
117                convertView = mInflater.inflate(R.layout.action_bar_text,
118                        parent, false);
119            }
120            TextView view = (TextView) convertView;
121            view.setText(sClusterItems[position].spinnerTitle);
122            return convertView;
123        }
124    }
125
126    public static String getClusterByTypeString(Context context, int type) {
127        for (ActionItem item : sClusterItems) {
128            if (item.action == type) {
129                return context.getString(item.clusterBy);
130            }
131        }
132        return null;
133    }
134
135    public GalleryActionBar(AbstractGalleryActivity activity) {
136        mActionBar = activity.getSupportActionBar();
137        mContext = activity.getAndroidContext();
138        mActivity = activity;
139        mInflater = ((Activity) mActivity).getLayoutInflater();
140        mCurrentIndex = 0;
141    }
142
143    private void createDialogData() {
144        ArrayList<CharSequence> titles = new ArrayList<CharSequence>();
145        mActions = new ArrayList<Integer>();
146        for (ActionItem item : sClusterItems) {
147            if (item.enabled && item.visible) {
148                titles.add(mContext.getString(item.dialogTitle));
149                mActions.add(item.action);
150            }
151        }
152        mTitles = new CharSequence[titles.size()];
153        titles.toArray(mTitles);
154    }
155
156    public int getHeight() {
157        return mActionBar != null ? mActionBar.getHeight() : 0;
158    }
159
160    public void setClusterItemEnabled(int id, boolean enabled) {
161        for (ActionItem item : sClusterItems) {
162            if (item.action == id) {
163                item.enabled = enabled;
164                return;
165            }
166        }
167    }
168
169    public void setClusterItemVisibility(int id, boolean visible) {
170        for (ActionItem item : sClusterItems) {
171            if (item.action == id) {
172                item.visible = visible;
173                return;
174            }
175        }
176    }
177
178    public int getClusterTypeAction() {
179        return sClusterItems[mCurrentIndex].action;
180    }
181
182    public void enableClusterMenu(int action, ClusterRunner runner) {
183        if (mActionBar != null) {
184            // Don't set cluster runner until action bar is ready.
185            mClusterRunner = null;
186            mActionBar.setListNavigationCallbacks(mAdapter, this);
187            mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
188            setSelectedAction(action);
189            mClusterRunner = runner;
190        }
191    }
192
193    // The only use case not to hideMenu in this method is to ensure
194    // all elements disappear at the same time when exiting gallery.
195    // hideMenu should always be true in all other cases.
196    public void disableClusterMenu(boolean hideMenu) {
197        if (mActionBar != null) {
198            mClusterRunner = null;
199            if (hideMenu) {
200                mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
201            }
202        }
203    }
204
205    public void showClusterDialog(final ClusterRunner clusterRunner) {
206        createDialogData();
207        final ArrayList<Integer> actions = mActions;
208        new AlertDialog.Builder(mContext).setTitle(R.string.group_by).setItems(
209                mTitles, new DialogInterface.OnClickListener() {
210            @Override
211            public void onClick(DialogInterface dialog, int which) {
212                // Need to lock rendering when operations invoked by system UI (main thread) are
213                // modifying slot data used in GL thread for rendering.
214                mActivity.getGLRoot().lockRenderThread();
215                try {
216                    clusterRunner.doCluster(actions.get(which).intValue());
217                } finally {
218                    mActivity.getGLRoot().unlockRenderThread();
219                }
220            }
221        }).create().show();
222    }
223
224    @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
225    private void setHomeButtonEnabled(boolean enabled) {
226        if (mActionBar != null) mActionBar.setHomeButtonEnabled(enabled);
227    }
228
229    public void setDisplayOptions(boolean displayHomeAsUp, boolean showTitle) {
230        if (mActionBar == null) return;
231        int options = 0;
232        if (displayHomeAsUp) options |= ActionBar.DISPLAY_HOME_AS_UP;
233        if (showTitle) options |= ActionBar.DISPLAY_SHOW_TITLE;
234
235        mActionBar.setDisplayOptions(options,
236                ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE);
237        mActionBar.setHomeButtonEnabled(displayHomeAsUp);
238    }
239
240    public void setTitle(String title) {
241        if (mActionBar != null) mActionBar.setTitle(title);
242    }
243
244    public void setTitle(int titleId) {
245        if (mActionBar != null) {
246            mActionBar.setTitle(mContext.getString(titleId));
247        }
248    }
249
250    public void setSubtitle(String title) {
251        if (mActionBar != null) mActionBar.setSubtitle(title);
252    }
253
254    public void show() {
255        if (mActionBar != null) mActionBar.show();
256    }
257
258    public void hide() {
259        if (mActionBar != null) mActionBar.hide();
260    }
261
262    public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
263        if (mActionBar != null) mActionBar.addOnMenuVisibilityListener(listener);
264    }
265
266    public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
267        if (mActionBar != null) mActionBar.removeOnMenuVisibilityListener(listener);
268    }
269
270    public boolean setSelectedAction(int type) {
271        if (mActionBar == null) return false;
272
273        for (int i = 0, n = sClusterItems.length; i < n; i++) {
274            ActionItem item = sClusterItems[i];
275            if (item.action == type) {
276                mActionBar.setSelectedNavigationItem(i);
277                mCurrentIndex = i;
278                return true;
279            }
280        }
281        return false;
282    }
283
284    @Override
285    public boolean onNavigationItemSelected(int itemPosition, long itemId) {
286        if (itemPosition != mCurrentIndex && mClusterRunner != null) {
287            // Need to lock rendering when operations invoked by system UI (main thread) are
288            // modifying slot data used in GL thread for rendering.
289            mActivity.getGLRoot().lockRenderThread();
290            try {
291                mClusterRunner.doCluster(sClusterItems[itemPosition].action);
292            } finally {
293                mActivity.getGLRoot().unlockRenderThread();
294            }
295        }
296        return false;
297    }
298
299    private Menu mActionBarMenu;
300    private MenuItem mShareMenuItem;
301
302    public void createActionBarMenu(int menuRes, Menu menu) {
303        mActivity.getSupportMenuInflater().inflate(menuRes, menu);
304        mActionBarMenu = menu;
305        mShareMenuItem = menu.findItem(R.id.action_share);
306    }
307
308    public Menu getMenu() {
309        return mActionBarMenu;
310    }
311
312    public boolean hasShareMenuItem() {
313        return mShareMenuItem != null;
314    }
315
316    public void setShareIntent(Intent shareIntent) {
317        ((ShareActionProvider) mShareMenuItem.getActionProvider())
318                .setShareIntent(shareIntent);
319    }
320
321    public MenuItem findMenuItem(int itemId) {
322        return mActionBarMenu.findItem(itemId);
323    }
324}
325