1 package com.cooliris.media;
3 import java.util.ArrayList;
4 import javax.microedition.khronos.opengles.GL11;
6 import android.hardware.SensorEvent;
7 import android.opengl.GLU;
8 import android.os.PowerManager;
9 import android.os.PowerManager.WakeLock;
10 import android.view.KeyEvent;
11 import android.view.MotionEvent;
12 import android.content.Context;
14 public final class GridLayer extends RootLayer implements MediaFeed.Listener, TimeBar.Listener {
15 public static final int STATE_MEDIA_SETS = 0;
16 public static final int STATE_GRID_VIEW = 1;
17 public static final int STATE_FULL_SCREEN = 2;
18 public static final int STATE_TIMELINE = 3;
20 public static final int ANCHOR_LEFT = 0;
21 public static final int ANCHOR_RIGHT = 1;
22 public static final int ANCHOR_CENTER = 2;
24 public static final int MAX_ITEMS_PER_SLOT = 12;
25 public static final int MAX_DISPLAYED_ITEMS_PER_SLOT = 4;
26 public static final int MAX_DISPLAY_SLOTS = 96;
27 public static final int MAX_ITEMS_DRAWABLE = MAX_ITEMS_PER_SLOT * MAX_DISPLAY_SLOTS;
29 private static final float SLIDESHOW_TRANSITION_TIME = 3.5f;
31 private HudLayer mHud;
33 private static final IndexRange sBufferedVisibleRange = new IndexRange();
34 private static final IndexRange sVisibleRange = new IndexRange();
35 private static final IndexRange sPreviousDataRange = new IndexRange();
36 private static final IndexRange sCompleteRange = new IndexRange();
38 private static final Pool<Vector3f> sTempVec;
39 private static final Pool<Vector3f> sTempVecAlt;
41 Vector3f[] vectorPool = new Vector3f[128];
42 int length = vectorPool.length;
43 for (int i = 0; i < length; ++i) {
44 vectorPool[i] = new Vector3f();
46 Vector3f[] vectorPoolRenderThread = new Vector3f[128];
47 length = vectorPoolRenderThread.length;
48 for (int i = 0; i < length; ++i) {
49 vectorPoolRenderThread[i] = new Vector3f();
51 sTempVec = new Pool<Vector3f>(vectorPool);
52 sTempVecAlt = new Pool<Vector3f>(vectorPoolRenderThread);
55 private static final ArrayList<MediaItem> sTempList = new ArrayList<MediaItem>();
56 private static final MediaItem[] sTempHash = new MediaItem[64];
58 private static final Vector3f sDeltaAnchorPositionUncommited = new Vector3f();
59 private static Vector3f sDeltaAnchorPosition = new Vector3f();
61 // The display primitives.
62 final private GridDrawables mDrawables;
63 private float mSelectedAlpha = 0.0f;
64 private float mTargetAlpha = 0.0f;
66 final private GridCamera mCamera;
67 final private GridCameraManager mCameraManager;
68 final private GridDrawManager mDrawManager;
69 final private GridInputProcessor mInputProcessor;
71 private boolean mFeedAboutToChange;
72 private boolean mPerformingLayoutChange;
73 private boolean mFeedChanged;
75 private final LayoutInterface mLayoutInterface;
76 private static final LayoutInterface sfullScreenLayoutInterface = new GridLayoutInterface(1);
78 private MediaFeed mMediaFeed;
79 private boolean mInAlbum = false;
80 private int mCurrentExpandedSlot;
82 private static final DisplayList sDisplayList = new DisplayList();
83 private static final DisplayItem[] sDisplayItems = new DisplayItem[MAX_ITEMS_DRAWABLE];
84 private static final DisplaySlot[] sDisplaySlots = new DisplaySlot[MAX_DISPLAY_SLOTS];
85 private static ArrayList<MediaItem> sVisibleItems;
87 private float mTimeElapsedSinceTransition;
88 private final BackgroundLayer mBackground;
89 private boolean mLocationFilter;
90 private float mZoomValue = 1.0f;
91 private float mCurrentFocusItemWidth = 1.0f;
92 private float mCurrentFocusItemHeight = 1.0f;
93 private float mTimeElapsedSinceGridViewReady = 0.0f;
95 private boolean mSlideshowMode;
96 private boolean mNoDeleteMode = false;
97 private float mTimeElapsedSinceView;
98 private static final MediaBucketList sBucketList = new MediaBucketList();
99 private float mTimeElapsedSinceStackViewReady;
101 private Context mContext;
102 private RenderView mView;
103 private boolean mPickIntent;
104 private boolean mViewIntent;
105 private WakeLock mWakeLock;
106 private int mStartMemoryRange;
107 private int mFramesDirty;
108 private String mRequestFocusContentUri;
109 private int mFrameCount;
111 public GridLayer(Context context, int itemWidth, int itemHeight, LayoutInterface layoutInterface, RenderView view) {
112 mBackground = new BackgroundLayer(this);
116 DisplaySlot[] displaySlots = sDisplaySlots;
117 for (int i = 0; i < MAX_DISPLAY_SLOTS; ++i) {
118 DisplaySlot slot = new DisplaySlot();
119 displaySlots[i] = slot;
121 mLayoutInterface = layoutInterface;
122 mCamera = new GridCamera(0, 0, itemWidth, itemHeight);
123 mDrawables = new GridDrawables(itemWidth, itemHeight);
124 sBufferedVisibleRange.set(Shared.INVALID, Shared.INVALID);
125 sVisibleRange.set(Shared.INVALID, Shared.INVALID);
126 sCompleteRange.set(Shared.INVALID, Shared.INVALID);
127 sPreviousDataRange.set(Shared.INVALID, Shared.INVALID);
128 sDeltaAnchorPosition.set(0, 0, 0);
129 sDeltaAnchorPositionUncommited.set(0, 0, 0);
132 sVisibleItems = new ArrayList<MediaItem>();
133 mHud = new HudLayer(context);
134 mHud.setContext(context);
135 mHud.setGridLayer(this);
136 mHud.getPathBar().clear();
137 mHud.setGridLayer(this);
138 mHud.getTimeBar().setListener(this);
139 mHud.getPathBar().pushLabel(R.drawable.icon_home_small, context.getResources().getString(R.string.app_name),
142 if (mHud.getAlpha() == 1.0f) {
143 if (!mFeedAboutToChange) {
144 setState(STATE_MEDIA_SETS);
151 mCameraManager = new GridCameraManager(mCamera);
152 mDrawManager = new GridDrawManager(context, mCamera, mDrawables, sDisplayList, sDisplayItems, sDisplaySlots);
153 mInputProcessor = new GridInputProcessor(context, mCamera, this, mView, sTempVec, sDisplayItems);
154 setState(STATE_MEDIA_SETS);
157 public HudLayer getHud() {
161 public void shutdown() {
162 if (mMediaFeed != null) {
163 mMediaFeed.shutdown();
177 public void generate(RenderView view, RenderView.Lists lists) {
178 lists.updateList.add(this);
179 lists.opaqueList.add(this);
180 mBackground.generate(view, lists);
181 lists.blendedList.add(this);
182 lists.hitTestList.add(this);
183 mHud.generate(view, lists);
187 protected void onSizeChanged() {
188 mHud.setSize(mWidth, mHeight);
190 mBackground.setSize(mWidth, mHeight);
191 mTimeElapsedSinceTransition = 0.0f;
193 mView.requestRender();
197 public int getState() {
201 public void setState(int state) {
202 boolean feedUnchanged = false;
203 if (mState == state) {
204 feedUnchanged = true;
206 GridLayoutInterface layoutInterface = (GridLayoutInterface) mLayoutInterface;
207 GridLayoutInterface oldLayout = (GridLayoutInterface) sfullScreenLayoutInterface;
208 oldLayout.mNumRows = layoutInterface.mNumRows;
209 oldLayout.mSpacingX = layoutInterface.mSpacingX;
210 oldLayout.mSpacingY = layoutInterface.mSpacingY;
211 GridCamera camera = mCamera;
212 int numMaxRows = (camera.mHeight >= camera.mWidth) ? 4 : 3;
213 MediaFeed feed = mMediaFeed;
214 boolean performLayout = true;
216 float yStretch = camera.mDefaultAspectRatio / camera.mAspectRatio;
217 if (yStretch < 1.0f) {
221 case STATE_GRID_VIEW:
222 mTimeElapsedSinceGridViewReady = 0.0f;
223 if (feed != null && feedUnchanged == false) {
224 boolean updatedData = feed.restorePreviousClusteringState();
226 performLayout = false;
229 layoutInterface.mNumRows = numMaxRows;
230 layoutInterface.mSpacingX = (int) (10 * Gallery.PIXEL_DENSITY);
231 layoutInterface.mSpacingY = (int) (10 * Gallery.PIXEL_DENSITY);
232 if (mState == STATE_MEDIA_SETS) {
235 MediaSet set = feed.getCurrentSet();
236 int icon = mDrawables.getIconForSet(set, true);
238 mHud.getPathBar().pushLabel(icon, set.mNoCountTitleString, new Runnable() {
240 if (mFeedAboutToChange) {
243 if (mHud.getAlpha() == 1.0f) {
244 disableLocationFiltering();
245 mInputProcessor.clearSelection();
246 setState(STATE_GRID_VIEW);
254 if (mState == STATE_FULL_SCREEN) {
255 mHud.getPathBar().popLabel();
259 mTimeElapsedSinceStackViewReady = 0.0f;
260 if (feed != null && feedUnchanged == false) {
261 feed.performClustering();
262 performLayout = false;
264 disableLocationFiltering();
265 layoutInterface.mNumRows = numMaxRows - 1;
266 layoutInterface.mSpacingX = (int) (100 * Gallery.PIXEL_DENSITY);
267 layoutInterface.mSpacingY = (int) (70 * Gallery.PIXEL_DENSITY * yStretch);
269 case STATE_FULL_SCREEN:
270 layoutInterface.mNumRows = 1;
271 layoutInterface.mSpacingX = (int) (40 * Gallery.PIXEL_DENSITY);
272 layoutInterface.mSpacingY = (int) (40 * Gallery.PIXEL_DENSITY);
273 if (mState != STATE_FULL_SCREEN) {
274 mHud.getPathBar().pushLabel(R.drawable.ic_fs_details, "", new Runnable() {
276 if (mHud.getAlpha() == 1.0f) {
277 mHud.swapFullscreenLabel();
284 case STATE_MEDIA_SETS:
285 mTimeElapsedSinceStackViewReady = 0.0f;
286 if (feed != null && feedUnchanged == false) {
287 feed.restorePreviousClusteringState();
288 feed.expandMediaSet(Shared.INVALID);
289 performLayout = false;
291 disableLocationFiltering();
292 mInputProcessor.clearSelection();
293 layoutInterface.mNumRows = numMaxRows - 1;
294 layoutInterface.mSpacingX = (int) (100 * Gallery.PIXEL_DENSITY);
295 layoutInterface.mSpacingY = (int) (70 * Gallery.PIXEL_DENSITY * yStretch);
297 if (mState == STATE_FULL_SCREEN) {
298 mHud.getPathBar().popLabel();
300 mHud.getPathBar().popLabel();
306 mHud.onGridStateChanged();
307 if (performLayout && mFeedAboutToChange == false) {
308 onLayout(Shared.INVALID, Shared.INVALID, oldLayout);
310 if (state != STATE_FULL_SCREEN) {
316 protected void enableLocationFiltering(String label) {
317 if (mLocationFilter == false) {
318 mLocationFilter = true;
319 mHud.getPathBar().pushLabel(R.drawable.icon_location_small, label, new Runnable() {
321 if (mHud.getAlpha() == 1.0f) {
322 if (mState == STATE_FULL_SCREEN) {
323 mInputProcessor.clearSelection();
324 setState(STATE_GRID_VIEW);
326 disableLocationFiltering();
336 protected void disableLocationFiltering() {
337 if (mLocationFilter) {
338 mLocationFilter = false;
339 mMediaFeed.removeFilter();
340 mHud.getPathBar().popLabel();
345 if (mFeedAboutToChange) {
349 if (mInputProcessor.getCurrentSelectedSlot() == Shared.INVALID) {
350 if (mLocationFilter) {
351 disableLocationFiltering();
352 setState(STATE_TIMELINE);
357 case STATE_GRID_VIEW:
358 setState(STATE_MEDIA_SETS);
361 setState(STATE_GRID_VIEW);
363 case STATE_FULL_SCREEN:
364 setState(STATE_GRID_VIEW);
365 mInputProcessor.clearSelection();
373 public void endSlideshow() {
374 mSlideshowMode = false;
375 if (mWakeLock != null) {
376 if (mWakeLock.isHeld()) {
385 public void onSensorChanged(RenderView view, SensorEvent event) {
386 mInputProcessor.onSensorChanged(view, event, mState);
389 public DataSource getDataSource() {
390 if (mMediaFeed != null)
391 return mMediaFeed.getDataSource();
395 public void setDataSource(DataSource dataSource) {
396 MediaFeed feed = mMediaFeed;
399 sDisplayList.clear();
402 mMediaFeed = new MediaFeed(mContext, dataSource, this);
406 public IndexRange getVisibleRange() {
407 return sVisibleRange;
410 public IndexRange getBufferedVisibleRange() {
411 return sBufferedVisibleRange;
414 public IndexRange getCompleteRange() {
415 return sCompleteRange;
418 private int hitTest(Vector3f worldPos, int itemWidth, int itemHeight) {
419 int retVal = Shared.INVALID;
420 int firstSlotIndex = 0;
421 int lastSlotIndex = 0;
422 IndexRange rangeToUse = sVisibleRange;
423 synchronized (rangeToUse) {
424 firstSlotIndex = rangeToUse.begin;
425 lastSlotIndex = rangeToUse.end;
427 Pool<Vector3f> pool = sTempVec;
428 float itemWidthBy2 = itemWidth * 0.5f;
429 float itemHeightBy2 = itemHeight * 0.5f;
430 Vector3f position = pool.create();
431 Vector3f deltaAnchorPosition = pool.create();
433 deltaAnchorPosition.set(sDeltaAnchorPosition);
434 for (int i = firstSlotIndex; i <= lastSlotIndex; ++i) {
435 GridCameraManager.getSlotPositionForSlotIndex(i, mCamera, mLayoutInterface, deltaAnchorPosition, position);
436 if (FloatUtils.boundsContainsPoint(position.x - itemWidthBy2, position.x + itemWidthBy2,
437 position.y - itemHeightBy2, position.y + itemHeightBy2, worldPos.x, worldPos.y)) {
443 pool.delete(deltaAnchorPosition);
444 pool.delete(position);
449 void centerCameraForSlot(int slotIndex, float baseConvergence) {
450 float imageTheta = 0.0f;
451 DisplayItem displayItem = getDisplayItemForSlotId(slotIndex);
452 if (displayItem != null) {
453 imageTheta = displayItem.getImageTheta();
455 mCameraManager.centerCameraForSlot(mLayoutInterface, slotIndex, baseConvergence, sDeltaAnchorPositionUncommited,
456 mInputProcessor.getCurrentSelectedSlot(), mZoomValue, imageTheta, mState);
459 boolean constrainCameraForSlot(int slotIndex) {
460 return mCameraManager.constrainCameraForSlot(mLayoutInterface, slotIndex, sDeltaAnchorPosition, mCurrentFocusItemWidth,
461 mCurrentFocusItemHeight);
464 // Called on render thread before rendering.
466 public boolean update(RenderView view, float timeElapsed) {
467 if (mFeedAboutToChange == false) {
468 mTimeElapsedSinceTransition += timeElapsed;
469 mTimeElapsedSinceGridViewReady += timeElapsed;
470 if (mTimeElapsedSinceGridViewReady >= 1.0f) {
471 mTimeElapsedSinceGridViewReady = 1.0f;
473 mTimeElapsedSinceStackViewReady += timeElapsed;
474 if (mTimeElapsedSinceStackViewReady >= 1.0f) {
475 mTimeElapsedSinceStackViewReady = 1.0f;
478 mTimeElapsedSinceTransition = 0;
480 if (mMediaFeed != null && mMediaFeed.isSingleImageMode()) {
481 HudLayer hud = getHud();
482 hud.getPathBar().setHidden(true);
483 hud.getMenuBar().setHidden(true);
484 if (hud.getMode() != HudLayer.MODE_NORMAL)
485 hud.setMode(HudLayer.MODE_NORMAL);
487 if (view.elapsedLoadingExpensiveTextures() > 150 || (mMediaFeed != null && mMediaFeed.getWaitingForMediaScanner())) {
488 mHud.getPathBar().setAnimatedIcons(GridDrawables.TEXTURE_SPINNER);
490 mHud.getPathBar().setAnimatedIcons(null);
493 // In that case, we need to commit the respective Display Items when the
495 GridCamera camera = mCamera;
496 camera.update(timeElapsed);
497 DisplayItem anchorDisplayItem = getAnchorDisplayItem(ANCHOR_CENTER);
498 if (anchorDisplayItem != null && !mHud.getTimeBar().isDragged()) {
499 mHud.getTimeBar().setItem(anchorDisplayItem.mItemRef);
501 sDisplayList.update(timeElapsed);
502 mInputProcessor.update(timeElapsed);
503 mSelectedAlpha = FloatUtils.animate(mSelectedAlpha, mTargetAlpha, timeElapsed * 0.5f);
504 if (mState == STATE_FULL_SCREEN) {
507 mHud.autoHide(false);
510 GridQuad[] fullscreenQuads = GridDrawables.sFullscreenGrid;
511 int numFullScreenQuads = fullscreenQuads.length;
512 for (int i = 0; i < numFullScreenQuads; ++i) {
513 fullscreenQuads[i].update(timeElapsed);
515 if (mSlideshowMode && mState == STATE_FULL_SCREEN) {
516 mTimeElapsedSinceView += timeElapsed;
517 if (mTimeElapsedSinceView > SLIDESHOW_TRANSITION_TIME) {
518 // time to go to the next slide
519 mTimeElapsedSinceView = 0.0f;
520 changeFocusToNextSlot(0.5f);
521 mCamera.commitMoveInX();
522 mCamera.commitMoveInY();
525 if (mState == STATE_MEDIA_SETS || mState == STATE_TIMELINE) {
526 mCamera.moveYTo(-0.1f);
527 mCamera.commitMoveInY();
529 boolean dirty = mDrawManager.update(timeElapsed);
530 dirty |= mSlideshowMode;
531 dirty |= mFramesDirty > 0;
533 if (mFramesDirty > 0) {
537 if (mMediaFeed != null && (mMediaFeed.getWaitingForMediaScanner())) {
538 // We limit the drawing of the frame so that the MediaScanner
539 // thread can do its work
542 } catch (InterruptedException e) {
545 if (sDisplayList.getNumAnimatables() != 0 || mCamera.isAnimating()
546 || (mTimeElapsedSinceTransition > 0.0f && mTimeElapsedSinceTransition < 1.0f) || mSelectedAlpha != mTargetAlpha
547 // || (mAnimatedFov != mTargetFov)
554 private void computeVisibleRange() {
555 if (mPerformingLayoutChange)
557 if (sDeltaAnchorPosition.equals(sDeltaAnchorPositionUncommited) == false) {
558 sDeltaAnchorPosition.set(sDeltaAnchorPositionUncommited);
560 mCameraManager.computeVisibleRange(mMediaFeed, mLayoutInterface, sDeltaAnchorPosition, sVisibleRange,
561 sBufferedVisibleRange, sCompleteRange, mState);
564 private void computeVisibleItems() {
565 if (mFeedAboutToChange == true || mPerformingLayoutChange == true) {
568 computeVisibleRange();
569 int deltaBegin = sBufferedVisibleRange.begin - sPreviousDataRange.begin;
570 int deltaEnd = sBufferedVisibleRange.end - sPreviousDataRange.end;
571 if (deltaBegin != 0 || deltaEnd != 0) {
572 // The delta has changed, we have to compute the display items
574 // We find the intersection range, these slots have not changed at
576 int firstVisibleSlotIndex = sBufferedVisibleRange.begin;
577 int lastVisibleSlotIndex = sBufferedVisibleRange.end;
578 sPreviousDataRange.begin = firstVisibleSlotIndex;
579 sPreviousDataRange.end = lastVisibleSlotIndex;
581 Pool<Vector3f> pool = sTempVec;
582 Vector3f position = pool.create();
583 Vector3f deltaAnchorPosition = pool.create();
585 MediaFeed feed = mMediaFeed;
586 DisplayList displayList = sDisplayList;
587 DisplayItem[] displayItems = sDisplayItems;
588 DisplaySlot[] displaySlots = sDisplaySlots;
589 int numDisplayItems = displayItems.length;
590 int numDisplaySlots = displaySlots.length;
591 ArrayList<MediaItem> visibleItems = sVisibleItems;
592 deltaAnchorPosition.set(sDeltaAnchorPosition);
593 LayoutInterface layout = mLayoutInterface;
594 GridCamera camera = mCamera;
595 for (int i = firstVisibleSlotIndex; i <= lastVisibleSlotIndex; ++i) {
596 GridCameraManager.getSlotPositionForSlotIndex(i, camera, layout, deltaAnchorPosition, position);
597 MediaSet set = feed.getSetForSlot(i);
598 int indexIntoSlots = i - firstVisibleSlotIndex;
600 if (set != null && indexIntoSlots >= 0 && indexIntoSlots < numDisplaySlots) {
601 ArrayList<MediaItem> items = set.getItems();
602 displaySlots[indexIntoSlots].setMediaSet(set);
603 ArrayList<MediaItem> bestItems = sTempList;
604 if (mTimeElapsedSinceTransition < 1.0f) {
605 // We always show the same top thumbnails for a
607 if (mState == STATE_MEDIA_SETS)
608 ArrayUtils.computeSortedIntersection(items, visibleItems, MAX_ITEMS_PER_SLOT, bestItems, sTempHash);
610 ArrayUtils.computeSortedIntersection(visibleItems, items, MAX_ITEMS_PER_SLOT, bestItems, sTempHash);
613 int numItemsInSet = set.getNumItems();
614 int numBestItems = bestItems.size();
615 int originallyFoundItems = numBestItems;
616 if (numBestItems < MAX_ITEMS_PER_SLOT) {
617 int itemsRemaining = MAX_ITEMS_PER_SLOT - numBestItems;
618 for (int currItemPos = 0; currItemPos < numItemsInSet; currItemPos++) {
619 MediaItem item = items.get(currItemPos);
620 if (mTimeElapsedSinceTransition >= 1.0f || !bestItems.contains(item)) {
622 if (--itemsRemaining == 0) {
628 numBestItems = bestItems.size();
629 int baseIndex = (i - firstVisibleSlotIndex) * MAX_ITEMS_PER_SLOT;
630 for (int j = 0; j < numBestItems; ++j) {
631 if (baseIndex + j >= numDisplayItems) {
634 if (j >= numItemsInSet) {
635 displayItems[baseIndex + j] = null;
637 MediaItem item = bestItems.get(j);
639 DisplayItem displayItem = displayList.get(item);
640 if ((mState == STATE_FULL_SCREEN && i != mInputProcessor.getCurrentSelectedSlot())
641 || (mState == STATE_GRID_VIEW && (mTimeElapsedSinceTransition > 1.0f || j >= originallyFoundItems))) {
642 displayItem.set(position, j, false);
643 displayItem.commit();
645 displayList.setPositionAndStackIndex(displayItem, position, j, true);
647 displayItems[baseIndex + j] = displayItem;
651 for (int j = numBestItems; j < MAX_ITEMS_PER_SLOT; ++j) {
652 displayItems[baseIndex + j] = null;
658 mFeedChanged = false;
659 if (mInputProcessor != null && mState == STATE_FULL_SCREEN && mRequestFocusContentUri == null) {
660 int currentSelectedSlot = mInputProcessor.getCurrentSelectedSlot();
661 if (currentSelectedSlot > sCompleteRange.end)
662 currentSelectedSlot = sCompleteRange.end;
663 mInputProcessor.setCurrentSelectedSlot(currentSelectedSlot);
665 if (mState == STATE_GRID_VIEW) {
666 MediaSet expandedSet = mMediaFeed.getExpandedMediaSet();
667 if (expandedSet != null) {
668 if (!mHud.getPathBar().getCurrentLabel().equals(expandedSet.mNoCountTitleString)) {
669 mHud.getPathBar().changeLabel(expandedSet.mNoCountTitleString);
673 if (mRequestFocusContentUri != null) {
674 // We have to find the item that has this contentUri
675 if (mState == STATE_FULL_SCREEN) {
676 int numSlots = sCompleteRange.end + 1;
677 for (int i = 0; i < numSlots; ++i) {
678 MediaSet set = feed.getSetForSlot(i);
679 ArrayList<MediaItem> items = set.getItems();
680 int numItems = items.size();
681 for (int j = 0; j < numItems; ++j) {
682 String itemUri = items.get(j).mContentUri;
683 if (itemUri != null && mRequestFocusContentUri != null) {
684 if (itemUri.equals(mRequestFocusContentUri)) {
685 mInputProcessor.setCurrentSelectedSlot(i);
692 mRequestFocusContentUri = null;
696 pool.delete(position);
697 pool.delete(deltaAnchorPosition);
699 // We keep upto 400 thumbnails in memory.
700 int numThumbnailsToKeepInMemory = (mState == STATE_MEDIA_SETS || mState == STATE_TIMELINE) ? 100 : 400;
701 int startMemoryRange = (sBufferedVisibleRange.begin / numThumbnailsToKeepInMemory) * numThumbnailsToKeepInMemory;
702 if (mStartMemoryRange != startMemoryRange) {
703 mStartMemoryRange = startMemoryRange;
704 clearUnusedThumbnails();
710 public void handleLowMemory() {
711 clearUnusedThumbnails();
712 GridDrawables.sStringTextureTable.clear();
713 mBackground.clearCache();
716 // This method can be potentially expensive
717 public void clearUnusedThumbnails() {
718 sDisplayList.clearExcept(sDisplayItems);
722 public void onSurfaceCreated(RenderView view, GL11 gl) {
723 sDisplayList.clear();
726 GridDrawables.sStringTextureTable.clear();
727 mDrawables.onSurfaceCreated(view, gl);
732 public void onSurfaceChanged(RenderView view, int width, int height) {
733 mCamera.viewportChanged(width, height, mCamera.mItemWidth, mCamera.mItemHeight);
734 view.setFov(mCamera.mFov);
738 // Renders the node in a given pass.
739 public void renderOpaque(RenderView view, GL11 gl) {
740 GridCamera camera = mCamera;
741 int selectedSlotIndex = mInputProcessor.getCurrentSelectedSlot();
742 computeVisibleItems();
744 gl.glMatrixMode(GL11.GL_MODELVIEW);
746 GLU.gluLookAt(gl, -camera.mEyeX, -camera.mEyeY, -camera.mEyeZ, -camera.mLookAtX, -camera.mLookAtY, -camera.mLookAtZ,
747 camera.mUpX, camera.mUpY, camera.mUpZ);
749 if (mSelectedAlpha != 1.0f) {
750 gl.glEnable(GL11.GL_BLEND);
751 gl.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
752 view.setAlpha(mSelectedAlpha);
754 if (selectedSlotIndex != Shared.INVALID) {
759 mDrawManager.prepareDraw(sBufferedVisibleRange, sVisibleRange, selectedSlotIndex, mInputProcessor.getCurrentFocusSlot(),
760 mInputProcessor.isFocusItemPressed());
761 if (mSelectedAlpha != 0.0f) {
762 mDrawManager.drawThumbnails(view, gl, mState);
764 if (mSelectedAlpha != 1.0f) {
765 gl.glDisable(GL11.GL_BLEND);
767 // We draw the selected slotIndex.
768 if (selectedSlotIndex != Shared.INVALID) {
769 mDrawManager.drawFocusItems(view, gl, mZoomValue, mSlideshowMode, mTimeElapsedSinceView);
770 mCurrentFocusItemWidth = mDrawManager.getFocusQuadWidth();
771 mCurrentFocusItemHeight = mDrawManager.getFocusQuadHeight();
773 view.setAlpha(mSelectedAlpha);
776 public void renderBlended(RenderView view, GL11 gl) {
777 // We draw the placeholder for all visible slots.
778 if (mHud != null && mDrawManager != null) {
779 mDrawManager.drawBlendedComponents(view, gl, mSelectedAlpha, mState, mHud.getMode(), mTimeElapsedSinceStackViewReady,
780 mTimeElapsedSinceGridViewReady, sBucketList, mMediaFeed.getWaitingForMediaScanner() || mFeedAboutToChange
781 || mMediaFeed.isLoading());
785 public synchronized void onLayout(int newAnchorSlotIndex, int currentAnchorSlotIndex, LayoutInterface oldLayout) {
786 if (mPerformingLayoutChange || !sDeltaAnchorPosition.equals(sDeltaAnchorPositionUncommited)) {
790 mTimeElapsedSinceTransition = 0.0f;
791 mPerformingLayoutChange = true;
792 LayoutInterface layout = mLayoutInterface;
793 if (oldLayout == null) {
794 oldLayout = sfullScreenLayoutInterface;
796 GridCamera camera = mCamera;
797 if (currentAnchorSlotIndex == Shared.INVALID) {
798 currentAnchorSlotIndex = getAnchorSlotIndex(ANCHOR_CENTER);
799 if (mCurrentExpandedSlot != Shared.INVALID) {
800 currentAnchorSlotIndex = mCurrentExpandedSlot;
802 int selectedSlotIndex = mInputProcessor.getCurrentSelectedSlot();
803 if (selectedSlotIndex != Shared.INVALID) {
804 currentAnchorSlotIndex = selectedSlotIndex;
807 if (newAnchorSlotIndex == Shared.INVALID) {
808 newAnchorSlotIndex = currentAnchorSlotIndex;
810 int itemHeight = camera.mItemHeight;
811 int itemWidth = camera.mItemWidth;
812 Pool<Vector3f> pool = sTempVec;
813 Vector3f deltaAnchorPosition = pool.create();
814 Vector3f currentSlotPosition = pool.create();
816 deltaAnchorPosition.set(0, 0, 0);
817 if (currentAnchorSlotIndex != Shared.INVALID && newAnchorSlotIndex != Shared.INVALID) {
818 layout.getPositionForSlotIndex(newAnchorSlotIndex, itemWidth, itemHeight, deltaAnchorPosition);
819 oldLayout.getPositionForSlotIndex(currentAnchorSlotIndex, itemWidth, itemHeight, currentSlotPosition);
820 currentSlotPosition.subtract(sDeltaAnchorPosition);
821 deltaAnchorPosition.subtract(currentSlotPosition);
822 deltaAnchorPosition.y = 0;
823 deltaAnchorPosition.z = 0;
825 sDeltaAnchorPositionUncommited.set(deltaAnchorPosition);
827 pool.delete(deltaAnchorPosition);
828 pool.delete(currentSlotPosition);
830 centerCameraForSlot(newAnchorSlotIndex, 1.0f);
831 mCurrentExpandedSlot = Shared.INVALID;
833 // Force recompute of visible items and their positions.
834 ((GridLayoutInterface) oldLayout).mNumRows = ((GridLayoutInterface) layout).mNumRows;
835 ((GridLayoutInterface) oldLayout).mSpacingX = ((GridLayoutInterface) layout).mSpacingX;
836 ((GridLayoutInterface) oldLayout).mSpacingY = ((GridLayoutInterface) layout).mSpacingY;
837 forceRecomputeVisibleRange();
838 mPerformingLayoutChange = false;
841 private void forceRecomputeVisibleRange() {
842 sPreviousDataRange.begin = Shared.INVALID;
843 sPreviousDataRange.end = Shared.INVALID;
845 mView.requestRender();
849 // called on background thread
850 public synchronized void onFeedChanged(MediaFeed feed, boolean needsLayout) {
853 forceRecomputeVisibleRange();
854 if (mState == STATE_GRID_VIEW || mState == STATE_FULL_SCREEN)
855 mHud.setFeed(feed, mState, needsLayout);
859 while (mPerformingLayoutChange == true) {
862 if (mState == STATE_GRID_VIEW) {
864 MediaSet set = feed.getCurrentSet();
865 if (set != null && !mLocationFilter)
866 mHud.getPathBar().changeLabel(set.mNoCountTitleString);
869 DisplayItem[] displayItems = sDisplayItems;
870 int firstBufferedVisibleSlotIndex = sBufferedVisibleRange.begin;
871 int lastBufferedVisibleSlotIndex = sBufferedVisibleRange.end;
872 int currentlyVisibleSlotIndex = getAnchorSlotIndex(ANCHOR_CENTER);
873 if (mCurrentExpandedSlot != Shared.INVALID) {
874 currentlyVisibleSlotIndex = mCurrentExpandedSlot;
876 MediaItem anchorItem = null;
877 ArrayList<MediaItem> visibleItems = sVisibleItems;
878 visibleItems.clear();
879 visibleItems.ensureCapacity(lastBufferedVisibleSlotIndex - firstBufferedVisibleSlotIndex);
880 if (currentlyVisibleSlotIndex != Shared.INVALID && currentlyVisibleSlotIndex >= firstBufferedVisibleSlotIndex
881 && currentlyVisibleSlotIndex <= lastBufferedVisibleSlotIndex) {
882 int baseIndex = (currentlyVisibleSlotIndex - firstBufferedVisibleSlotIndex) * MAX_ITEMS_PER_SLOT;
883 for (int i = 0; i < MAX_ITEMS_PER_SLOT; ++i) {
884 DisplayItem displayItem = displayItems[baseIndex + i];
885 if (displayItem != null) {
886 if (anchorItem == null) {
887 anchorItem = displayItem.mItemRef;
889 visibleItems.add(displayItem.mItemRef);
893 // We want to add items from the middle.
894 int numItems = lastBufferedVisibleSlotIndex - firstBufferedVisibleSlotIndex + 1;
895 int midPoint = (lastBufferedVisibleSlotIndex - firstBufferedVisibleSlotIndex) / 2;
896 int length = displayItems.length;
897 for (int i = 0; i < numItems; ++i) {
898 int index = midPoint + Shared.midPointIterator(i);
899 int indexIntoDisplayItem = (index - firstBufferedVisibleSlotIndex) * MAX_ITEMS_PER_SLOT;
900 if (indexIntoDisplayItem >= 0 && indexIntoDisplayItem < length) {
901 for (int j = 0; j < MAX_ITEMS_PER_SLOT; ++j) {
902 DisplayItem displayItem = displayItems[indexIntoDisplayItem + j];
903 if (displayItem != null) {
904 MediaItem item = displayItem.mItemRef;
905 if (item != anchorItem) {
906 visibleItems.add(item);
912 int newSlotIndex = Shared.INVALID;
913 if (anchorItem != null) {
914 // We try to find the anchor item in the new feed.
915 int numSlots = feed.getNumSlots();
916 for (int i = 0; i < numSlots; ++i) {
917 MediaSet set = feed.getSetForSlot(i);
918 if (set != null && set.containsItem(anchorItem)) {
925 if (anchorItem != null && newSlotIndex == Shared.INVALID) {
926 int numSlots = feed.getNumSlots();
927 MediaSet parentSet = anchorItem.mParentMediaSet;
928 for (int i = 0; i < numSlots; ++i) {
929 MediaSet set = feed.getSetForSlot(i);
930 if (set != null && set.mId == parentSet.mId) {
937 // We must create a new display store now since the data has changed.
938 if (newSlotIndex != Shared.INVALID) {
939 if (mState == STATE_MEDIA_SETS) {
940 sDisplayList.clearExcept(displayItems);
942 onLayout(newSlotIndex, currentlyVisibleSlotIndex, null);
944 forceRecomputeVisibleRange();
946 mCurrentExpandedSlot = Shared.INVALID;
947 mFeedAboutToChange = false;
950 if (mState == STATE_GRID_VIEW || mState == STATE_FULL_SCREEN)
951 mHud.setFeed(feed, mState, needsLayout);
954 mView.requestRender();
958 public DisplayItem getRepresentativeDisplayItem() {
959 int slotIndex = Shared.INVALID;
960 if (mInputProcessor != null) {
961 slotIndex = mInputProcessor.getCurrentFocusSlot();
963 if (slotIndex == Shared.INVALID) {
964 slotIndex = getAnchorSlotIndex(ANCHOR_CENTER);
966 int index = (slotIndex - sBufferedVisibleRange.begin) * MAX_ITEMS_PER_SLOT;
967 if (index >= 0 && index < MAX_ITEMS_DRAWABLE) {
968 return sDisplayItems[index];
974 public DisplayItem getAnchorDisplayItem(int type) {
975 int slotIndex = getAnchorSlotIndex(type);
976 return sDisplayItems[(slotIndex - sBufferedVisibleRange.begin) * MAX_ITEMS_PER_SLOT];
979 public float getScrollPosition() {
980 return (mCamera.mLookAtX * mCamera.mScale + sDeltaAnchorPosition.x); // in
984 public DisplayItem getDisplayItemForScrollPosition(float posX) {
985 Pool<Vector3f> pool = sTempVecAlt;
986 MediaFeed feed = mMediaFeed;
987 int itemWidth = mCamera.mItemWidth;
988 int itemHeight = mCamera.mItemHeight;
989 GridLayoutInterface gridInterface = (GridLayoutInterface) mLayoutInterface;
990 float absolutePosX = posX;
991 int left = (int) ((absolutePosX / itemWidth) * gridInterface.mNumRows);
992 int right = feed == null ? 0 : (int) (feed.getNumSlots());
994 Vector3f position = pool.create();
996 for (int i = left; i < right; ++i) {
997 gridInterface.getPositionForSlotIndex(i, itemWidth, itemHeight, position);
999 if (position.x >= absolutePosX) {
1004 pool.delete(position);
1006 if (mFeedAboutToChange) {
1009 right = feed == null ? 0 : feed.getNumSlots();
1014 if (retSlot >= right)
1015 retSlot = right - 1;
1016 MediaSet set = feed.getSetForSlot(retSlot);
1018 ArrayList<MediaItem> items = set.getItems();
1019 if (items != null && set.getNumItems() > 0) {
1020 return (sDisplayList.get(items.get(0)));
1026 // Returns the top left-most item.
1027 public int getAnchorSlotIndex(int anchorType) {
1029 switch (anchorType) {
1031 retVal = sVisibleRange.begin;
1034 retVal = sVisibleRange.end;
1037 retVal = (sVisibleRange.begin + sVisibleRange.end) / 2;
1043 DisplayItem getDisplayItemForSlotId(int slotId) {
1044 int index = slotId - sBufferedVisibleRange.begin;
1045 if (index >= 0 && slotId <= sBufferedVisibleRange.end) {
1046 return sDisplayItems[index * MAX_ITEMS_PER_SLOT];
1051 boolean changeFocusToNextSlot(float convergence) {
1052 int currentSelectedSlot = mInputProcessor.getCurrentSelectedSlot();
1053 boolean retVal = changeFocusToSlot(currentSelectedSlot + 1, convergence);
1054 if (mInputProcessor.getCurrentSelectedSlot() == currentSelectedSlot) {
1056 mHud.setAlpha(1.0f);
1061 boolean changeFocusToSlot(int slotId, float convergence) {
1063 int index = slotId - sBufferedVisibleRange.begin;
1064 if (index >= 0 && slotId <= sBufferedVisibleRange.end) {
1065 DisplayItem displayItem = sDisplayItems[index * MAX_ITEMS_PER_SLOT];
1066 if (displayItem != null) {
1067 MediaItem item = displayItem.mItemRef;
1068 mHud.fullscreenSelectionChanged(item, slotId + 1, sCompleteRange.end + 1);
1069 if (slotId != Shared.INVALID && slotId <= sCompleteRange.end) {
1070 mInputProcessor.setCurrentFocusSlot(slotId);
1071 centerCameraForSlot(slotId, convergence);
1074 centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), convergence);
1082 boolean changeFocusToPreviousSlot(float convergence) {
1083 return changeFocusToSlot(mInputProcessor.getCurrentSelectedSlot() - 1, convergence);
1086 public ArrayList<MediaBucket> getSelectedBuckets() {
1087 return sBucketList.get();
1090 public void selectAll() {
1091 if (mState != STATE_FULL_SCREEN) {
1092 int numSlots = sCompleteRange.end + 1;
1093 for (int i = 0; i < numSlots; ++i) {
1094 addSlotToSelectedItems(i, false, false);
1096 updateCountOfSelectedItems();
1098 addSlotToSelectedItems(mInputProcessor.getCurrentFocusSlot(), false, true);
1102 public void deselectOrCancelSelectMode() {
1103 if (sBucketList.size() == 0) {
1104 mHud.cancelSelection();
1106 sBucketList.clear();
1107 updateCountOfSelectedItems();
1111 public void deselectAll() {
1112 mHud.cancelSelection();
1113 sBucketList.clear();
1114 updateCountOfSelectedItems();
1117 public void deleteSelection() {
1118 // Delete the selection and exit selection mode.
1119 mMediaFeed.performOperation(MediaFeed.OPERATION_DELETE, getSelectedBuckets(), null);
1122 // If the current set is now empty, return to the parent set.
1123 if (sCompleteRange.isEmpty()) {
1124 goBack(); // TODO(venkat): This does not work most of the time, can
1129 void addSlotToSelectedItems(int slotId, boolean removeIfAlreadyAdded, boolean updateCount) {
1130 if (mFeedAboutToChange == false) {
1131 MediaFeed feed = mMediaFeed;
1132 sBucketList.add(slotId, feed, removeIfAlreadyAdded);
1134 updateCountOfSelectedItems();
1135 if (sBucketList.size() == 0)
1139 mHud.computeBottomMenu();
1142 private void updateCountOfSelectedItems() {
1143 mHud.updateNumItemsSelected(sBucketList.size());
1146 public int getMetadataSlotIndexForScreenPosition(int posX, int posY) {
1147 return getSlotForScreenPosition(posX, posY, mCamera.mItemWidth + (int) (100 * Gallery.PIXEL_DENSITY), mCamera.mItemHeight
1148 + (int) (100 * Gallery.PIXEL_DENSITY));
1151 public int getSlotIndexForScreenPosition(int posX, int posY) {
1152 return getSlotForScreenPosition(posX, posY, mCamera.mItemWidth, mCamera.mItemHeight);
1155 private int getSlotForScreenPosition(int posX, int posY, int itemWidth, int itemHeight) {
1156 Pool<Vector3f> pool = sTempVec;
1158 Vector3f worldPos = pool.create();
1160 GridCamera camera = mCamera;
1161 camera.convertToCameraSpace(posX, posY, 0, worldPos);
1162 // slots are expressed in pixels as well
1163 worldPos.x *= camera.mScale;
1164 worldPos.y *= camera.mScale;
1166 retVal = hitTest(worldPos, itemWidth, itemHeight);
1168 pool.delete(worldPos);
1173 public boolean tapGesture(int slotIndex, boolean metadata) {
1174 MediaFeed feed = mMediaFeed;
1175 if (!feed.isClustered()) {
1176 // It is not clustering.
1177 if (!feed.hasExpandedMediaSet()) {
1178 if (feed.canExpandSet(slotIndex)) {
1179 mCurrentExpandedSlot = slotIndex;
1180 feed.expandMediaSet(slotIndex);
1181 setState(STATE_GRID_VIEW);
1188 // Select a cluster, and recompute a new cluster within this
1190 mCurrentExpandedSlot = slotIndex;
1193 DisplaySlot slot = sDisplaySlots[slotIndex - sBufferedVisibleRange.begin];
1194 if (slot.hasValidLocation()) {
1195 MediaSet set = slot.getMediaSet();
1196 if (set.mReverseGeocodedLocation != null) {
1197 enableLocationFiltering(set.mReverseGeocodedLocation);
1199 feed.setFilter(new LocationMediaFilter(set.mMinLatLatitude, set.mMinLonLongitude, set.mMaxLatLatitude,
1200 set.mMaxLonLongitude));
1207 public void onTimeChanged(TimeBar timebar) {
1208 if (mFeedAboutToChange) {
1211 // TODO lot of optimization possible here
1212 MediaItem item = timebar.getItem();
1213 MediaFeed feed = mMediaFeed;
1214 int numSlots = feed.getNumSlots();
1215 for (int i = 0; i < numSlots; ++i) {
1216 MediaSet set = feed.getSetForSlot(i);
1220 ArrayList<MediaItem> items = set.getItems();
1221 if (items == null || set.getNumItems() == 0) {
1224 if (items.contains(item)) {
1225 centerCameraForSlot(i, 1.0f);
1231 public void onFeedAboutToChange(MediaFeed feed) {
1232 mFeedAboutToChange = true;
1233 mTimeElapsedSinceTransition = 0;
1236 public void startSlideshow() {
1238 mSlideshowMode = true;
1240 centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
1241 mTimeElapsedSinceView = SLIDESHOW_TRANSITION_TIME - 1.0f;
1243 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
1244 mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "GridView.Slideshow");
1245 mWakeLock.acquire();
1248 public void enterSelectionMode() {
1249 mSlideshowMode = false;
1250 mHud.enterSelectionMode();
1251 int currentSlot = mInputProcessor.getCurrentSelectedSlot();
1252 if (currentSlot == Shared.INVALID) {
1253 currentSlot = mInputProcessor.getCurrentFocusSlot();
1255 addSlotToSelectedItems(currentSlot, false, true);
1258 private float getFillScreenZoomValue() {
1259 return GridCameraManager.getFillScreenZoomValue(mCamera, sTempVec, mCurrentFocusItemWidth, mCurrentFocusItemHeight);
1262 public void zoomInToSelectedItem() {
1263 mSlideshowMode = false;
1264 float potentialZoomValue = getFillScreenZoomValue();
1265 if (mZoomValue < potentialZoomValue) {
1266 mZoomValue = potentialZoomValue;
1270 if (mZoomValue > 6.0f) {
1273 mHud.setAlpha(1.0f);
1274 centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
1277 public void zoomOutFromSelectedItem() {
1278 mSlideshowMode = false;
1279 if (mZoomValue == getFillScreenZoomValue()) {
1284 if (mZoomValue < 1.0f) {
1287 mHud.setAlpha(1.0f);
1288 centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
1291 public void rotateSelectedItems(float f) {
1292 MediaBucketList bucketList = sBucketList;
1293 ArrayList<MediaBucket> mediaBuckets = bucketList.get();
1294 DisplayList displayList = sDisplayList;
1295 int numBuckets = mediaBuckets.size();
1296 for (int i = 0; i < numBuckets; ++i) {
1297 MediaBucket bucket = mediaBuckets.get(i);
1298 ArrayList<MediaItem> mediaItems = bucket.mediaItems;
1299 if (mediaItems != null) {
1300 int numMediaItems = mediaItems.size();
1301 for (int j = 0; j < numMediaItems; ++j) {
1302 MediaItem item = mediaItems.get(j);
1303 DisplayItem displayItem = displayList.get(item);
1304 displayItem.rotateImageBy(f);
1305 displayList.addToAnimatables(displayItem);
1309 if (mState == STATE_FULL_SCREEN) {
1310 centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
1312 mMediaFeed.performOperation(MediaFeed.OPERATION_ROTATE, mediaBuckets, new Float(f));
1313 // we recreate these displayitems from the cache
1316 public void cropSelectedItem() {
1321 public boolean onTouchEvent(MotionEvent event) {
1322 return mInputProcessor.onTouchEvent(event);
1326 public boolean onKeyDown(int keyCode, KeyEvent event) {
1327 if (mInputProcessor != null)
1328 return mInputProcessor.onKeyDown(keyCode, event, mState);
1332 public boolean inSlideShowMode() {
1333 return mSlideshowMode;
1336 public boolean noDeleteMode() {
1337 return mNoDeleteMode || (mMediaFeed != null && mMediaFeed.isSingleImageMode());
1340 public float getZoomValue() {
1344 public boolean feedAboutToChange() {
1345 return mFeedAboutToChange;
1348 public boolean isInAlbumMode() {
1352 public Vector3f getDeltaAnchorPosition() {
1353 return sDeltaAnchorPosition;
1356 public int getExpandedSlot() {
1357 return mCurrentExpandedSlot;
1360 public GridLayoutInterface getLayoutInterface() {
1361 return (GridLayoutInterface) mLayoutInterface;
1364 public void setZoomValue(float f) {
1366 centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
1369 public void setPickIntent(boolean b) {
1371 mHud.getPathBar().popLabel();
1372 mHud.getPathBar().pushLabel(R.drawable.icon_location_small, mContext.getResources().getString(R.string.pick),
1375 if (mHud.getAlpha() == 1.0f) {
1376 if (!mFeedAboutToChange) {
1377 setState(STATE_MEDIA_SETS);
1380 mHud.setAlpha(1.0f);
1386 public boolean getPickIntent() {
1390 public void setViewIntent(boolean b, final String setName) {
1393 mMediaFeed.expandMediaSet(0);
1394 setState(STATE_GRID_VIEW);
1395 // We need to make sure we haven't pushed the same label twice
1396 if (mHud.getPathBar().getNumLevels() == 1) {
1397 mHud.getPathBar().pushLabel(R.drawable.icon_folder_small, setName, new Runnable() {
1399 if (mFeedAboutToChange) {
1402 if (mHud.getAlpha() == 1.0f) {
1403 disableLocationFiltering();
1404 if (mInputProcessor != null)
1405 mInputProcessor.clearSelection();
1406 setState(STATE_GRID_VIEW);
1408 mHud.setAlpha(1.0f);
1416 public boolean getViewIntent() {
1420 public void setSingleImage(boolean noDeleteMode) {
1421 mNoDeleteMode = noDeleteMode;
1422 mInputProcessor.setCurrentSelectedSlot(0);
1425 public MediaFeed getFeed() {
1429 public void markDirty(int numFrames) {
1430 mFramesDirty = numFrames;
1433 public void focusItem(String contentUri) {
1434 mRequestFocusContentUri = contentUri;
1435 mMediaFeed.updateListener(false);