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.util.Log;
11 import android.view.KeyEvent;
12 import android.view.MotionEvent;
13 import android.content.Context;
15 public final class GridLayer extends RootLayer implements MediaFeed.Listener, TimeBar.Listener {
16 public static final int STATE_MEDIA_SETS = 0;
17 public static final int STATE_GRID_VIEW = 1;
18 public static final int STATE_FULL_SCREEN = 2;
19 public static final int STATE_TIMELINE = 3;
21 public static final int ANCHOR_LEFT = 0;
22 public static final int ANCHOR_RIGHT = 1;
23 public static final int ANCHOR_CENTER = 2;
25 public static final int MAX_ITEMS_PER_SLOT = 12;
26 public static final int MAX_DISPLAYED_ITEMS_PER_SLOT = 4;
27 public static final int MAX_DISPLAY_SLOTS = 96;
28 public static final int MAX_ITEMS_DRAWABLE = MAX_ITEMS_PER_SLOT * MAX_DISPLAY_SLOTS;
30 private static final float SLIDESHOW_TRANSITION_TIME = 3.5f;
32 private static HudLayer sHud;
34 private static final IndexRange sBufferedVisibleRange = new IndexRange();
35 private static final IndexRange sVisibleRange = new IndexRange();
36 private static final IndexRange sPreviousDataRange = new IndexRange();
37 private static final IndexRange sCompleteRange = new IndexRange();
39 private static final Pool<Vector3f> sTempVec;
40 private static final Pool<Vector3f> sTempVecAlt;
42 Vector3f[] vectorPool = new Vector3f[128];
43 int length = vectorPool.length;
44 for (int i = 0; i < length; ++i) {
45 vectorPool[i] = new Vector3f();
47 Vector3f[] vectorPoolRenderThread = new Vector3f[128];
48 length = vectorPoolRenderThread.length;
49 for (int i = 0; i < length; ++i) {
50 vectorPoolRenderThread[i] = new Vector3f();
52 sTempVec = new Pool<Vector3f>(vectorPool);
53 sTempVecAlt = new Pool<Vector3f>(vectorPoolRenderThread);
56 private static final ArrayList<MediaItem> sTempList = new ArrayList<MediaItem>();
57 private static final MediaItem[] sTempHash = new MediaItem[64];
59 private static final Vector3f sDeltaAnchorPositionUncommited = new Vector3f();
60 private static Vector3f sDeltaAnchorPosition = new Vector3f();
62 // The display primitives.
63 private GridDrawables mDrawables;
64 private float mSelectedAlpha = 0.0f;
65 private float mTargetAlpha = 0.0f;
67 private GridCamera mCamera;
68 private GridCameraManager mCameraManager;
69 private GridDrawManager mDrawManager;
70 private GridInputProcessor mInputProcessor;
72 private boolean mFeedAboutToChange;
73 private boolean mPerformingLayoutChange;
74 private boolean mFeedChanged;
76 private final LayoutInterface mLayoutInterface;
77 private static final LayoutInterface sfullScreenLayoutInterface = new GridLayoutInterface(1);
79 private MediaFeed mMediaFeed;
80 private boolean mInAlbum = false;
81 private int mCurrentExpandedSlot;
83 private static final DisplayList sDisplayList = new DisplayList();
84 private static final DisplayItem[] sDisplayItems = new DisplayItem[MAX_ITEMS_DRAWABLE];
85 private static final DisplaySlot[] sDisplaySlots = new DisplaySlot[MAX_DISPLAY_SLOTS];
86 private static ArrayList<MediaItem> sVisibleItems;
88 private float mTimeElapsedSinceTransition;
89 private BackgroundLayer mBackground;
90 private boolean mLocationFilter;
91 private float mZoomValue = 1.0f;
92 private float mCurrentFocusItemWidth = 1.0f;
93 private float mCurrentFocusItemHeight = 1.0f;
94 private float mTimeElapsedSinceGridViewReady = 0.0f;
96 private boolean mSlideshowMode;
97 private boolean mNoDeleteMode = false;
98 private float mTimeElapsedSinceView;
99 private static final MediaBucketList sBucketList = new MediaBucketList();
100 private float mTimeElapsedSinceStackViewReady;
102 private Context mContext;
103 private RenderView mView;
104 private boolean mPickIntent;
105 private boolean mViewIntent;
106 private WakeLock mWakeLock;
107 private int mStartMemoryRange;
108 private int mFramesDirty;
109 private String mRequestFocusContentUri;
110 private int mFrameCount;
111 private boolean mNeedsInit;
113 public GridLayer(Context context, int itemWidth, int itemHeight, LayoutInterface layoutInterface, RenderView view) {
114 mBackground = new BackgroundLayer(this);
119 DisplaySlot[] displaySlots = sDisplaySlots;
120 for (int i = 0; i < MAX_DISPLAY_SLOTS; ++i) {
121 DisplaySlot slot = new DisplaySlot();
122 displaySlots[i] = slot;
124 mLayoutInterface = layoutInterface;
125 mCamera = new GridCamera(0, 0, itemWidth, itemHeight);
126 mDrawables = new GridDrawables(itemWidth, itemHeight);
127 sBufferedVisibleRange.set(Shared.INVALID, Shared.INVALID);
128 sVisibleRange.set(Shared.INVALID, Shared.INVALID);
129 sCompleteRange.set(Shared.INVALID, Shared.INVALID);
130 sPreviousDataRange.set(Shared.INVALID, Shared.INVALID);
131 sDeltaAnchorPosition.set(0, 0, 0);
132 sDeltaAnchorPositionUncommited.set(0, 0, 0);
135 sVisibleItems = new ArrayList<MediaItem>();
137 sHud = new HudLayer(context);
139 sHud.setContext(context);
140 sHud.setGridLayer(this);
141 sHud.getPathBar().clear();
142 sHud.setGridLayer(this);
143 sHud.getTimeBar().setListener(this);
144 sHud.getPathBar().pushLabel(R.drawable.icon_home_small, context.getResources().getString(R.string.app_name),
147 if (sHud.getAlpha() == 1.0f) {
148 if (!mFeedAboutToChange) {
149 setState(STATE_MEDIA_SETS);
156 mCameraManager = new GridCameraManager(mCamera);
157 mDrawManager = new GridDrawManager(context, mCamera, mDrawables, sDisplayList, sDisplayItems, sDisplaySlots);
158 mInputProcessor = new GridInputProcessor(context, mCamera, this, mView, sTempVec, sDisplayItems);
161 public HudLayer getHud() {
165 public void shutdown() {
166 if (mMediaFeed != null) {
167 mMediaFeed.shutdown();
182 public void generate(RenderView view, RenderView.Lists lists) {
183 lists.updateList.add(this);
184 lists.opaqueList.add(this);
185 mBackground.generate(view, lists);
186 lists.blendedList.add(this);
187 lists.hitTestList.add(this);
188 sHud.generate(view, lists);
192 protected void onSizeChanged() {
193 sHud.setSize(mWidth, mHeight);
195 mBackground.setSize(mWidth, mHeight);
196 mTimeElapsedSinceTransition = 0.0f;
198 mView.requestRender();
202 public int getState() {
206 public void setState(int state) {
207 boolean feedUnchanged = false;
208 if (mState == state) {
209 feedUnchanged = true;
211 GridLayoutInterface layoutInterface = (GridLayoutInterface) mLayoutInterface;
212 GridLayoutInterface oldLayout = (GridLayoutInterface) sfullScreenLayoutInterface;
213 oldLayout.mNumRows = layoutInterface.mNumRows;
214 oldLayout.mSpacingX = layoutInterface.mSpacingX;
215 oldLayout.mSpacingY = layoutInterface.mSpacingY;
216 GridCamera camera = mCamera;
217 int numMaxRows = (camera.mHeight >= camera.mWidth) ? 4 : 3;
218 MediaFeed feed = mMediaFeed;
219 boolean performLayout = true;
221 float yStretch = camera.mDefaultAspectRatio / camera.mAspectRatio;
222 if (yStretch < 1.0f) {
226 case STATE_GRID_VIEW:
227 mTimeElapsedSinceGridViewReady = 0.0f;
228 if (feed != null && feedUnchanged == false) {
229 boolean updatedData = feed.restorePreviousClusteringState();
231 performLayout = false;
234 layoutInterface.mNumRows = numMaxRows;
235 layoutInterface.mSpacingX = (int) (10 * Gallery.PIXEL_DENSITY);
236 layoutInterface.mSpacingY = (int) (10 * Gallery.PIXEL_DENSITY);
237 if (mState == STATE_MEDIA_SETS) {
240 MediaSet set = feed.getCurrentSet();
241 int icon = mDrawables.getIconForSet(set, true);
243 sHud.getPathBar().pushLabel(icon, set.mNoCountTitleString, new Runnable() {
245 if (mFeedAboutToChange) {
248 if (sHud.getAlpha() == 1.0f) {
249 disableLocationFiltering();
250 mInputProcessor.clearSelection();
251 setState(STATE_GRID_VIEW);
259 if (mState == STATE_FULL_SCREEN) {
260 sHud.getPathBar().popLabel();
264 mTimeElapsedSinceStackViewReady = 0.0f;
265 if (feed != null && feedUnchanged == false) {
266 feed.performClustering();
267 performLayout = false;
269 disableLocationFiltering();
270 layoutInterface.mNumRows = numMaxRows - 1;
271 layoutInterface.mSpacingX = (int) (100 * Gallery.PIXEL_DENSITY);
272 layoutInterface.mSpacingY = (int) (70 * Gallery.PIXEL_DENSITY * yStretch);
274 case STATE_FULL_SCREEN:
275 layoutInterface.mNumRows = 1;
276 layoutInterface.mSpacingX = (int) (40 * Gallery.PIXEL_DENSITY);
277 layoutInterface.mSpacingY = (int) (40 * Gallery.PIXEL_DENSITY);
278 if (mState != STATE_FULL_SCREEN) {
279 sHud.getPathBar().pushLabel(R.drawable.ic_fs_details, "", new Runnable() {
281 if (sHud.getAlpha() == 1.0f) {
282 sHud.swapFullscreenLabel();
289 case STATE_MEDIA_SETS:
290 mTimeElapsedSinceStackViewReady = 0.0f;
291 if (feed != null && feedUnchanged == false) {
292 feed.restorePreviousClusteringState();
293 feed.expandMediaSet(Shared.INVALID);
294 performLayout = false;
296 disableLocationFiltering();
297 mInputProcessor.clearSelection();
298 layoutInterface.mNumRows = numMaxRows - 1;
299 layoutInterface.mSpacingX = (int) (100 * Gallery.PIXEL_DENSITY);
300 layoutInterface.mSpacingY = (int) (70 * Gallery.PIXEL_DENSITY * yStretch);
302 if (mState == STATE_FULL_SCREEN) {
303 sHud.getPathBar().popLabel();
305 sHud.getPathBar().popLabel();
311 sHud.onGridStateChanged();
312 if (performLayout && mFeedAboutToChange == false) {
313 onLayout(Shared.INVALID, Shared.INVALID, oldLayout);
315 if (state != STATE_FULL_SCREEN) {
321 protected void enableLocationFiltering(String label) {
322 if (mLocationFilter == false) {
323 mLocationFilter = true;
324 sHud.getPathBar().pushLabel(R.drawable.icon_location_small, label, new Runnable() {
326 if (sHud.getAlpha() == 1.0f) {
327 if (mState == STATE_FULL_SCREEN) {
328 mInputProcessor.clearSelection();
329 setState(STATE_GRID_VIEW);
331 disableLocationFiltering();
341 protected void disableLocationFiltering() {
342 if (mLocationFilter) {
343 mLocationFilter = false;
344 mMediaFeed.removeFilter();
345 sHud.getPathBar().popLabel();
350 if (mFeedAboutToChange) {
354 if (mInputProcessor.getCurrentSelectedSlot() == Shared.INVALID) {
355 if (mLocationFilter) {
356 disableLocationFiltering();
357 setState(STATE_TIMELINE);
362 case STATE_GRID_VIEW:
363 setState(STATE_MEDIA_SETS);
366 setState(STATE_GRID_VIEW);
368 case STATE_FULL_SCREEN:
369 setState(STATE_GRID_VIEW);
370 mInputProcessor.clearSelection();
378 public void endSlideshow() {
379 mSlideshowMode = false;
380 if (mWakeLock != null) {
381 if (mWakeLock.isHeld()) {
390 public void onSensorChanged(RenderView view, SensorEvent event) {
391 mInputProcessor.onSensorChanged(view, event, mState);
394 public DataSource getDataSource() {
395 if (mMediaFeed != null)
396 return mMediaFeed.getDataSource();
400 public void setDataSource(DataSource dataSource) {
401 MediaFeed feed = mMediaFeed;
404 sDisplayList.clear();
407 mMediaFeed = new MediaFeed(mContext, dataSource, this);
411 public IndexRange getVisibleRange() {
412 return sVisibleRange;
415 public IndexRange getBufferedVisibleRange() {
416 return sBufferedVisibleRange;
419 public IndexRange getCompleteRange() {
420 return sCompleteRange;
423 private int hitTest(Vector3f worldPos, int itemWidth, int itemHeight) {
424 int retVal = Shared.INVALID;
425 int firstSlotIndex = 0;
426 int lastSlotIndex = 0;
427 IndexRange rangeToUse = sVisibleRange;
428 synchronized (rangeToUse) {
429 firstSlotIndex = rangeToUse.begin;
430 lastSlotIndex = rangeToUse.end;
432 Pool<Vector3f> pool = sTempVec;
433 float itemWidthBy2 = itemWidth * 0.5f;
434 float itemHeightBy2 = itemHeight * 0.5f;
435 Vector3f position = pool.create();
436 Vector3f deltaAnchorPosition = pool.create();
438 deltaAnchorPosition.set(sDeltaAnchorPosition);
439 for (int i = firstSlotIndex; i <= lastSlotIndex; ++i) {
440 GridCameraManager.getSlotPositionForSlotIndex(i, mCamera, mLayoutInterface, deltaAnchorPosition, position);
441 if (FloatUtils.boundsContainsPoint(position.x - itemWidthBy2, position.x + itemWidthBy2,
442 position.y - itemHeightBy2, position.y + itemHeightBy2, worldPos.x, worldPos.y)) {
448 pool.delete(deltaAnchorPosition);
449 pool.delete(position);
454 void centerCameraForSlot(int slotIndex, float baseConvergence) {
455 float imageTheta = 0.0f;
456 DisplayItem displayItem = getDisplayItemForSlotId(slotIndex);
457 if (displayItem != null) {
458 imageTheta = displayItem.getImageTheta();
460 mCameraManager.centerCameraForSlot(mLayoutInterface, slotIndex, baseConvergence, sDeltaAnchorPositionUncommited,
461 mInputProcessor.getCurrentSelectedSlot(), mZoomValue, imageTheta, mState);
464 boolean constrainCameraForSlot(int slotIndex) {
465 return mCameraManager.constrainCameraForSlot(mLayoutInterface, slotIndex, sDeltaAnchorPosition, mCurrentFocusItemWidth,
466 mCurrentFocusItemHeight);
469 // Called on render thread before rendering.
471 public boolean update(RenderView view, float timeElapsed) {
472 if (mFeedAboutToChange == false) {
473 mTimeElapsedSinceTransition += timeElapsed;
474 mTimeElapsedSinceGridViewReady += timeElapsed;
475 if (mTimeElapsedSinceGridViewReady >= 1.0f) {
476 mTimeElapsedSinceGridViewReady = 1.0f;
478 mTimeElapsedSinceStackViewReady += timeElapsed;
479 if (mTimeElapsedSinceStackViewReady >= 1.0f) {
480 mTimeElapsedSinceStackViewReady = 1.0f;
483 mTimeElapsedSinceTransition = 0;
485 if (mMediaFeed != null && mMediaFeed.isSingleImageMode()) {
486 HudLayer hud = getHud();
487 hud.getPathBar().setHidden(true);
488 hud.getMenuBar().setHidden(true);
489 if (hud.getMode() != HudLayer.MODE_NORMAL)
490 hud.setMode(HudLayer.MODE_NORMAL);
492 if (view.elapsedLoadingExpensiveTextures() > 150 || (mMediaFeed != null && mMediaFeed.getWaitingForMediaScanner())) {
493 sHud.getPathBar().setAnimatedIcons(GridDrawables.TEXTURE_SPINNER);
495 sHud.getPathBar().setAnimatedIcons(null);
498 // In that case, we need to commit the respective Display Items when the
500 GridCamera camera = mCamera;
501 camera.update(timeElapsed);
502 DisplayItem anchorDisplayItem = getAnchorDisplayItem(ANCHOR_CENTER);
503 if (anchorDisplayItem != null && !sHud.getTimeBar().isDragged()) {
504 sHud.getTimeBar().setItem(anchorDisplayItem.mItemRef);
506 sDisplayList.update(timeElapsed);
507 mInputProcessor.update(timeElapsed);
508 mSelectedAlpha = FloatUtils.animate(mSelectedAlpha, mTargetAlpha, timeElapsed * 0.5f);
509 if (mState == STATE_FULL_SCREEN) {
512 sHud.autoHide(false);
515 GridQuad[] fullscreenQuads = GridDrawables.sFullscreenGrid;
516 int numFullScreenQuads = fullscreenQuads.length;
517 for (int i = 0; i < numFullScreenQuads; ++i) {
518 fullscreenQuads[i].update(timeElapsed);
520 if (mSlideshowMode && mState == STATE_FULL_SCREEN) {
521 mTimeElapsedSinceView += timeElapsed;
522 if (mTimeElapsedSinceView > SLIDESHOW_TRANSITION_TIME) {
523 // time to go to the next slide
524 mTimeElapsedSinceView = 0.0f;
525 changeFocusToNextSlot(0.5f);
526 mCamera.commitMoveInX();
527 mCamera.commitMoveInY();
530 if (mState == STATE_MEDIA_SETS || mState == STATE_TIMELINE) {
531 mCamera.moveYTo(-0.1f);
532 mCamera.commitMoveInY();
534 boolean dirty = mDrawManager.update(timeElapsed);
535 dirty |= mSlideshowMode;
536 dirty |= mFramesDirty > 0;
538 if (mFramesDirty > 0) {
542 if (mMediaFeed != null && (mMediaFeed.getWaitingForMediaScanner())) {
543 // We limit the drawing of the frame so that the MediaScanner
544 // thread can do its work
547 } catch (InterruptedException e) {
550 if (sDisplayList.getNumAnimatables() != 0 || mCamera.isAnimating()
551 || (mTimeElapsedSinceTransition > 0.0f && mTimeElapsedSinceTransition < 1.0f) || mSelectedAlpha != mTargetAlpha
552 // || (mAnimatedFov != mTargetFov)
559 private void computeVisibleRange() {
560 if (mPerformingLayoutChange)
562 if (sDeltaAnchorPosition.equals(sDeltaAnchorPositionUncommited) == false) {
563 sDeltaAnchorPosition.set(sDeltaAnchorPositionUncommited);
565 mCameraManager.computeVisibleRange(mMediaFeed, mLayoutInterface, sDeltaAnchorPosition, sVisibleRange,
566 sBufferedVisibleRange, sCompleteRange, mState);
569 private void computeVisibleItems() {
570 if (mFeedAboutToChange == true || mPerformingLayoutChange == true) {
573 computeVisibleRange();
574 int deltaBegin = sBufferedVisibleRange.begin - sPreviousDataRange.begin;
575 int deltaEnd = sBufferedVisibleRange.end - sPreviousDataRange.end;
576 if (deltaBegin != 0 || deltaEnd != 0) {
577 // The delta has changed, we have to compute the display items
579 // We find the intersection range, these slots have not changed at
581 int firstVisibleSlotIndex = sBufferedVisibleRange.begin;
582 int lastVisibleSlotIndex = sBufferedVisibleRange.end;
583 sPreviousDataRange.begin = firstVisibleSlotIndex;
584 sPreviousDataRange.end = lastVisibleSlotIndex;
586 Pool<Vector3f> pool = sTempVec;
587 Vector3f position = pool.create();
588 Vector3f deltaAnchorPosition = pool.create();
590 MediaFeed feed = mMediaFeed;
591 DisplayList displayList = sDisplayList;
592 DisplayItem[] displayItems = sDisplayItems;
593 DisplaySlot[] displaySlots = sDisplaySlots;
594 int numDisplayItems = displayItems.length;
595 int numDisplaySlots = displaySlots.length;
596 ArrayList<MediaItem> visibleItems = sVisibleItems;
597 deltaAnchorPosition.set(sDeltaAnchorPosition);
598 LayoutInterface layout = mLayoutInterface;
599 GridCamera camera = mCamera;
600 for (int i = firstVisibleSlotIndex; i <= lastVisibleSlotIndex; ++i) {
601 GridCameraManager.getSlotPositionForSlotIndex(i, camera, layout, deltaAnchorPosition, position);
602 MediaSet set = feed.getSetForSlot(i);
603 int indexIntoSlots = i - firstVisibleSlotIndex;
605 if (set != null && indexIntoSlots >= 0 && indexIntoSlots < numDisplaySlots) {
606 ArrayList<MediaItem> items = set.getItems();
607 displaySlots[indexIntoSlots].setMediaSet(set);
608 ArrayList<MediaItem> bestItems = sTempList;
609 if (mTimeElapsedSinceTransition < 1.0f) {
610 // We always show the same top thumbnails for a
612 if (mState == STATE_MEDIA_SETS)
613 ArrayUtils.computeSortedIntersection(items, visibleItems, MAX_ITEMS_PER_SLOT, bestItems, sTempHash);
615 ArrayUtils.computeSortedIntersection(visibleItems, items, MAX_ITEMS_PER_SLOT, bestItems, sTempHash);
618 int numItemsInSet = set.getNumItems();
619 int numBestItems = bestItems.size();
620 int originallyFoundItems = numBestItems;
621 if (numBestItems < MAX_ITEMS_PER_SLOT) {
622 int itemsRemaining = MAX_ITEMS_PER_SLOT - numBestItems;
623 for (int currItemPos = 0; currItemPos < numItemsInSet; currItemPos++) {
624 MediaItem item = items.get(currItemPos);
625 if (mTimeElapsedSinceTransition >= 1.0f || !bestItems.contains(item)) {
627 if (--itemsRemaining == 0) {
633 numBestItems = bestItems.size();
634 int baseIndex = (i - firstVisibleSlotIndex) * MAX_ITEMS_PER_SLOT;
635 for (int j = 0; j < numBestItems; ++j) {
636 if (baseIndex + j >= numDisplayItems) {
639 if (j >= numItemsInSet) {
640 displayItems[baseIndex + j] = null;
642 MediaItem item = bestItems.get(j);
644 DisplayItem displayItem = displayList.get(item);
645 if ((mState == STATE_FULL_SCREEN && i != mInputProcessor.getCurrentSelectedSlot())
646 || (mState == STATE_GRID_VIEW && (mTimeElapsedSinceTransition > 1.0f || j >= originallyFoundItems))) {
647 displayItem.set(position, j, false);
648 displayItem.commit();
650 displayList.setPositionAndStackIndex(displayItem, position, j, true);
652 displayItems[baseIndex + j] = displayItem;
656 for (int j = numBestItems; j < MAX_ITEMS_PER_SLOT; ++j) {
657 displayItems[baseIndex + j] = null;
663 mFeedChanged = false;
664 if (mInputProcessor != null && mState == STATE_FULL_SCREEN && mRequestFocusContentUri == null) {
665 int currentSelectedSlot = mInputProcessor.getCurrentSelectedSlot();
666 if (currentSelectedSlot > sCompleteRange.end)
667 currentSelectedSlot = sCompleteRange.end;
668 mInputProcessor.setCurrentSelectedSlot(currentSelectedSlot);
670 if (mState == STATE_GRID_VIEW) {
671 MediaSet expandedSet = mMediaFeed.getExpandedMediaSet();
672 if (expandedSet != null) {
673 if (!sHud.getPathBar().getCurrentLabel().equals(expandedSet.mNoCountTitleString)) {
674 sHud.getPathBar().changeLabel(expandedSet.mNoCountTitleString);
678 if (mRequestFocusContentUri != null) {
679 // We have to find the item that has this contentUri
680 if (mState == STATE_FULL_SCREEN) {
681 int numSlots = sCompleteRange.end + 1;
682 for (int i = 0; i < numSlots; ++i) {
683 MediaSet set = feed.getSetForSlot(i);
684 ArrayList<MediaItem> items = set.getItems();
685 int numItems = items.size();
686 for (int j = 0; j < numItems; ++j) {
687 String itemUri = items.get(j).mContentUri;
688 if (itemUri != null && mRequestFocusContentUri != null) {
689 if (itemUri.equals(mRequestFocusContentUri)) {
690 mInputProcessor.setCurrentSelectedSlot(i);
691 mRequestFocusContentUri = null;
701 pool.delete(position);
702 pool.delete(deltaAnchorPosition);
704 // We keep upto 400 thumbnails in memory.
705 int numThumbnailsToKeepInMemory = (mState == STATE_MEDIA_SETS || mState == STATE_TIMELINE) ? 100 : 400;
706 int startMemoryRange = (sBufferedVisibleRange.begin / numThumbnailsToKeepInMemory) * numThumbnailsToKeepInMemory;
707 if (mStartMemoryRange != startMemoryRange) {
708 mStartMemoryRange = startMemoryRange;
709 clearUnusedThumbnails();
715 public void handleLowMemory() {
716 clearUnusedThumbnails();
717 GridDrawables.sStringTextureTable.clear();
718 mBackground.clearCache();
721 // This method can be potentially expensive
722 public void clearUnusedThumbnails() {
723 sDisplayList.clearExcept(sDisplayItems);
727 public void onSurfaceCreated(RenderView view, GL11 gl) {
728 sDisplayList.clear();
731 GridDrawables.sStringTextureTable.clear();
732 mDrawables.onSurfaceCreated(view, gl);
737 public void onSurfaceChanged(RenderView view, int width, int height) {
738 mCamera.viewportChanged(width, height, mCamera.mItemWidth, mCamera.mItemHeight);
739 view.setFov(mCamera.mFov);
743 // Renders the node in a given pass.
744 public void renderOpaque(RenderView view, GL11 gl) {
745 GridCamera camera = mCamera;
746 int selectedSlotIndex = mInputProcessor.getCurrentSelectedSlot();
747 computeVisibleItems();
749 gl.glMatrixMode(GL11.GL_MODELVIEW);
751 GLU.gluLookAt(gl, -camera.mEyeX, -camera.mEyeY, -camera.mEyeZ, -camera.mLookAtX, -camera.mLookAtY, -camera.mLookAtZ,
752 camera.mUpX, camera.mUpY, camera.mUpZ);
754 if (mSelectedAlpha != 1.0f) {
755 gl.glEnable(GL11.GL_BLEND);
756 gl.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
757 view.setAlpha(mSelectedAlpha);
759 if (selectedSlotIndex != Shared.INVALID) {
764 mDrawManager.prepareDraw(sBufferedVisibleRange, sVisibleRange, selectedSlotIndex, mInputProcessor.getCurrentFocusSlot(),
765 mInputProcessor.isFocusItemPressed());
766 if (mSelectedAlpha != 0.0f) {
767 mDrawManager.drawThumbnails(view, gl, mState);
769 if (mSelectedAlpha != 1.0f) {
770 gl.glDisable(GL11.GL_BLEND);
772 // We draw the selected slotIndex.
773 if (selectedSlotIndex != Shared.INVALID) {
774 mDrawManager.drawFocusItems(view, gl, mZoomValue, mSlideshowMode, mTimeElapsedSinceView);
775 mCurrentFocusItemWidth = mDrawManager.getFocusQuadWidth();
776 mCurrentFocusItemHeight = mDrawManager.getFocusQuadHeight();
778 view.setAlpha(mSelectedAlpha);
781 public void renderBlended(RenderView view, GL11 gl) {
782 // We draw the placeholder for all visible slots.
783 if (sHud != null && mDrawManager != null) {
784 mDrawManager.drawBlendedComponents(view, gl, mSelectedAlpha, mState, sHud.getMode(), mTimeElapsedSinceStackViewReady,
785 mTimeElapsedSinceGridViewReady, sBucketList, mMediaFeed.getWaitingForMediaScanner() || mFeedAboutToChange
786 || mMediaFeed.isLoading());
790 public synchronized void onLayout(int newAnchorSlotIndex, int currentAnchorSlotIndex, LayoutInterface oldLayout) {
791 if (mPerformingLayoutChange || !sDeltaAnchorPosition.equals(sDeltaAnchorPositionUncommited)) {
795 mTimeElapsedSinceTransition = 0.0f;
796 mPerformingLayoutChange = true;
797 LayoutInterface layout = mLayoutInterface;
798 if (oldLayout == null) {
799 oldLayout = sfullScreenLayoutInterface;
801 GridCamera camera = mCamera;
802 if (currentAnchorSlotIndex == Shared.INVALID) {
803 currentAnchorSlotIndex = getAnchorSlotIndex(ANCHOR_CENTER);
804 if (mCurrentExpandedSlot != Shared.INVALID) {
805 currentAnchorSlotIndex = mCurrentExpandedSlot;
807 int selectedSlotIndex = mInputProcessor.getCurrentSelectedSlot();
808 if (selectedSlotIndex != Shared.INVALID) {
809 currentAnchorSlotIndex = selectedSlotIndex;
812 if (newAnchorSlotIndex == Shared.INVALID) {
813 newAnchorSlotIndex = currentAnchorSlotIndex;
815 int itemHeight = camera.mItemHeight;
816 int itemWidth = camera.mItemWidth;
817 Pool<Vector3f> pool = sTempVec;
818 Vector3f deltaAnchorPosition = pool.create();
819 Vector3f currentSlotPosition = pool.create();
821 deltaAnchorPosition.set(0, 0, 0);
822 if (currentAnchorSlotIndex != Shared.INVALID && newAnchorSlotIndex != Shared.INVALID) {
823 layout.getPositionForSlotIndex(newAnchorSlotIndex, itemWidth, itemHeight, deltaAnchorPosition);
824 oldLayout.getPositionForSlotIndex(currentAnchorSlotIndex, itemWidth, itemHeight, currentSlotPosition);
825 currentSlotPosition.subtract(sDeltaAnchorPosition);
826 deltaAnchorPosition.subtract(currentSlotPosition);
827 deltaAnchorPosition.y = 0;
828 deltaAnchorPosition.z = 0;
830 sDeltaAnchorPositionUncommited.set(deltaAnchorPosition);
832 pool.delete(deltaAnchorPosition);
833 pool.delete(currentSlotPosition);
835 centerCameraForSlot(newAnchorSlotIndex, 1.0f);
836 mCurrentExpandedSlot = Shared.INVALID;
838 // Force recompute of visible items and their positions.
839 ((GridLayoutInterface) oldLayout).mNumRows = ((GridLayoutInterface) layout).mNumRows;
840 ((GridLayoutInterface) oldLayout).mSpacingX = ((GridLayoutInterface) layout).mSpacingX;
841 ((GridLayoutInterface) oldLayout).mSpacingY = ((GridLayoutInterface) layout).mSpacingY;
842 forceRecomputeVisibleRange();
843 mPerformingLayoutChange = false;
846 private void forceRecomputeVisibleRange() {
847 sPreviousDataRange.begin = Shared.INVALID;
848 sPreviousDataRange.end = Shared.INVALID;
850 mView.requestRender();
854 // called on background thread
855 public synchronized void onFeedChanged(MediaFeed feed, boolean needsLayout) {
858 forceRecomputeVisibleRange();
859 if (mState == STATE_GRID_VIEW || mState == STATE_FULL_SCREEN)
860 sHud.setFeed(feed, mState, needsLayout);
864 while (mPerformingLayoutChange == true) {
867 if (mState == STATE_GRID_VIEW) {
869 MediaSet set = feed.getCurrentSet();
870 if (set != null && !mLocationFilter)
871 sHud.getPathBar().changeLabel(set.mNoCountTitleString);
874 DisplayItem[] displayItems = sDisplayItems;
875 int firstBufferedVisibleSlotIndex = sBufferedVisibleRange.begin;
876 int lastBufferedVisibleSlotIndex = sBufferedVisibleRange.end;
877 int currentlyVisibleSlotIndex = getAnchorSlotIndex(ANCHOR_CENTER);
878 if (mCurrentExpandedSlot != Shared.INVALID) {
879 currentlyVisibleSlotIndex = mCurrentExpandedSlot;
881 MediaItem anchorItem = null;
882 ArrayList<MediaItem> visibleItems = sVisibleItems;
883 visibleItems.clear();
884 visibleItems.ensureCapacity(lastBufferedVisibleSlotIndex - firstBufferedVisibleSlotIndex);
885 if (currentlyVisibleSlotIndex != Shared.INVALID && currentlyVisibleSlotIndex >= firstBufferedVisibleSlotIndex
886 && currentlyVisibleSlotIndex <= lastBufferedVisibleSlotIndex) {
887 int baseIndex = (currentlyVisibleSlotIndex - firstBufferedVisibleSlotIndex) * MAX_ITEMS_PER_SLOT;
888 for (int i = 0; i < MAX_ITEMS_PER_SLOT; ++i) {
889 DisplayItem displayItem = displayItems[baseIndex + i];
890 if (displayItem != null) {
891 if (anchorItem == null) {
892 anchorItem = displayItem.mItemRef;
894 visibleItems.add(displayItem.mItemRef);
898 // We want to add items from the middle.
899 int numItems = lastBufferedVisibleSlotIndex - firstBufferedVisibleSlotIndex + 1;
900 int midPoint = (lastBufferedVisibleSlotIndex - firstBufferedVisibleSlotIndex) / 2;
901 int length = displayItems.length;
902 for (int i = 0; i < numItems; ++i) {
903 int index = midPoint + Shared.midPointIterator(i);
904 int indexIntoDisplayItem = (index - firstBufferedVisibleSlotIndex) * MAX_ITEMS_PER_SLOT;
905 if (indexIntoDisplayItem >= 0 && indexIntoDisplayItem < length) {
906 for (int j = 0; j < MAX_ITEMS_PER_SLOT; ++j) {
907 DisplayItem displayItem = displayItems[indexIntoDisplayItem + j];
908 if (displayItem != null) {
909 MediaItem item = displayItem.mItemRef;
910 if (item != anchorItem) {
911 visibleItems.add(item);
917 int newSlotIndex = Shared.INVALID;
918 if (anchorItem != null) {
919 // We try to find the anchor item in the new feed.
920 int numSlots = feed.getNumSlots();
921 for (int i = 0; i < numSlots; ++i) {
922 MediaSet set = feed.getSetForSlot(i);
923 if (set != null && set.containsItem(anchorItem)) {
930 if (anchorItem != null && newSlotIndex == Shared.INVALID) {
931 int numSlots = feed.getNumSlots();
932 MediaSet parentSet = anchorItem.mParentMediaSet;
933 for (int i = 0; i < numSlots; ++i) {
934 MediaSet set = feed.getSetForSlot(i);
935 if (set != null && set.mId == parentSet.mId) {
942 // We must create a new display store now since the data has changed.
943 if (newSlotIndex != Shared.INVALID) {
944 if (mState == STATE_MEDIA_SETS) {
945 sDisplayList.clearExcept(displayItems);
947 onLayout(newSlotIndex, currentlyVisibleSlotIndex, null);
949 forceRecomputeVisibleRange();
951 mCurrentExpandedSlot = Shared.INVALID;
952 mFeedAboutToChange = false;
955 if (mState == STATE_GRID_VIEW || mState == STATE_FULL_SCREEN)
956 sHud.setFeed(feed, mState, needsLayout);
959 mView.requestRender();
963 public DisplayItem getRepresentativeDisplayItem() {
964 int slotIndex = Shared.INVALID;
965 if (mInputProcessor != null) {
966 slotIndex = mInputProcessor.getCurrentFocusSlot();
968 if (slotIndex == Shared.INVALID) {
969 slotIndex = getAnchorSlotIndex(ANCHOR_CENTER);
971 int index = (slotIndex - sBufferedVisibleRange.begin) * MAX_ITEMS_PER_SLOT;
972 if (index >= 0 && index < MAX_ITEMS_DRAWABLE) {
973 return sDisplayItems[index];
979 public DisplayItem getAnchorDisplayItem(int type) {
980 int slotIndex = getAnchorSlotIndex(type);
981 return sDisplayItems[(slotIndex - sBufferedVisibleRange.begin) * MAX_ITEMS_PER_SLOT];
984 public float getScrollPosition() {
985 return (mCamera.mLookAtX * mCamera.mScale + sDeltaAnchorPosition.x); // in
989 public DisplayItem getDisplayItemForScrollPosition(float posX) {
990 Pool<Vector3f> pool = sTempVecAlt;
991 MediaFeed feed = mMediaFeed;
992 int itemWidth = mCamera.mItemWidth;
993 int itemHeight = mCamera.mItemHeight;
994 GridLayoutInterface gridInterface = (GridLayoutInterface) mLayoutInterface;
995 float absolutePosX = posX;
996 int left = (int) ((absolutePosX / itemWidth) * gridInterface.mNumRows);
997 int right = feed == null ? 0 : (int) (feed.getNumSlots());
999 Vector3f position = pool.create();
1001 for (int i = left; i < right; ++i) {
1002 gridInterface.getPositionForSlotIndex(i, itemWidth, itemHeight, position);
1004 if (position.x >= absolutePosX) {
1009 pool.delete(position);
1011 if (mFeedAboutToChange) {
1014 right = feed == null ? 0 : feed.getNumSlots();
1019 if (retSlot >= right)
1020 retSlot = right - 1;
1021 MediaSet set = feed.getSetForSlot(retSlot);
1023 ArrayList<MediaItem> items = set.getItems();
1024 if (items != null && set.getNumItems() > 0) {
1025 return (sDisplayList.get(items.get(0)));
1031 // Returns the top left-most item.
1032 public int getAnchorSlotIndex(int anchorType) {
1034 switch (anchorType) {
1036 retVal = sVisibleRange.begin;
1039 retVal = sVisibleRange.end;
1042 retVal = (sVisibleRange.begin + sVisibleRange.end) / 2;
1048 DisplayItem getDisplayItemForSlotId(int slotId) {
1049 int index = slotId - sBufferedVisibleRange.begin;
1050 if (index >= 0 && slotId <= sBufferedVisibleRange.end) {
1051 return sDisplayItems[index * MAX_ITEMS_PER_SLOT];
1056 boolean changeFocusToNextSlot(float convergence) {
1057 int currentSelectedSlot = mInputProcessor.getCurrentSelectedSlot();
1058 boolean retVal = changeFocusToSlot(currentSelectedSlot + 1, convergence);
1059 if (mInputProcessor.getCurrentSelectedSlot() == currentSelectedSlot) {
1061 sHud.setAlpha(1.0f);
1066 boolean changeFocusToSlot(int slotId, float convergence) {
1068 int index = slotId - sBufferedVisibleRange.begin;
1069 if (index >= 0 && slotId <= sBufferedVisibleRange.end) {
1070 DisplayItem displayItem = sDisplayItems[index * MAX_ITEMS_PER_SLOT];
1071 if (displayItem != null) {
1072 MediaItem item = displayItem.mItemRef;
1073 sHud.fullscreenSelectionChanged(item, slotId + 1, sCompleteRange.end + 1);
1074 if (slotId != Shared.INVALID && slotId <= sCompleteRange.end) {
1075 mInputProcessor.setCurrentFocusSlot(slotId);
1076 centerCameraForSlot(slotId, convergence);
1079 centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), convergence);
1087 boolean changeFocusToPreviousSlot(float convergence) {
1088 return changeFocusToSlot(mInputProcessor.getCurrentSelectedSlot() - 1, convergence);
1091 public ArrayList<MediaBucket> getSelectedBuckets() {
1092 return sBucketList.get();
1095 public void selectAll() {
1096 if (mState != STATE_FULL_SCREEN) {
1097 int numSlots = sCompleteRange.end + 1;
1098 for (int i = 0; i < numSlots; ++i) {
1099 addSlotToSelectedItems(i, false, false);
1101 updateCountOfSelectedItems();
1103 addSlotToSelectedItems(mInputProcessor.getCurrentFocusSlot(), false, true);
1107 public void deselectOrCancelSelectMode() {
1108 if (sBucketList.size() == 0) {
1109 sHud.cancelSelection();
1111 sBucketList.clear();
1112 updateCountOfSelectedItems();
1116 public void deselectAll() {
1117 sHud.cancelSelection();
1118 sBucketList.clear();
1119 updateCountOfSelectedItems();
1122 public void deleteSelection() {
1123 // Delete the selection and exit selection mode.
1124 mMediaFeed.performOperation(MediaFeed.OPERATION_DELETE, getSelectedBuckets(), null);
1127 // If the current set is now empty, return to the parent set.
1128 if (sCompleteRange.isEmpty()) {
1129 goBack(); // TODO(venkat): This does not work most of the time, can
1134 void addSlotToSelectedItems(int slotId, boolean removeIfAlreadyAdded, boolean updateCount) {
1135 if (mFeedAboutToChange == false) {
1136 MediaFeed feed = mMediaFeed;
1137 sBucketList.add(slotId, feed, removeIfAlreadyAdded);
1139 updateCountOfSelectedItems();
1140 if (sBucketList.size() == 0)
1144 sHud.computeBottomMenu();
1147 private void updateCountOfSelectedItems() {
1148 sHud.updateNumItemsSelected(sBucketList.size());
1151 public int getMetadataSlotIndexForScreenPosition(int posX, int posY) {
1152 return getSlotForScreenPosition(posX, posY, mCamera.mItemWidth + (int) (100 * Gallery.PIXEL_DENSITY), mCamera.mItemHeight
1153 + (int) (100 * Gallery.PIXEL_DENSITY));
1156 public int getSlotIndexForScreenPosition(int posX, int posY) {
1157 return getSlotForScreenPosition(posX, posY, mCamera.mItemWidth, mCamera.mItemHeight);
1160 private int getSlotForScreenPosition(int posX, int posY, int itemWidth, int itemHeight) {
1161 Pool<Vector3f> pool = sTempVec;
1163 Vector3f worldPos = pool.create();
1165 GridCamera camera = mCamera;
1166 camera.convertToCameraSpace(posX, posY, 0, worldPos);
1167 // slots are expressed in pixels as well
1168 worldPos.x *= camera.mScale;
1169 worldPos.y *= camera.mScale;
1171 retVal = hitTest(worldPos, itemWidth, itemHeight);
1173 pool.delete(worldPos);
1178 public boolean tapGesture(int slotIndex, boolean metadata) {
1179 MediaFeed feed = mMediaFeed;
1180 if (!feed.isClustered()) {
1181 // It is not clustering.
1182 if (!feed.hasExpandedMediaSet()) {
1183 if (feed.canExpandSet(slotIndex)) {
1184 mCurrentExpandedSlot = slotIndex;
1185 feed.expandMediaSet(slotIndex);
1186 setState(STATE_GRID_VIEW);
1193 // Select a cluster, and recompute a new cluster within this
1195 mCurrentExpandedSlot = slotIndex;
1198 DisplaySlot slot = sDisplaySlots[slotIndex - sBufferedVisibleRange.begin];
1199 if (slot.hasValidLocation()) {
1200 MediaSet set = slot.getMediaSet();
1201 if (set.mReverseGeocodedLocation != null) {
1202 enableLocationFiltering(set.mReverseGeocodedLocation);
1204 feed.setFilter(new LocationMediaFilter(set.mMinLatLatitude, set.mMinLonLongitude, set.mMaxLatLatitude,
1205 set.mMaxLonLongitude));
1212 public void onTimeChanged(TimeBar timebar) {
1213 if (mFeedAboutToChange) {
1216 // TODO lot of optimization possible here
1217 MediaItem item = timebar.getItem();
1218 MediaFeed feed = mMediaFeed;
1219 int numSlots = feed.getNumSlots();
1220 for (int i = 0; i < numSlots; ++i) {
1221 MediaSet set = feed.getSetForSlot(i);
1225 ArrayList<MediaItem> items = set.getItems();
1226 if (items == null || set.getNumItems() == 0) {
1229 if (items.contains(item)) {
1230 centerCameraForSlot(i, 1.0f);
1236 public void onFeedAboutToChange(MediaFeed feed) {
1237 mFeedAboutToChange = true;
1238 mTimeElapsedSinceTransition = 0;
1241 public void startSlideshow() {
1243 mSlideshowMode = true;
1245 centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
1246 mTimeElapsedSinceView = SLIDESHOW_TRANSITION_TIME - 1.0f;
1248 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
1249 mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "GridView.Slideshow");
1250 mWakeLock.acquire();
1253 public void enterSelectionMode() {
1254 mSlideshowMode = false;
1255 sHud.enterSelectionMode();
1256 int currentSlot = mInputProcessor.getCurrentSelectedSlot();
1257 if (currentSlot == Shared.INVALID) {
1258 currentSlot = mInputProcessor.getCurrentFocusSlot();
1260 addSlotToSelectedItems(currentSlot, false, true);
1263 private float getFillScreenZoomValue() {
1264 return GridCameraManager.getFillScreenZoomValue(mCamera, sTempVec, mCurrentFocusItemWidth, mCurrentFocusItemHeight);
1267 public void zoomInToSelectedItem() {
1268 mSlideshowMode = false;
1269 float potentialZoomValue = getFillScreenZoomValue();
1270 if (mZoomValue < potentialZoomValue) {
1271 mZoomValue = potentialZoomValue;
1275 if (mZoomValue > 6.0f) {
1278 sHud.setAlpha(1.0f);
1279 centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
1282 public void zoomOutFromSelectedItem() {
1283 mSlideshowMode = false;
1284 if (mZoomValue == getFillScreenZoomValue()) {
1289 if (mZoomValue < 1.0f) {
1292 sHud.setAlpha(1.0f);
1293 centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
1296 public void rotateSelectedItems(float f) {
1297 MediaBucketList bucketList = sBucketList;
1298 ArrayList<MediaBucket> mediaBuckets = bucketList.get();
1299 DisplayList displayList = sDisplayList;
1300 int numBuckets = mediaBuckets.size();
1301 for (int i = 0; i < numBuckets; ++i) {
1302 MediaBucket bucket = mediaBuckets.get(i);
1303 ArrayList<MediaItem> mediaItems = bucket.mediaItems;
1304 if (mediaItems != null) {
1305 int numMediaItems = mediaItems.size();
1306 for (int j = 0; j < numMediaItems; ++j) {
1307 MediaItem item = mediaItems.get(j);
1308 DisplayItem displayItem = displayList.get(item);
1309 displayItem.rotateImageBy(f);
1310 displayList.addToAnimatables(displayItem);
1314 if (mState == STATE_FULL_SCREEN) {
1315 centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
1317 mMediaFeed.performOperation(MediaFeed.OPERATION_ROTATE, mediaBuckets, new Float(f));
1318 // we recreate these displayitems from the cache
1321 public void cropSelectedItem() {
1326 public boolean onTouchEvent(MotionEvent event) {
1327 return mInputProcessor.onTouchEvent(event);
1331 public boolean onKeyDown(int keyCode, KeyEvent event) {
1332 if (mInputProcessor != null)
1333 return mInputProcessor.onKeyDown(keyCode, event, mState);
1337 public boolean inSlideShowMode() {
1338 return mSlideshowMode;
1341 public boolean noDeleteMode() {
1342 return mNoDeleteMode || (mMediaFeed != null && mMediaFeed.isSingleImageMode());
1345 public float getZoomValue() {
1349 public boolean feedAboutToChange() {
1350 return mFeedAboutToChange;
1353 public boolean isInAlbumMode() {
1357 public Vector3f getDeltaAnchorPosition() {
1358 return sDeltaAnchorPosition;
1361 public int getExpandedSlot() {
1362 return mCurrentExpandedSlot;
1365 public GridLayoutInterface getLayoutInterface() {
1366 return (GridLayoutInterface) mLayoutInterface;
1369 public void setZoomValue(float f) {
1371 centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
1374 public void setPickIntent(boolean b) {
1376 sHud.getPathBar().popLabel();
1377 sHud.getPathBar().pushLabel(R.drawable.icon_location_small, mContext.getResources().getString(R.string.pick),
1380 if (sHud.getAlpha() == 1.0f) {
1381 if (!mFeedAboutToChange) {
1382 setState(STATE_MEDIA_SETS);
1385 sHud.setAlpha(1.0f);
1391 public boolean getPickIntent() {
1395 public void setViewIntent(boolean b, final String setName) {
1398 mMediaFeed.expandMediaSet(0);
1399 setState(STATE_GRID_VIEW);
1400 // We need to make sure we haven't pushed the same label twice
1401 if (sHud.getPathBar().getNumLevels() == 1) {
1402 sHud.getPathBar().pushLabel(R.drawable.icon_folder_small, setName, new Runnable() {
1404 if (mFeedAboutToChange) {
1407 if (sHud.getAlpha() == 1.0f) {
1408 disableLocationFiltering();
1409 if (mInputProcessor != null)
1410 mInputProcessor.clearSelection();
1411 setState(STATE_GRID_VIEW);
1413 sHud.setAlpha(1.0f);
1421 public boolean getViewIntent() {
1425 public void setSingleImage(boolean noDeleteMode) {
1426 mNoDeleteMode = noDeleteMode;
1427 mInputProcessor.setCurrentSelectedSlot(0);
1430 public MediaFeed getFeed() {
1434 public void markDirty(int numFrames) {
1435 mFramesDirty = numFrames;
1438 public void focusItem(String contentUri) {
1439 mRequestFocusContentUri = contentUri;
1440 mMediaFeed.updateListener(false);