OSDN Git Service

Updates to 3D gallery. Build 1203.
[android-x86/packages-apps-Gallery2.git] / src / com / cooliris / media / HudLayer.java
1 package com.cooliris.media;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import javax.microedition.khronos.opengles.GL11;
7
8 import android.app.AlertDialog;
9 import android.content.ComponentName;
10 import android.content.Context;
11 import android.content.Intent;
12 import android.content.pm.ActivityInfo;
13 import android.content.pm.PackageManager;
14 import android.content.pm.ResolveInfo;
15 import android.content.res.Resources;
16 import android.net.Uri;
17 import android.util.FloatMath;
18 import android.view.MotionEvent;
19
20 import com.cooliris.media.MenuBar.Menu;
21 import com.cooliris.media.PopupMenu.Option;
22
23 public final class HudLayer extends Layer {
24     public static final int MODE_NORMAL = 0;
25     public static final int MODE_SELECT = 1;
26
27     private Context mContext;
28     private GridLayer mGridLayer;
29     private final ImageButton mTopRightButton = new ImageButton();
30     private final ImageButton mZoomInButton = new ImageButton();
31     private final ImageButton mZoomOutButton = new ImageButton();
32     private static PathBarLayer sPathBar;
33     private static TimeBar sTimeBar;
34     private MenuBar.Menu[] mNormalBottomMenu = null;
35     private MenuBar.Menu[] mSingleViewIntentBottomMenu = null;
36     private final MenuBar mSelectionMenuBottom;
37     private final MenuBar mSelectionMenuTop;
38     private final MenuBar mFullscreenMenu;
39     private final LoadingLayer mLoadingLayer = new LoadingLayer();
40     private RenderView mView = null;
41
42     private int mMode = MODE_NORMAL;
43
44     // Camera button - launches the camera intent when pressed.
45     private static final int CAMERA_BUTTON_ICON = R.drawable.btn_camera;
46     private static final int CAMERA_BUTTON_ICON_PRESSED = R.drawable.btn_camera_pressed;
47     private static final int ZOOM_IN_ICON = R.drawable.btn_hud_zoom_in_normal;
48     private static final int ZOOM_IN_ICON_PRESSED = R.drawable.btn_hud_zoom_in_pressed;
49     private static final int ZOOM_OUT_ICON = R.drawable.btn_hud_zoom_out_normal;
50     private static final int ZOOM_OUT_ICON_PRESSED = R.drawable.btn_hud_zoom_out_pressed;
51
52     private final Runnable mCameraButtonAction = new Runnable() {
53         public void run() {
54             // Launch the camera intent.
55             Intent intent = new Intent();
56             intent.setClassName("com.android.camera", "com.android.camera.Camera");
57             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
58             mContext.startActivity(intent);
59         }
60     };
61
62     // Grid mode button - switches the media browser to grid mode.
63     private static final int GRID_MODE_ICON = R.drawable.mode_stack;
64     private static final int GRID_MODE_PRESSED_ICON = R.drawable.mode_stack;
65
66     private final Runnable mZoomInButtonAction = new Runnable() {
67         public void run() {
68             mGridLayer.zoomInToSelectedItem();
69             mGridLayer.markDirty(1);
70         }
71     };
72
73     private final Runnable mZoomOutButtonAction = new Runnable() {
74         public void run() {
75             mGridLayer.zoomOutFromSelectedItem();
76             mGridLayer.markDirty(1);
77         }
78     };
79
80     private final Runnable mGridModeButtonAction = new Runnable() {
81         public void run() {
82             mGridLayer.setState(GridLayer.STATE_GRID_VIEW);
83         }
84     };
85
86     /**
87      * Stack mode button - switches the media browser to grid mode.
88      */
89     private static final int STACK_MODE_ICON = R.drawable.mode_grid;
90     private static final int STACK_MODE_PRESSED_ICON = R.drawable.mode_grid;
91     private final Runnable mStackModeButtonAction = new Runnable() {
92         public void run() {
93             mGridLayer.setState(GridLayer.STATE_TIMELINE);
94         }
95     };
96     private float mAlpha;
97     private float mAnimAlpha;
98     private boolean mAutoHide;
99     private float mTimeElapsedSinceFullOpacity;
100     private String mCachedCaption;
101     private String mCachedPosition;
102     private String mCachedCurrentLabel;
103
104     HudLayer(Context context) {
105         mAlpha = 1.0f;
106         if (sTimeBar == null) {
107             sTimeBar = new TimeBar(context);
108             sPathBar = new PathBarLayer();
109         }
110         mTopRightButton.setSize((int) (100 * Gallery.PIXEL_DENSITY), (int) (94 * Gallery.PIXEL_DENSITY));
111
112         mZoomInButton.setSize(43 * Gallery.PIXEL_DENSITY, 43 * Gallery.PIXEL_DENSITY);
113         mZoomOutButton.setSize(43 * Gallery.PIXEL_DENSITY, 43 * Gallery.PIXEL_DENSITY);
114         mZoomInButton.setImages(ZOOM_IN_ICON, ZOOM_IN_ICON_PRESSED);
115         mZoomInButton.setAction(mZoomInButtonAction);
116         mZoomOutButton.setImages(ZOOM_OUT_ICON, ZOOM_OUT_ICON_PRESSED);
117         mZoomOutButton.setAction(mZoomOutButtonAction);
118
119         // The Share submenu is populated dynamically when opened.
120         Resources resources = context.getResources();
121         PopupMenu.Option[] deleteOptions = {
122                 new PopupMenu.Option(context.getResources().getString(R.string.confirm_delete), resources
123                         .getDrawable(R.drawable.icon_delete), new Runnable() {
124                     public void run() {
125                         deleteSelection();
126                     }
127                 }),
128                 new PopupMenu.Option(context.getResources().getString(R.string.cancel), resources
129                         .getDrawable(R.drawable.icon_cancel), new Runnable() {
130                     public void run() {
131
132                     }
133                 }), };
134         mSelectionMenuBottom = new MenuBar(context);
135
136         MenuBar.Menu shareMenu = new MenuBar.Menu.Builder(context.getResources().getString(R.string.share)).icon(
137                 R.drawable.icon_share).onSelect(new Runnable() {
138             public void run() {
139                 updateShareMenu();
140             }
141         }).build();
142
143         MenuBar.Menu deleteMenu = new MenuBar.Menu.Builder(context.getResources().getString(R.string.delete)).icon(
144                 R.drawable.icon_delete).options(deleteOptions).build();
145
146         MenuBar.Menu moreMenu = new MenuBar.Menu.Builder(context.getResources().getString(R.string.more)).icon(
147                 R.drawable.icon_more).onSelect(new Runnable() {
148             public void run() {
149                 buildMoreOptions();
150             }
151         }).build();
152
153         mNormalBottomMenu = new MenuBar.Menu[] { shareMenu, deleteMenu, moreMenu };
154         mSingleViewIntentBottomMenu = new MenuBar.Menu[] { shareMenu, moreMenu };
155
156         mSelectionMenuBottom.setMenus(mNormalBottomMenu);
157         mSelectionMenuTop = new MenuBar(context);
158         mSelectionMenuTop.setMenus(new MenuBar.Menu[] {
159                 new MenuBar.Menu.Builder(context.getResources().getString(R.string.select_all)).onSelect(new Runnable() {
160                     public void run() {
161                         mGridLayer.selectAll();
162                     }
163                 }).build(), new MenuBar.Menu.Builder("").build(),
164                 new MenuBar.Menu.Builder(context.getResources().getString(R.string.deselect_all)).onSelect(new Runnable() {
165                     public void run() {
166                         mGridLayer.deselectOrCancelSelectMode();
167                     }
168                 }).build() });
169         mFullscreenMenu = new MenuBar(context);
170         mFullscreenMenu.setMenus(new MenuBar.Menu[] {
171                 new MenuBar.Menu.Builder(context.getResources().getString(R.string.slideshow)).icon(R.drawable.icon_play)
172                         .onSingleTapUp(new Runnable() {
173                             public void run() {
174                                 if (getAlpha() == 1.0f)
175                                     mGridLayer.startSlideshow();
176                                 else
177                                     setAlpha(1.0f);
178                             }
179                         }).build(), /* new MenuBar.Menu.Builder("").build(), */
180                 new MenuBar.Menu.Builder(context.getResources().getString(R.string.menu)).icon(R.drawable.icon_more)
181                         .onSingleTapUp(new Runnable() {
182                             public void run() {
183                                 if (getAlpha() == 1.0f)
184                                     mGridLayer.enterSelectionMode();
185                                 else
186                                     setAlpha(1.0f);
187                             }
188                         }).build() });
189     }
190     
191     public void setContext(Context context) {
192         if (mContext != context) {
193             mContext = context;
194             sTimeBar.regenerateStringsForContext(context);
195         }
196     }
197
198     private void buildMoreOptions() {
199         ArrayList<MediaBucket> buckets = mGridLayer.getSelectedBuckets();
200
201         int numBuckets = buckets.size();
202         boolean albumMode = false;
203         boolean singleItem = false;
204         boolean isPicasa = false;
205         int mediaType = MediaItem.MEDIA_TYPE_IMAGE;
206         if (numBuckets > 1) {
207             albumMode = true;
208         }
209         if (numBuckets == 1) {
210             MediaBucket bucket = buckets.get(0);
211             MediaSet mediaSet = bucket.mediaSet;
212             if (mediaSet == null) {
213                 return;
214             }
215             isPicasa = mediaSet.mPicasaAlbumId != Shared.INVALID;
216             if (bucket.mediaItems == null || bucket.mediaItems.size() == 0) {
217                 albumMode = true;
218             } else {
219                 ArrayList<MediaItem> items = bucket.mediaItems;
220                 int numItems = items.size();
221                 mediaType = items.get(0).getMediaType();
222                 if (numItems == 1) {
223                     singleItem = true;
224                 } else {
225                     for (int i = 1; i < numItems; ++i) {
226                         if (items.get(0).getMediaType() != mediaType) {
227                             albumMode = true;
228                             break;
229                         }
230                     }
231                 }
232             }
233         }
234
235         Option[] optionAll = new Option[] { new PopupMenu.Option(mContext.getResources().getString(R.string.details), mContext
236                 .getResources().getDrawable(R.drawable.ic_menu_view_details), new Runnable() {
237             public void run() {
238                 ArrayList<MediaBucket> buckets = mGridLayer.getSelectedBuckets();
239                 final AlertDialog.Builder builder = new AlertDialog.Builder((Gallery) mContext);
240                 builder.setTitle(mContext.getResources().getString(R.string.details));
241                 boolean foundDataToDisplay = true;
242
243                 if (buckets == null) {
244                     foundDataToDisplay = false;
245                 } else {
246                     CharSequence[] strings = DetailMode.populateDetailModeStrings(mContext, buckets);
247                     if (strings == null) {
248                         foundDataToDisplay = false;
249                     } else {
250                         builder.setItems(strings, null);
251                     }
252                 }
253
254                 mGridLayer.deselectAll();
255                 if (foundDataToDisplay) {
256                     builder.setNeutralButton(R.string.details_ok, null);
257                     ((Gallery) mContext).getHandler().post(new Runnable() {
258                         public void run() {
259                             builder.show();
260                         }
261                     });
262                 }
263             }
264         }) };
265
266         Option[] optionSingle = new Option[] { new PopupMenu.Option(mContext.getResources().getString(R.string.show_on_map),
267                 mContext.getResources().getDrawable(R.drawable.ic_menu_mapmode), new Runnable() {
268                     public void run() {
269                         ArrayList<MediaBucket> buckets = mGridLayer.getSelectedBuckets();
270                         MediaItem item = MediaBucketList.getFirstItemSelection(buckets);
271                         if (item == null) {
272                             return;
273                         }
274                         mGridLayer.deselectAll();
275                         Util.openMaps(mContext, item.mLatitude, item.mLongitude);
276                     }
277                 }), };
278
279         Option[] optionImageMultiple = new Option[] {
280                 new PopupMenu.Option(mContext.getResources().getString(R.string.rotate_left), mContext.getResources().getDrawable(
281                         R.drawable.ic_menu_rotate_left), new Runnable() {
282                     public void run() {
283                         mGridLayer.rotateSelectedItems(-90.0f);
284                     }
285                 }),
286                 new PopupMenu.Option(mContext.getResources().getString(R.string.rotate_right), mContext.getResources().getDrawable(
287                         R.drawable.ic_menu_rotate_right), new Runnable() {
288                     public void run() {
289                         mGridLayer.rotateSelectedItems(90.0f);
290                     }
291                 }), };
292
293         if (isPicasa) {
294             optionImageMultiple = new Option[] {};
295         }
296         Option[] optionImageSingle;
297         if (isPicasa) {
298             optionImageSingle = new Option[] { new PopupMenu.Option(mContext.getResources().getString(R.string.set_as_wallpaper),
299                     mContext.getResources().getDrawable(R.drawable.ic_menu_set_as), new Runnable() {
300                         public void run() {
301                             ArrayList<MediaBucket> buckets = mGridLayer.getSelectedBuckets();
302                             MediaItem item = MediaBucketList.getFirstItemSelection(buckets);
303                             if (item == null) {
304                                 return;
305                             }
306                             mGridLayer.deselectAll();
307                             if (item.mParentMediaSet.mPicasaAlbumId != Shared.INVALID) {
308                                 final Intent intent = new Intent("android.intent.action.ATTACH_DATA");
309                                 intent.setClassName("com.cooliris.media", "com.cooliris.media.Photographs");
310                                 intent.setData(Uri.parse(item.mContentUri));
311                                 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
312                                 ((Gallery) mContext).startActivityForResult(intent, 0);
313                             }
314                         }
315                     }) };
316         } else {
317             optionImageSingle = new Option[] {
318                     new PopupMenu.Option((isPicasa) ? mContext.getResources().getString(R.string.set_as_wallpaper) : mContext
319                             .getResources().getString(R.string.set_as), mContext.getResources().getDrawable(
320                             R.drawable.ic_menu_set_as), new Runnable() {
321                         public void run() {
322                             ArrayList<MediaBucket> buckets = mGridLayer.getSelectedBuckets();
323                             MediaItem item = MediaBucketList.getFirstItemSelection(buckets);
324                             if (item == null) {
325                                 return;
326                             }
327                             mGridLayer.deselectAll();
328                             if (item.mParentMediaSet.mPicasaAlbumId != Shared.INVALID) {
329                                 final Intent intent = new Intent("android.intent.action.ATTACH_DATA");
330                                 intent.setClassName("com.cooliris.media", "com.cooliris.media.Photographs");
331                                 intent.setData(Uri.parse(item.mContentUri));
332                                 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
333                                 ((Gallery) mContext).startActivityForResult(intent, 0);
334                             } else {
335                                 Intent intent = Util.createSetAsIntent(Uri.parse(item.mContentUri), item.mMimeType);
336                                 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
337                                 ((Gallery) mContext).startActivity(Intent.createChooser(intent, ((Gallery) mContext)
338                                         .getText(R.string.set_image)));
339                             }
340                         }
341                     }),
342                     new PopupMenu.Option(mContext.getResources().getString(R.string.crop), mContext.getResources().getDrawable(
343                             R.drawable.ic_menu_crop), new Runnable() {
344                         public void run() {
345                             ArrayList<MediaBucket> buckets = mGridLayer.getSelectedBuckets();
346                             MediaItem item = MediaBucketList.getFirstItemSelection(buckets);
347                             if (item == null) {
348                                 return;
349                             }
350                             mGridLayer.deselectAll();
351                             final Intent intent = new Intent("com.android.camera.action.CROP");
352                             intent.setClassName("com.cooliris.media", "com.cooliris.media.CropImage");
353                             intent.setData(Uri.parse(item.mContentUri));
354                             ((Gallery) mContext).startActivityForResult(intent, Gallery.CROP_MSG_INTERNAL);
355                         }
356                     }) };
357         }
358         Option[] options = optionAll;
359         if (!albumMode) {
360             if (!singleItem) {
361                 if (mediaType == MediaItem.MEDIA_TYPE_IMAGE)
362                     options = concat(options, optionImageMultiple);
363             } else {
364                 MediaItem item = MediaBucketList.getFirstItemSelection(buckets);
365                 if (item.mLatitude != 0.0f && item.mLongitude != 0.0f) {
366                     options = concat(options, optionSingle);
367                 }
368                 if (mediaType == MediaItem.MEDIA_TYPE_IMAGE) {
369                     options = concat(options, optionImageSingle);
370                     options = concat(options, optionImageMultiple);
371                 }
372             }
373         }
374
375         // We are assuming that the more menu is the last item in the menu array.
376         int lastIndex = mSelectionMenuBottom.getMenus().length - 1;
377         mSelectionMenuBottom.getMenus()[lastIndex].options = options;
378     }
379
380     private static final Option[] concat(Option[] A, Option[] B) {
381         Option[] C = (Option[]) new Option[A.length + B.length];
382         System.arraycopy(A, 0, C, 0, A.length);
383         System.arraycopy(B, 0, C, A.length, B.length);
384         return C;
385     }
386
387     public void updateNumItemsSelected(int numItems) {
388         String items = " " + ((numItems == 1) ? mContext.getString(R.string.item) : mContext.getString(R.string.items));
389         Menu menu = new MenuBar.Menu.Builder(numItems + items).config(MenuBar.MENU_TITLE_STYLE_TEXT).build();
390         mSelectionMenuTop.updateMenu(menu, 1);
391     }
392
393     protected void deleteSelection() {
394         mGridLayer.deleteSelection();
395     }
396
397     void setGridLayer(GridLayer layer) {
398         mGridLayer = layer;
399         updateViews();
400     }
401
402     int getMode() {
403         return mMode;
404     }
405
406     void setMode(int mode) {
407         if (mMode != mode) {
408             mMode = mode;
409             updateViews();
410         }
411     }
412
413     @Override
414     protected void onSizeChanged() {
415         final float width = mWidth;
416         final float height = mHeight;
417         closeSelectionMenu();
418
419         sTimeBar.setPosition(0f, height - TimeBar.HEIGHT * Gallery.PIXEL_DENSITY);
420         sTimeBar.setSize(width, TimeBar.HEIGHT * Gallery.PIXEL_DENSITY);
421         mSelectionMenuTop.setPosition(0f, 0);
422         mSelectionMenuTop.setSize(width, MenuBar.HEIGHT * Gallery.PIXEL_DENSITY);
423         mSelectionMenuBottom.setPosition(0f, height - MenuBar.HEIGHT * Gallery.PIXEL_DENSITY);
424         mSelectionMenuBottom.setSize(width, MenuBar.HEIGHT * Gallery.PIXEL_DENSITY);
425
426         mFullscreenMenu.setPosition(0f, height - MenuBar.HEIGHT * Gallery.PIXEL_DENSITY);
427         mFullscreenMenu.setSize(width, MenuBar.HEIGHT * Gallery.PIXEL_DENSITY);
428
429         sPathBar.setPosition(0f, -4f * Gallery.PIXEL_DENSITY);
430         computeSizeForPathbar();
431
432         mTopRightButton.setPosition(width - mTopRightButton.getWidth(), 0f);
433         mZoomInButton.setPosition(width - mZoomInButton.getWidth(), 0f);
434         mZoomOutButton.setPosition(width - mZoomInButton.getWidth(), mZoomInButton.getHeight());
435     }
436
437     private void computeSizeForPathbar() {
438         float pathBarWidth = mWidth
439                 - ((mGridLayer.getState() == GridLayer.STATE_FULL_SCREEN) ? 32 * Gallery.PIXEL_DENSITY
440                         : 120 * Gallery.PIXEL_DENSITY);
441         sPathBar.setSize(pathBarWidth, FloatMath.ceil(39 * Gallery.PIXEL_DENSITY));
442         sPathBar.recomputeComponents();
443     }
444
445     public void setFeed(MediaFeed feed, int state, boolean needsLayout) {
446         sTimeBar.setFeed(feed, state, needsLayout);
447     }
448
449     public void onGridStateChanged() {
450         updateViews();
451     }
452
453     private void updateViews() {
454         if (mGridLayer == null)
455             return;
456         final int state = mGridLayer.getState();
457         // Show the selection menu in selection mode.
458         final boolean selectionMode = mMode == MODE_SELECT;
459         final boolean fullscreenMode = state == GridLayer.STATE_FULL_SCREEN;
460         final boolean stackMode = state == GridLayer.STATE_MEDIA_SETS || state == GridLayer.STATE_TIMELINE;
461         mSelectionMenuTop.setHidden(!selectionMode || fullscreenMode);
462         mSelectionMenuBottom.setHidden(!selectionMode);
463         mFullscreenMenu.setHidden(!fullscreenMode || selectionMode);
464         mZoomInButton.setHidden(mFullscreenMenu.isHidden());
465         mZoomOutButton.setHidden(mFullscreenMenu.isHidden());
466
467         // Show the time bar in stack and grid states, except in selection mode.
468         sTimeBar.setHidden(fullscreenMode || selectionMode || stackMode);
469         // mTimeBar.setHidden(selectionMode || (state != GridLayer.STATE_TIMELINE && state != GridLayer.STATE_GRID_VIEW));
470
471         // Hide the path bar and top-right button in selection mode.
472         sPathBar.setHidden(selectionMode);
473         mTopRightButton.setHidden(selectionMode || fullscreenMode);
474         computeSizeForPathbar();
475
476         // Configure the top-right button.
477         int image = 0;
478         int pressedImage = 0;
479         Runnable action = null;
480         final ImageButton topRightButton = mTopRightButton;
481         int height = (int) (94 * Gallery.PIXEL_DENSITY);
482         switch (state) {
483         case GridLayer.STATE_MEDIA_SETS:
484             image = CAMERA_BUTTON_ICON;
485             pressedImage = CAMERA_BUTTON_ICON_PRESSED;
486             action = mCameraButtonAction;
487             break;
488         case GridLayer.STATE_GRID_VIEW:
489             height /= 2;
490             image = STACK_MODE_ICON;
491             pressedImage = STACK_MODE_PRESSED_ICON;
492             action = mStackModeButtonAction;
493             break;
494         case GridLayer.STATE_TIMELINE:
495             image = GRID_MODE_ICON;
496             pressedImage = GRID_MODE_PRESSED_ICON;
497             action = mGridModeButtonAction;
498             break;
499         default:
500             break;
501         }
502         topRightButton.setSize((int) (100 * Gallery.PIXEL_DENSITY), height);
503         topRightButton.setImages(image, pressedImage);
504         topRightButton.setAction(action);
505     }
506
507     public TimeBar getTimeBar() {
508         return sTimeBar;
509     }
510
511     public PathBarLayer getPathBar() {
512         return sPathBar;
513     }
514
515     public GridLayer getGridLayer() {
516         return mGridLayer;
517     }
518
519     @Override
520     public boolean update(RenderView view, float frameInterval) {
521         float factor = 1.0f;
522         if (mAlpha == 1.0f) {
523             // Speed up the animation when it becomes visible.
524             factor = 4.0f;
525         }
526         mAnimAlpha = FloatUtils.animate(mAnimAlpha, mAlpha, frameInterval * factor);
527         boolean timeElapsedSinceFullOpacity_Reset = mTimeElapsedSinceFullOpacity == 0.0f;
528
529         if (mAutoHide) {
530             if (mAlpha == 1.0f && mMode != MODE_SELECT) {
531                 mTimeElapsedSinceFullOpacity += frameInterval;
532                 if (mTimeElapsedSinceFullOpacity > 5.0f)
533                     setAlpha(0);
534             }
535         }
536         if (mAnimAlpha != mAlpha || (mTimeElapsedSinceFullOpacity < 5.0f && !timeElapsedSinceFullOpacity_Reset))
537             return true;
538
539         return false;
540     }
541
542     public void renderOpaque(RenderView view, GL11 gl) {
543
544     }
545
546     public void renderBlended(RenderView view, GL11 gl) {
547         view.setAlpha(mAnimAlpha);
548     }
549
550     public void setAlpha(float alpha) {
551         float oldAlpha = mAlpha;
552         mAlpha = alpha;
553         if (oldAlpha != alpha) {
554             if (mView != null)
555                 mView.requestRender();
556         }
557         if (alpha == 1.0f) {
558             mTimeElapsedSinceFullOpacity = 0.0f;
559         }
560     }
561
562     public float getAlpha() {
563         return mAlpha;
564     }
565
566     public void setTimeBarTime(long time) {
567         // mTimeBar.setTime(time);
568     }
569
570     @Override
571     public void generate(RenderView view, RenderView.Lists lists) {
572         lists.opaqueList.add(this);
573         lists.blendedList.add(this);
574         lists.hitTestList.add(this);
575         lists.updateList.add(this);
576         mTopRightButton.generate(view, lists);
577         mZoomInButton.generate(view, lists);
578         mZoomOutButton.generate(view, lists);
579         sTimeBar.generate(view, lists);
580         mSelectionMenuTop.generate(view, lists);
581         mSelectionMenuBottom.generate(view, lists);
582         mFullscreenMenu.generate(view, lists);
583         sPathBar.generate(view, lists);
584         // mLoadingLayer.generate(view, lists);
585         mView = view;
586     }
587
588     @Override
589     public boolean containsPoint(float x, float y) {
590         return false;
591     }
592
593     public void cancelSelection() {
594         mSelectionMenuBottom.close();
595         closeSelectionMenu();
596         setMode(MODE_NORMAL);
597     }
598
599     public void closeSelectionMenu() {
600         mSelectionMenuBottom.close();
601     }
602
603     @Override
604     public boolean onTouchEvent(MotionEvent event) {
605         if (mMode == MODE_SELECT) {
606             /*
607              * setMode(MODE_NORMAL); ArrayList<MediaBucket> displayBuckets = mGridLayer.getSelectedBuckets(); // use this list, and
608              * then clear the items return true;
609              */
610             return false;
611         } else {
612             return false;
613         }
614     }
615
616     public boolean isLoaded() {
617         return mLoadingLayer.isLoaded();
618     }
619
620     void reset() {
621         mLoadingLayer.reset();
622         sTimeBar.regenerateStringsForContext(mContext);
623     }
624
625     public void fullscreenSelectionChanged(MediaItem item, int index, int count) {
626         // request = new ReverseGeocoder.Request();
627         // request.firstLatitude = request.secondLatitude = item.latitude;
628         // request.firstLongitude = request.secondLongitude = item.longitude;
629         // mGeo.enqueue(request);
630         if (item == null)
631             return;
632         String location = index + "/" + count;
633         mCachedCaption = item.mCaption;
634         mCachedPosition = location;
635         mCachedCurrentLabel = location;
636         sPathBar.changeLabel(location);
637     }
638
639     private void updateShareMenu() {
640         // Get the first selected item. Wire this up to multiple-item intents when we move
641         // to Eclair.
642         ArrayList<MediaBucket> selection = mGridLayer.getSelectedBuckets();
643         ArrayList<Uri> uris = new ArrayList<Uri>();
644         String mimeType = null;
645         if (!selection.isEmpty()) {
646             int mediaType = Shared.INVALID;
647             int numBuckets = selection.size();
648             for (int j = 0; j < numBuckets; ++j) {
649                 MediaBucket bucket = selection.get(j);
650                 ArrayList<MediaItem> items = null;
651                 int numItems = 0;
652                 if (bucket.mediaItems != null && !bucket.mediaItems.isEmpty()) {
653                     items = bucket.mediaItems;
654                     numItems = items.size();
655                 } else if (bucket.mediaSet != null) {
656                     // We need to delete the entire bucket.
657                     items = bucket.mediaSet.getItems();
658                     numItems = bucket.mediaSet.getNumItems();
659                 }
660                 for (int i = 0; i < numItems; ++i) {
661                     MediaItem item = items.get(i);
662                     if (mimeType == null) {
663                         mimeType = item.mMimeType;
664                         mediaType = item.getMediaType();
665                         MediaSet parentMediaSet = item.mParentMediaSet;
666                         if (parentMediaSet != null && parentMediaSet.mPicasaAlbumId != Shared.INVALID) {
667                             // This will go away once http uri's are supported for all media types.
668                             // This ensures that just the link is shared as a text
669                             mimeType = "text/plain";
670                         }
671                     }
672                     if (mediaType == item.getMediaType()) {
673                         // add this uri
674                         if (item.mContentUri != null) {
675                             Uri uri = Uri.parse(item.mContentUri);
676                             uris.add(uri);
677                         }
678                     }
679                 }
680             }
681         }
682         PopupMenu.Option[] options = null;
683         if (uris.size() != 0) {
684             final Intent intent = new Intent();
685             if (mimeType == null)
686                 mimeType = "image/jpeg";
687             if (mimeType.contains("text")) {
688                 // We need to share this as a text string.
689                 intent.setAction(Intent.ACTION_SEND);
690                 intent.setType(mimeType);
691
692                 // Create a newline-separated list of URLs.
693                 StringBuilder builder = new StringBuilder();
694                 for (int i = 0, size = uris.size(); i < size; ++i) {
695                     builder.append(uris.get(i));
696                     if (i != size - 1) {
697                         builder.append('\n');
698                     }
699                 }
700                 intent.putExtra(Intent.EXTRA_TEXT, builder.toString());
701             } else {
702                 if (uris.size() == 1) {
703                     intent.setAction(Intent.ACTION_SEND);
704                     intent.putExtra(Intent.EXTRA_STREAM, uris.get(0));
705                 } else {
706                     intent.setAction(Intent.ACTION_SEND_MULTIPLE);
707                     intent.putExtra(Intent.EXTRA_STREAM, uris);
708                 }
709                 intent.setType(mimeType);
710             }
711             intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
712
713             // Query the system for matching activities.
714             PackageManager packageManager = mContext.getPackageManager();
715             List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
716             int numActivities = activities.size();
717             options = new PopupMenu.Option[numActivities];
718             for (int i = 0; i != numActivities; ++i) {
719                 final ResolveInfo info = activities.get(i);
720                 String label = info.loadLabel(packageManager).toString();
721                 options[i] = new PopupMenu.Option(label, info.loadIcon(packageManager), new Runnable() {
722                     public void run() {
723                         startResolvedActivity(intent, info);
724                     }
725                 });
726             }
727         }
728         mSelectionMenuBottom.getMenus()[0].options = options;
729     }
730
731     private void startResolvedActivity(Intent intent, ResolveInfo info) {
732         final Intent resolvedIntent = new Intent(intent);
733         ActivityInfo ai = info.activityInfo;
734         resolvedIntent.setComponent(new ComponentName(ai.applicationInfo.packageName, ai.name));
735         ((Gallery) mContext).getHandler().post(new Runnable() {
736             public void run() {
737                 mContext.startActivity(resolvedIntent);
738             }
739         });
740     }
741
742     public void autoHide(boolean hide) {
743         mAutoHide = hide;
744     }
745
746     public void swapFullscreenLabel() {
747         mCachedCurrentLabel = (mCachedCurrentLabel == mCachedCaption || mCachedCaption == null) ? mCachedPosition : mCachedCaption;
748         sPathBar.changeLabel(mCachedCurrentLabel);
749     }
750
751     public void clear() {
752
753     }
754
755     public void enterSelectionMode() {
756         setAlpha(1.0f);
757         setMode(HudLayer.MODE_SELECT);
758         // if we are in single view mode, show the bottom menu without the delete button.
759         if (mGridLayer.noDeleteMode()) {
760             mSelectionMenuBottom.setMenus(mSingleViewIntentBottomMenu);
761         } else {
762             mSelectionMenuBottom.setMenus(mNormalBottomMenu);
763         }
764     }
765     
766     public void computeBottomMenu() {
767         // we need to the same for picasa albums
768         ArrayList<MediaBucket> selection = mGridLayer.getSelectedBuckets();
769         Menu[] menus = mSelectionMenuBottom.getMenus();
770         if (menus == mSingleViewIntentBottomMenu)
771                 return;
772         int numBuckets = selection.size();
773         for (int i = 0; i < numBuckets; ++i) {
774                 MediaBucket bucket = selection.get(i);
775                 if (bucket.mediaSet.mPicasaAlbumId != Shared.INVALID) {
776                         mSelectionMenuBottom.setMenus(mSingleViewIntentBottomMenu);
777                         break;
778                 }
779         }
780     }
781
782     public Layer getMenuBar() {
783         return mFullscreenMenu;
784     }
785 }