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