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 sSelectedBucketList = new MediaBucketList();
99 private static final MediaBucketList sMarkedBucketList = 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;
112 public GridLayer(Context context, int itemWidth, int itemHeight, LayoutInterface layoutInterface, RenderView view) {
113 mBackground = new BackgroundLayer(this);
117 DisplaySlot[] displaySlots = sDisplaySlots;
118 for (int i = 0; i < MAX_DISPLAY_SLOTS; ++i) {
119 DisplaySlot slot = new DisplaySlot();
120 displaySlots[i] = slot;
122 mLayoutInterface = layoutInterface;
123 mCamera = new GridCamera(0, 0, itemWidth, itemHeight);
124 mDrawables = new GridDrawables(itemWidth, itemHeight);
125 sBufferedVisibleRange.set(Shared.INVALID, Shared.INVALID);
126 sVisibleRange.set(Shared.INVALID, Shared.INVALID);
127 sCompleteRange.set(Shared.INVALID, Shared.INVALID);
128 sPreviousDataRange.set(Shared.INVALID, Shared.INVALID);
129 sDeltaAnchorPosition.set(0, 0, 0);
130 sDeltaAnchorPositionUncommited.set(0, 0, 0);
131 sSelectedBucketList.clear();
133 sVisibleItems = new ArrayList<MediaItem>();
134 mHud = new HudLayer(context);
135 mHud.setContext(context);
136 mHud.setGridLayer(this);
137 mHud.getPathBar().clear();
138 mHud.setGridLayer(this);
139 mHud.getTimeBar().setListener(this);
140 mHud.getPathBar().pushLabel(R.drawable.icon_home_small, context.getResources().getString(R.string.app_name),
143 if (mHud.getAlpha() == 1.0f) {
144 if (!mFeedAboutToChange) {
145 setState(STATE_MEDIA_SETS);
152 mCameraManager = new GridCameraManager(mCamera);
153 mDrawManager = new GridDrawManager(context, mCamera, mDrawables, sDisplayList, sDisplayItems, sDisplaySlots);
154 mInputProcessor = new GridInputProcessor(context, mCamera, this, mView, sTempVec, sDisplayItems);
155 setState(STATE_MEDIA_SETS);
158 public HudLayer getHud() {
162 public void shutdown() {
163 if (mMediaFeed != null) {
164 mMediaFeed.shutdown();
167 sSelectedBucketList.clear();
178 public void generate(RenderView view, RenderView.Lists lists) {
179 lists.updateList.add(this);
180 lists.opaqueList.add(this);
181 mBackground.generate(view, lists);
182 lists.blendedList.add(this);
183 lists.hitTestList.add(this);
184 mHud.generate(view, lists);
188 protected void onSizeChanged() {
189 mHud.setSize(mWidth, mHeight);
191 mBackground.setSize(mWidth, mHeight);
192 mTimeElapsedSinceTransition = 0.0f;
194 mView.requestRender();
198 public int getState() {
202 public void setState(int state) {
203 boolean feedUnchanged = false;
204 if (mState == state) {
205 feedUnchanged = true;
207 GridLayoutInterface layoutInterface = (GridLayoutInterface) mLayoutInterface;
208 GridLayoutInterface oldLayout = (GridLayoutInterface) sfullScreenLayoutInterface;
209 oldLayout.mNumRows = layoutInterface.mNumRows;
210 oldLayout.mSpacingX = layoutInterface.mSpacingX;
211 oldLayout.mSpacingY = layoutInterface.mSpacingY;
212 GridCamera camera = mCamera;
213 int numMaxRows = (camera.mHeight >= camera.mWidth) ? 4 : 3;
214 MediaFeed feed = mMediaFeed;
215 boolean performLayout = true;
217 float yStretch = camera.mDefaultAspectRatio / camera.mAspectRatio;
218 if (yStretch < 1.0f) {
222 case STATE_GRID_VIEW:
223 mTimeElapsedSinceGridViewReady = 0.0f;
224 if (feed != null && feedUnchanged == false) {
225 boolean updatedData = feed.restorePreviousClusteringState();
227 performLayout = false;
230 layoutInterface.mNumRows = numMaxRows;
231 layoutInterface.mSpacingX = (int) (10 * Gallery.PIXEL_DENSITY);
232 layoutInterface.mSpacingY = (int) (10 * Gallery.PIXEL_DENSITY);
233 if (mState == STATE_MEDIA_SETS) {
236 MediaSet set = feed.getCurrentSet();
237 int icon = mDrawables.getIconForSet(set, true);
239 mHud.getPathBar().pushLabel(icon, set.mNoCountTitleString, new Runnable() {
241 if (mFeedAboutToChange) {
244 if (mHud.getAlpha() == 1.0f) {
245 disableLocationFiltering();
246 mInputProcessor.clearSelection();
247 setState(STATE_GRID_VIEW);
255 if (mState == STATE_FULL_SCREEN) {
256 mHud.getPathBar().popLabel();
260 mTimeElapsedSinceStackViewReady = 0.0f;
261 if (feed != null && feedUnchanged == false) {
262 feed.performClustering();
263 performLayout = false;
265 disableLocationFiltering();
266 layoutInterface.mNumRows = numMaxRows - 1;
267 layoutInterface.mSpacingX = (int) (100 * Gallery.PIXEL_DENSITY);
268 layoutInterface.mSpacingY = (int) (70 * Gallery.PIXEL_DENSITY * yStretch);
270 case STATE_FULL_SCREEN:
271 layoutInterface.mNumRows = 1;
272 layoutInterface.mSpacingX = (int) (40 * Gallery.PIXEL_DENSITY);
273 layoutInterface.mSpacingY = (int) (40 * Gallery.PIXEL_DENSITY);
274 if (mState != STATE_FULL_SCREEN) {
275 mHud.getPathBar().pushLabel(R.drawable.ic_fs_details, "", new Runnable() {
277 if (mHud.getAlpha() == 1.0f) {
278 mHud.swapFullscreenLabel();
285 case STATE_MEDIA_SETS:
286 mTimeElapsedSinceStackViewReady = 0.0f;
287 if (feed != null && feedUnchanged == false) {
288 feed.restorePreviousClusteringState();
289 sMarkedBucketList.clear();
290 feed.expandMediaSet(Shared.INVALID);
291 performLayout = false;
293 disableLocationFiltering();
294 mInputProcessor.clearSelection();
295 layoutInterface.mNumRows = numMaxRows - 1;
296 layoutInterface.mSpacingX = (int) (100 * Gallery.PIXEL_DENSITY);
297 layoutInterface.mSpacingY = (int) (70 * Gallery.PIXEL_DENSITY * yStretch);
299 if (mState == STATE_FULL_SCREEN) {
300 mHud.getPathBar().popLabel();
302 mHud.getPathBar().popLabel();
308 mHud.onGridStateChanged();
309 if (performLayout && mFeedAboutToChange == false) {
310 onLayout(Shared.INVALID, Shared.INVALID, oldLayout);
312 if (state != STATE_FULL_SCREEN) {
318 protected void enableLocationFiltering(String label) {
319 if (mLocationFilter == false) {
320 mLocationFilter = true;
321 mHud.getPathBar().pushLabel(R.drawable.icon_location_small, label, new Runnable() {
323 if (mHud.getAlpha() == 1.0f) {
324 if (mState == STATE_FULL_SCREEN) {
325 mInputProcessor.clearSelection();
326 setState(STATE_GRID_VIEW);
328 disableLocationFiltering();
338 protected void disableLocationFiltering() {
339 if (mLocationFilter) {
340 mLocationFilter = false;
341 mMediaFeed.removeFilter();
342 mHud.getPathBar().popLabel();
347 if (mFeedAboutToChange) {
351 if (mInputProcessor.getCurrentSelectedSlot() == Shared.INVALID) {
352 if (mLocationFilter) {
353 disableLocationFiltering();
354 setState(STATE_TIMELINE);
359 case STATE_GRID_VIEW:
360 setState(STATE_MEDIA_SETS);
363 setState(STATE_GRID_VIEW);
365 case STATE_FULL_SCREEN:
366 setState(STATE_GRID_VIEW);
367 mInputProcessor.clearSelection();
375 public void endSlideshow() {
376 mSlideshowMode = false;
377 if (mWakeLock != null) {
378 if (mWakeLock.isHeld()) {
387 public void onSensorChanged(RenderView view, SensorEvent event) {
388 mInputProcessor.onSensorChanged(view, event, mState);
391 public DataSource getDataSource() {
392 if (mMediaFeed != null)
393 return mMediaFeed.getDataSource();
397 public void setDataSource(DataSource dataSource) {
398 MediaFeed feed = mMediaFeed;
401 sDisplayList.clear();
404 mMediaFeed = new MediaFeed(mContext, dataSource, this);
408 public IndexRange getVisibleRange() {
409 return sVisibleRange;
412 public IndexRange getBufferedVisibleRange() {
413 return sBufferedVisibleRange;
416 public IndexRange getCompleteRange() {
417 return sCompleteRange;
420 private int hitTest(Vector3f worldPos, int itemWidth, int itemHeight) {
421 int retVal = Shared.INVALID;
422 int firstSlotIndex = 0;
423 int lastSlotIndex = 0;
424 IndexRange rangeToUse = sVisibleRange;
425 synchronized (rangeToUse) {
426 firstSlotIndex = rangeToUse.begin;
427 lastSlotIndex = rangeToUse.end;
429 Pool<Vector3f> pool = sTempVec;
430 float itemWidthBy2 = itemWidth * 0.5f;
431 float itemHeightBy2 = itemHeight * 0.5f;
432 Vector3f position = pool.create();
433 Vector3f deltaAnchorPosition = pool.create();
435 deltaAnchorPosition.set(sDeltaAnchorPosition);
436 for (int i = firstSlotIndex; i <= lastSlotIndex; ++i) {
437 GridCameraManager.getSlotPositionForSlotIndex(i, mCamera, mLayoutInterface, deltaAnchorPosition, position);
438 if (FloatUtils.boundsContainsPoint(position.x - itemWidthBy2, position.x + itemWidthBy2,
439 position.y - itemHeightBy2, position.y + itemHeightBy2, worldPos.x, worldPos.y)) {
445 pool.delete(deltaAnchorPosition);
446 pool.delete(position);
451 void centerCameraForSlot(int slotIndex, float baseConvergence) {
452 float imageTheta = 0.0f;
453 DisplayItem displayItem = getDisplayItemForSlotId(slotIndex);
454 if (displayItem != null) {
455 imageTheta = displayItem.getImageTheta();
457 mCameraManager.centerCameraForSlot(mLayoutInterface, slotIndex, baseConvergence, sDeltaAnchorPositionUncommited,
458 mInputProcessor.getCurrentSelectedSlot(), mZoomValue, imageTheta, mState);
461 boolean constrainCameraForSlot(int slotIndex) {
462 return mCameraManager.constrainCameraForSlot(mLayoutInterface, slotIndex, sDeltaAnchorPosition, mCurrentFocusItemWidth,
463 mCurrentFocusItemHeight);
466 // Called on render thread before rendering.
468 public boolean update(RenderView view, float timeElapsed) {
469 if (mFeedAboutToChange == false) {
470 mTimeElapsedSinceTransition += timeElapsed;
471 mTimeElapsedSinceGridViewReady += timeElapsed;
472 if (mTimeElapsedSinceGridViewReady >= 1.0f) {
473 mTimeElapsedSinceGridViewReady = 1.0f;
475 mTimeElapsedSinceStackViewReady += timeElapsed;
476 if (mTimeElapsedSinceStackViewReady >= 1.0f) {
477 mTimeElapsedSinceStackViewReady = 1.0f;
480 mTimeElapsedSinceTransition = 0;
482 if (mMediaFeed != null && mMediaFeed.isSingleImageMode()) {
483 HudLayer hud = getHud();
484 hud.getPathBar().setHidden(true);
485 hud.getMenuBar().setHidden(true);
486 if (hud.getMode() != HudLayer.MODE_NORMAL)
487 hud.setMode(HudLayer.MODE_NORMAL);
489 if (view.elapsedLoadingExpensiveTextures() > 150 || (mMediaFeed != null && mMediaFeed.getWaitingForMediaScanner())) {
490 mHud.getPathBar().setAnimatedIcons(GridDrawables.TEXTURE_SPINNER);
492 mHud.getPathBar().setAnimatedIcons(null);
495 // In that case, we need to commit the respective Display Items when the
497 GridCamera camera = mCamera;
498 camera.update(timeElapsed);
499 DisplayItem anchorDisplayItem = getAnchorDisplayItem(ANCHOR_CENTER);
500 if (anchorDisplayItem != null && !mHud.getTimeBar().isDragged()) {
501 mHud.getTimeBar().setItem(anchorDisplayItem.mItemRef);
503 sDisplayList.update(timeElapsed);
504 mInputProcessor.update(timeElapsed);
505 mSelectedAlpha = FloatUtils.animate(mSelectedAlpha, mTargetAlpha, timeElapsed * 0.5f);
506 if (mState == STATE_FULL_SCREEN) {
509 mHud.autoHide(false);
512 GridQuad[] fullscreenQuads = GridDrawables.sFullscreenGrid;
513 int numFullScreenQuads = fullscreenQuads.length;
514 for (int i = 0; i < numFullScreenQuads; ++i) {
515 fullscreenQuads[i].update(timeElapsed);
517 if (mSlideshowMode && mState == STATE_FULL_SCREEN) {
518 mTimeElapsedSinceView += timeElapsed;
519 if (mTimeElapsedSinceView > SLIDESHOW_TRANSITION_TIME) {
520 // time to go to the next slide
521 mTimeElapsedSinceView = 0.0f;
522 changeFocusToNextSlot(0.5f);
523 mCamera.commitMoveInX();
524 mCamera.commitMoveInY();
527 if (mState == STATE_MEDIA_SETS || mState == STATE_TIMELINE) {
528 mCamera.moveYTo(-0.1f);
529 mCamera.commitMoveInY();
531 boolean dirty = mDrawManager.update(timeElapsed);
532 dirty |= mSlideshowMode;
533 dirty |= mFramesDirty > 0;
535 if (mFramesDirty > 0) {
539 if (mMediaFeed != null && (mMediaFeed.getWaitingForMediaScanner())) {
540 // We limit the drawing of the frame so that the MediaScanner
541 // thread can do its work
544 } catch (InterruptedException e) {
547 if (sDisplayList.getNumAnimatables() != 0 || mCamera.isAnimating()
548 || (mTimeElapsedSinceTransition > 0.0f && mTimeElapsedSinceTransition < 1.0f) || mSelectedAlpha != mTargetAlpha
549 // || (mAnimatedFov != mTargetFov)
556 private void computeVisibleRange() {
557 if (mPerformingLayoutChange)
559 if (sDeltaAnchorPosition.equals(sDeltaAnchorPositionUncommited) == false) {
560 sDeltaAnchorPosition.set(sDeltaAnchorPositionUncommited);
562 mCameraManager.computeVisibleRange(mMediaFeed, mLayoutInterface, sDeltaAnchorPosition, sVisibleRange,
563 sBufferedVisibleRange, sCompleteRange, mState);
566 private void computeVisibleItems() {
567 if (mFeedAboutToChange == true || mPerformingLayoutChange == true) {
570 computeVisibleRange();
571 int deltaBegin = sBufferedVisibleRange.begin - sPreviousDataRange.begin;
572 int deltaEnd = sBufferedVisibleRange.end - sPreviousDataRange.end;
573 if (deltaBegin != 0 || deltaEnd != 0) {
574 // The delta has changed, we have to compute the display items
576 // We find the intersection range, these slots have not changed at
578 int firstVisibleSlotIndex = sBufferedVisibleRange.begin;
579 int lastVisibleSlotIndex = sBufferedVisibleRange.end;
580 sPreviousDataRange.begin = firstVisibleSlotIndex;
581 sPreviousDataRange.end = lastVisibleSlotIndex;
583 Pool<Vector3f> pool = sTempVec;
584 Vector3f position = pool.create();
585 Vector3f deltaAnchorPosition = pool.create();
587 MediaFeed feed = mMediaFeed;
588 DisplayList displayList = sDisplayList;
589 DisplayItem[] displayItems = sDisplayItems;
590 DisplaySlot[] displaySlots = sDisplaySlots;
591 int numDisplayItems = displayItems.length;
592 int numDisplaySlots = displaySlots.length;
593 ArrayList<MediaItem> visibleItems = sVisibleItems;
594 deltaAnchorPosition.set(sDeltaAnchorPosition);
595 LayoutInterface layout = mLayoutInterface;
596 GridCamera camera = mCamera;
597 for (int i = firstVisibleSlotIndex; i <= lastVisibleSlotIndex; ++i) {
598 GridCameraManager.getSlotPositionForSlotIndex(i, camera, layout, deltaAnchorPosition, position);
599 MediaSet set = feed.getSetForSlot(i);
600 int indexIntoSlots = i - firstVisibleSlotIndex;
602 if (set != null && indexIntoSlots >= 0 && indexIntoSlots < numDisplaySlots) {
603 ArrayList<MediaItem> items = set.getItems();
604 displaySlots[indexIntoSlots].setMediaSet(set);
605 ArrayList<MediaItem> bestItems = sTempList;
606 if (mTimeElapsedSinceTransition < 1.0f) {
607 // We always show the same top thumbnails for a
609 if (mState == STATE_MEDIA_SETS)
610 ArrayUtils.computeSortedIntersection(items, visibleItems, MAX_ITEMS_PER_SLOT, bestItems, sTempHash);
612 ArrayUtils.computeSortedIntersection(visibleItems, items, MAX_ITEMS_PER_SLOT, bestItems, sTempHash);
615 int numItemsInSet = set.getNumItems();
616 int numBestItems = bestItems.size();
617 int originallyFoundItems = numBestItems;
618 if (numBestItems < MAX_ITEMS_PER_SLOT) {
619 int itemsRemaining = MAX_ITEMS_PER_SLOT - numBestItems;
620 for (int currItemPos = 0; currItemPos < numItemsInSet; currItemPos++) {
621 MediaItem item = items.get(currItemPos);
622 if (mTimeElapsedSinceTransition >= 1.0f || !bestItems.contains(item)) {
624 if (--itemsRemaining == 0) {
630 numBestItems = bestItems.size();
631 int baseIndex = (i - firstVisibleSlotIndex) * MAX_ITEMS_PER_SLOT;
632 for (int j = 0; j < numBestItems; ++j) {
633 if (baseIndex + j >= numDisplayItems) {
636 if (j >= numItemsInSet) {
637 displayItems[baseIndex + j] = null;
639 MediaItem item = bestItems.get(j);
641 DisplayItem displayItem = displayList.get(item);
642 if ((mState == STATE_FULL_SCREEN && i != mInputProcessor.getCurrentSelectedSlot())
643 || (mState == STATE_GRID_VIEW && (mTimeElapsedSinceTransition > 1.0f || j >= originallyFoundItems))) {
644 displayItem.set(position, j, false);
645 displayItem.commit();
647 displayList.setPositionAndStackIndex(displayItem, position, j, true);
649 displayItems[baseIndex + j] = displayItem;
653 for (int j = numBestItems; j < MAX_ITEMS_PER_SLOT; ++j) {
654 displayItems[baseIndex + j] = null;
660 mFeedChanged = false;
661 if (mInputProcessor != null && mState == STATE_FULL_SCREEN && mRequestFocusContentUri == null) {
662 int currentSelectedSlot = mInputProcessor.getCurrentSelectedSlot();
663 if (currentSelectedSlot > sCompleteRange.end)
664 currentSelectedSlot = sCompleteRange.end;
665 mInputProcessor.setCurrentSelectedSlot(currentSelectedSlot);
667 if (mState == STATE_GRID_VIEW) {
668 MediaSet expandedSet = mMediaFeed.getExpandedMediaSet();
669 if (expandedSet != null) {
670 if (!mHud.getPathBar().getCurrentLabel().equals(expandedSet.mNoCountTitleString)) {
671 mHud.getPathBar().changeLabel(expandedSet.mNoCountTitleString);
675 if (mRequestFocusContentUri != null) {
676 // We have to find the item that has this contentUri
677 if (mState == STATE_FULL_SCREEN) {
678 int numSlots = sCompleteRange.end + 1;
679 for (int i = 0; i < numSlots; ++i) {
680 MediaSet set = feed.getSetForSlot(i);
681 ArrayList<MediaItem> items = set.getItems();
682 int numItems = items.size();
683 for (int j = 0; j < numItems; ++j) {
684 String itemUri = items.get(j).mContentUri;
685 if (itemUri != null && mRequestFocusContentUri != null) {
686 if (itemUri.equals(mRequestFocusContentUri)) {
687 mInputProcessor.setCurrentSelectedSlot(i);
694 mRequestFocusContentUri = null;
698 pool.delete(position);
699 pool.delete(deltaAnchorPosition);
701 // We keep upto 400 thumbnails in memory.
702 int numThumbnailsToKeepInMemory = (mState == STATE_MEDIA_SETS || mState == STATE_TIMELINE) ? 100 : 400;
703 int startMemoryRange = (sBufferedVisibleRange.begin / numThumbnailsToKeepInMemory) * numThumbnailsToKeepInMemory;
704 if (mStartMemoryRange != startMemoryRange) {
705 mStartMemoryRange = startMemoryRange;
706 clearUnusedThumbnails();
712 public void handleLowMemory() {
713 clearUnusedThumbnails();
714 GridDrawables.sStringTextureTable.clear();
715 mBackground.clearCache();
718 // This method can be potentially expensive
719 public void clearUnusedThumbnails() {
720 sDisplayList.clearExcept(sDisplayItems);
724 public void onSurfaceCreated(RenderView view, GL11 gl) {
725 sDisplayList.clear();
728 GridDrawables.sStringTextureTable.clear();
729 mDrawables.onSurfaceCreated(view, gl);
734 public void onSurfaceChanged(RenderView view, int width, int height) {
735 mCamera.viewportChanged(width, height, mCamera.mItemWidth, mCamera.mItemHeight);
736 view.setFov(mCamera.mFov);
740 // Renders the node in a given pass.
741 public void renderOpaque(RenderView view, GL11 gl) {
742 GridCamera camera = mCamera;
743 int selectedSlotIndex = mInputProcessor.getCurrentSelectedSlot();
744 computeVisibleItems();
746 gl.glMatrixMode(GL11.GL_MODELVIEW);
748 GLU.gluLookAt(gl, -camera.mEyeX, -camera.mEyeY, -camera.mEyeZ, -camera.mLookAtX, -camera.mLookAtY, -camera.mLookAtZ,
749 camera.mUpX, camera.mUpY, camera.mUpZ);
751 if (mSelectedAlpha != 1.0f) {
752 gl.glEnable(GL11.GL_BLEND);
753 gl.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
754 view.setAlpha(mSelectedAlpha);
756 if (selectedSlotIndex != Shared.INVALID) {
761 mDrawManager.prepareDraw(sBufferedVisibleRange, sVisibleRange, selectedSlotIndex, mInputProcessor.getCurrentFocusSlot(),
762 mInputProcessor.isFocusItemPressed());
763 if (mSelectedAlpha != 0.0f) {
764 mDrawManager.drawThumbnails(view, gl, mState);
766 if (mSelectedAlpha != 1.0f) {
767 gl.glDisable(GL11.GL_BLEND);
769 // We draw the selected slotIndex.
770 if (selectedSlotIndex != Shared.INVALID) {
771 mDrawManager.drawFocusItems(view, gl, mZoomValue, mSlideshowMode, mTimeElapsedSinceView);
772 mCurrentFocusItemWidth = mDrawManager.getFocusQuadWidth();
773 mCurrentFocusItemHeight = mDrawManager.getFocusQuadHeight();
775 view.setAlpha(mSelectedAlpha);
778 public void renderBlended(RenderView view, GL11 gl) {
779 // We draw the placeholder for all visible slots.
780 if (mHud != null && mDrawManager != null) {
781 mDrawManager.drawBlendedComponents(view, gl, mSelectedAlpha, mState, mHud.getMode(), mTimeElapsedSinceStackViewReady,
782 mTimeElapsedSinceGridViewReady, sSelectedBucketList, sMarkedBucketList, mMediaFeed.getWaitingForMediaScanner()
783 || mFeedAboutToChange || mMediaFeed.isLoading());
787 public synchronized void onLayout(int newAnchorSlotIndex, int currentAnchorSlotIndex, LayoutInterface oldLayout) {
788 if (mPerformingLayoutChange || !sDeltaAnchorPosition.equals(sDeltaAnchorPositionUncommited)) {
792 mTimeElapsedSinceTransition = 0.0f;
793 mPerformingLayoutChange = true;
794 LayoutInterface layout = mLayoutInterface;
795 if (oldLayout == null) {
796 oldLayout = sfullScreenLayoutInterface;
798 GridCamera camera = mCamera;
799 if (currentAnchorSlotIndex == Shared.INVALID) {
800 currentAnchorSlotIndex = getAnchorSlotIndex(ANCHOR_CENTER);
801 if (mCurrentExpandedSlot != Shared.INVALID) {
802 currentAnchorSlotIndex = mCurrentExpandedSlot;
804 int selectedSlotIndex = mInputProcessor.getCurrentSelectedSlot();
805 if (selectedSlotIndex != Shared.INVALID) {
806 currentAnchorSlotIndex = selectedSlotIndex;
809 if (newAnchorSlotIndex == Shared.INVALID) {
810 newAnchorSlotIndex = currentAnchorSlotIndex;
812 int itemHeight = camera.mItemHeight;
813 int itemWidth = camera.mItemWidth;
814 Pool<Vector3f> pool = sTempVec;
815 Vector3f deltaAnchorPosition = pool.create();
816 Vector3f currentSlotPosition = pool.create();
818 deltaAnchorPosition.set(0, 0, 0);
819 if (currentAnchorSlotIndex != Shared.INVALID && newAnchorSlotIndex != Shared.INVALID) {
820 layout.getPositionForSlotIndex(newAnchorSlotIndex, itemWidth, itemHeight, deltaAnchorPosition);
821 oldLayout.getPositionForSlotIndex(currentAnchorSlotIndex, itemWidth, itemHeight, currentSlotPosition);
822 currentSlotPosition.subtract(sDeltaAnchorPosition);
823 deltaAnchorPosition.subtract(currentSlotPosition);
824 deltaAnchorPosition.y = 0;
825 deltaAnchorPosition.z = 0;
827 sDeltaAnchorPositionUncommited.set(deltaAnchorPosition);
829 pool.delete(deltaAnchorPosition);
830 pool.delete(currentSlotPosition);
832 centerCameraForSlot(newAnchorSlotIndex, 1.0f);
833 mCurrentExpandedSlot = Shared.INVALID;
835 // Force recompute of visible items and their positions.
836 ((GridLayoutInterface) oldLayout).mNumRows = ((GridLayoutInterface) layout).mNumRows;
837 ((GridLayoutInterface) oldLayout).mSpacingX = ((GridLayoutInterface) layout).mSpacingX;
838 ((GridLayoutInterface) oldLayout).mSpacingY = ((GridLayoutInterface) layout).mSpacingY;
839 forceRecomputeVisibleRange();
840 mPerformingLayoutChange = false;
843 private void forceRecomputeVisibleRange() {
844 sPreviousDataRange.begin = Shared.INVALID;
845 sPreviousDataRange.end = Shared.INVALID;
847 mView.requestRender();
851 // called on background thread
852 public synchronized void onFeedChanged(MediaFeed feed, boolean needsLayout) {
855 forceRecomputeVisibleRange();
856 if (mState == STATE_GRID_VIEW || mState == STATE_FULL_SCREEN)
857 mHud.setFeed(feed, mState, needsLayout);
861 while (mPerformingLayoutChange == true) {
864 if (mState == STATE_GRID_VIEW) {
866 MediaSet set = feed.getCurrentSet();
867 if (set != null && !mLocationFilter)
868 mHud.getPathBar().changeLabel(set.mNoCountTitleString);
871 DisplayItem[] displayItems = sDisplayItems;
872 int firstBufferedVisibleSlotIndex = sBufferedVisibleRange.begin;
873 int lastBufferedVisibleSlotIndex = sBufferedVisibleRange.end;
874 int currentlyVisibleSlotIndex = getAnchorSlotIndex(ANCHOR_CENTER);
875 if (mCurrentExpandedSlot != Shared.INVALID) {
876 currentlyVisibleSlotIndex = mCurrentExpandedSlot;
878 MediaItem anchorItem = null;
879 ArrayList<MediaItem> visibleItems = sVisibleItems;
880 visibleItems.clear();
881 visibleItems.ensureCapacity(lastBufferedVisibleSlotIndex - firstBufferedVisibleSlotIndex);
882 if (currentlyVisibleSlotIndex != Shared.INVALID && currentlyVisibleSlotIndex >= firstBufferedVisibleSlotIndex
883 && currentlyVisibleSlotIndex <= lastBufferedVisibleSlotIndex) {
884 int baseIndex = (currentlyVisibleSlotIndex - firstBufferedVisibleSlotIndex) * MAX_ITEMS_PER_SLOT;
885 for (int i = 0; i < MAX_ITEMS_PER_SLOT; ++i) {
886 DisplayItem displayItem = displayItems[baseIndex + i];
887 if (displayItem != null) {
888 if (anchorItem == null) {
889 anchorItem = displayItem.mItemRef;
891 visibleItems.add(displayItem.mItemRef);
895 // We want to add items from the middle.
896 int numItems = lastBufferedVisibleSlotIndex - firstBufferedVisibleSlotIndex + 1;
897 int midPoint = (lastBufferedVisibleSlotIndex - firstBufferedVisibleSlotIndex) / 2;
898 int length = displayItems.length;
899 for (int i = 0; i < numItems; ++i) {
900 int index = midPoint + Shared.midPointIterator(i);
901 int indexIntoDisplayItem = (index - firstBufferedVisibleSlotIndex) * MAX_ITEMS_PER_SLOT;
902 if (indexIntoDisplayItem >= 0 && indexIntoDisplayItem < length) {
903 for (int j = 0; j < MAX_ITEMS_PER_SLOT; ++j) {
904 DisplayItem displayItem = displayItems[indexIntoDisplayItem + j];
905 if (displayItem != null) {
906 MediaItem item = displayItem.mItemRef;
907 if (item != anchorItem) {
908 visibleItems.add(item);
914 int newSlotIndex = Shared.INVALID;
915 if (anchorItem != null) {
916 // We try to find the anchor item in the new feed.
917 int numSlots = feed.getNumSlots();
918 for (int i = 0; i < numSlots; ++i) {
919 MediaSet set = feed.getSetForSlot(i);
920 if (set != null && set.containsItem(anchorItem)) {
927 if (anchorItem != null && newSlotIndex == Shared.INVALID) {
928 int numSlots = feed.getNumSlots();
929 MediaSet parentSet = anchorItem.mParentMediaSet;
930 for (int i = 0; i < numSlots; ++i) {
931 MediaSet set = feed.getSetForSlot(i);
932 if (set != null && set.mId == parentSet.mId) {
939 // We must create a new display store now since the data has changed.
940 if (newSlotIndex != Shared.INVALID) {
941 if (mState == STATE_MEDIA_SETS) {
942 sDisplayList.clearExcept(displayItems);
944 onLayout(newSlotIndex, currentlyVisibleSlotIndex, null);
946 forceRecomputeVisibleRange();
948 mCurrentExpandedSlot = Shared.INVALID;
949 mFeedAboutToChange = false;
952 if (mState == STATE_GRID_VIEW || mState == STATE_FULL_SCREEN)
953 mHud.setFeed(feed, mState, needsLayout);
956 mView.requestRender();
960 public DisplayItem getRepresentativeDisplayItem() {
961 int slotIndex = Shared.INVALID;
962 if (mInputProcessor != null) {
963 slotIndex = mInputProcessor.getCurrentFocusSlot();
965 if (slotIndex == Shared.INVALID) {
966 slotIndex = getAnchorSlotIndex(ANCHOR_CENTER);
968 int index = (slotIndex - sBufferedVisibleRange.begin) * MAX_ITEMS_PER_SLOT;
969 if (index >= 0 && index < MAX_ITEMS_DRAWABLE) {
970 return sDisplayItems[index];
976 public DisplayItem getAnchorDisplayItem(int type) {
977 int slotIndex = getAnchorSlotIndex(type);
978 return sDisplayItems[(slotIndex - sBufferedVisibleRange.begin) * MAX_ITEMS_PER_SLOT];
981 public float getScrollPosition() {
982 return (mCamera.mLookAtX * mCamera.mScale + sDeltaAnchorPosition.x); // in
986 public DisplayItem getDisplayItemForScrollPosition(float posX) {
987 Pool<Vector3f> pool = sTempVecAlt;
988 MediaFeed feed = mMediaFeed;
989 int itemWidth = mCamera.mItemWidth;
990 int itemHeight = mCamera.mItemHeight;
991 GridLayoutInterface gridInterface = (GridLayoutInterface) mLayoutInterface;
992 float absolutePosX = posX;
993 int left = (int) ((absolutePosX / itemWidth) * gridInterface.mNumRows);
994 int right = feed == null ? 0 : (int) (feed.getNumSlots());
996 Vector3f position = pool.create();
998 for (int i = left; i < right; ++i) {
999 gridInterface.getPositionForSlotIndex(i, itemWidth, itemHeight, position);
1001 if (position.x >= absolutePosX) {
1006 pool.delete(position);
1008 if (mFeedAboutToChange) {
1011 right = feed == null ? 0 : feed.getNumSlots();
1016 if (retSlot >= right)
1017 retSlot = right - 1;
1018 MediaSet set = feed.getSetForSlot(retSlot);
1020 ArrayList<MediaItem> items = set.getItems();
1021 if (items != null && set.getNumItems() > 0) {
1022 return (sDisplayList.get(items.get(0)));
1028 // Returns the top left-most item.
1029 public int getAnchorSlotIndex(int anchorType) {
1031 switch (anchorType) {
1033 retVal = sVisibleRange.begin;
1036 retVal = sVisibleRange.end;
1039 retVal = (sVisibleRange.begin + sVisibleRange.end) / 2;
1045 DisplayItem getDisplayItemForSlotId(int slotId) {
1046 int index = slotId - sBufferedVisibleRange.begin;
1047 if (index >= 0 && slotId <= sBufferedVisibleRange.end) {
1048 return sDisplayItems[index * MAX_ITEMS_PER_SLOT];
1053 boolean changeFocusToNextSlot(float convergence) {
1054 int currentSelectedSlot = mInputProcessor.getCurrentSelectedSlot();
1055 boolean retVal = changeFocusToSlot(currentSelectedSlot + 1, convergence);
1056 if (mInputProcessor.getCurrentSelectedSlot() == currentSelectedSlot) {
1058 mHud.setAlpha(1.0f);
1063 boolean changeFocusToSlot(int slotId, float convergence) {
1065 int index = slotId - sBufferedVisibleRange.begin;
1066 if (index >= 0 && slotId <= sBufferedVisibleRange.end) {
1067 DisplayItem displayItem = sDisplayItems[index * MAX_ITEMS_PER_SLOT];
1068 if (displayItem != null) {
1069 MediaItem item = displayItem.mItemRef;
1070 mHud.fullscreenSelectionChanged(item, slotId + 1, sCompleteRange.end + 1);
1071 if (slotId != Shared.INVALID && slotId <= sCompleteRange.end) {
1072 mInputProcessor.setCurrentFocusSlot(slotId);
1073 centerCameraForSlot(slotId, convergence);
1076 centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), convergence);
1084 boolean changeFocusToPreviousSlot(float convergence) {
1085 return changeFocusToSlot(mInputProcessor.getCurrentSelectedSlot() - 1, convergence);
1088 public ArrayList<MediaBucket> getSelectedBuckets() {
1089 return sSelectedBucketList.get();
1092 public void selectAll() {
1093 if (mState != STATE_FULL_SCREEN) {
1094 int numSlots = sCompleteRange.end + 1;
1095 for (int i = 0; i < numSlots; ++i) {
1096 addSlotToSelectedItems(i, false, false);
1098 updateCountOfSelectedItems();
1100 addSlotToSelectedItems(mInputProcessor.getCurrentFocusSlot(), false, true);
1104 public void deselectOrCancelSelectMode() {
1105 if (sSelectedBucketList.size() == 0) {
1106 mHud.cancelSelection();
1108 sSelectedBucketList.clear();
1109 updateCountOfSelectedItems();
1113 public void deselectAll() {
1114 mHud.cancelSelection();
1115 sSelectedBucketList.clear();
1116 updateCountOfSelectedItems();
1119 public void deleteSelection() {
1120 // Delete the selection and exit selection mode.
1121 mMediaFeed.performOperation(MediaFeed.OPERATION_DELETE, getSelectedBuckets(), null);
1124 // If the current set is now empty, return to the parent set.
1125 if (sCompleteRange.isEmpty()) {
1126 goBack(); // TODO(venkat): This does not work most of the time, can
1131 void addSlotToSelectedItems(int slotId, boolean removeIfAlreadyAdded, boolean updateCount) {
1132 if (mFeedAboutToChange == false) {
1133 MediaFeed feed = mMediaFeed;
1134 sSelectedBucketList.add(slotId, feed, removeIfAlreadyAdded);
1136 updateCountOfSelectedItems();
1137 if (sSelectedBucketList.size() == 0)
1141 mHud.computeBottomMenu();
1144 private void updateCountOfSelectedItems() {
1145 mHud.updateNumItemsSelected(sSelectedBucketList.size());
1148 public int getMetadataSlotIndexForScreenPosition(int posX, int posY) {
1149 return getSlotForScreenPosition(posX, posY, mCamera.mItemWidth + (int) (100 * Gallery.PIXEL_DENSITY), mCamera.mItemHeight
1150 + (int) (100 * Gallery.PIXEL_DENSITY));
1153 public int getSlotIndexForScreenPosition(int posX, int posY) {
1154 return getSlotForScreenPosition(posX, posY, mCamera.mItemWidth, mCamera.mItemHeight);
1157 private int getSlotForScreenPosition(int posX, int posY, int itemWidth, int itemHeight) {
1158 Pool<Vector3f> pool = sTempVec;
1160 Vector3f worldPos = pool.create();
1162 GridCamera camera = mCamera;
1163 camera.convertToCameraSpace(posX, posY, 0, worldPos);
1164 // slots are expressed in pixels as well
1165 worldPos.x *= camera.mScale;
1166 worldPos.y *= camera.mScale;
1168 retVal = hitTest(worldPos, itemWidth, itemHeight);
1170 pool.delete(worldPos);
1175 public boolean tapGesture(int slotIndex, boolean metadata) {
1176 MediaFeed feed = mMediaFeed;
1177 if (!feed.isClustered()) {
1178 // It is not clustering.
1179 if (!feed.hasExpandedMediaSet()) {
1180 if (feed.canExpandSet(slotIndex)) {
1181 mCurrentExpandedSlot = slotIndex;
1182 feed.expandMediaSet(slotIndex);
1183 setState(STATE_GRID_VIEW);
1190 // Select a cluster, and recompute a new cluster within this
1192 mCurrentExpandedSlot = slotIndex;
1193 sMarkedBucketList.clear();
1194 sMarkedBucketList.add(slotIndex, feed, false);
1197 DisplaySlot slot = sDisplaySlots[slotIndex - sBufferedVisibleRange.begin];
1198 if (slot.hasValidLocation()) {
1199 MediaSet set = slot.getMediaSet();
1200 if (set.mReverseGeocodedLocation != null) {
1201 enableLocationFiltering(set.mReverseGeocodedLocation);
1203 feed.setFilter(new LocationMediaFilter(set.mMinLatLatitude, set.mMinLonLongitude, set.mMaxLatLatitude,
1204 set.mMaxLonLongitude));
1211 public void onTimeChanged(TimeBar timebar) {
1212 if (mFeedAboutToChange) {
1215 // TODO lot of optimization possible here
1216 MediaItem item = timebar.getItem();
1217 MediaFeed feed = mMediaFeed;
1218 int numSlots = feed.getNumSlots();
1219 for (int i = 0; i < numSlots; ++i) {
1220 MediaSet set = feed.getSetForSlot(i);
1224 ArrayList<MediaItem> items = set.getItems();
1225 if (items == null || set.getNumItems() == 0) {
1228 if (items.contains(item)) {
1229 centerCameraForSlot(i, 1.0f);
1235 public void onFeedAboutToChange(MediaFeed feed) {
1236 mFeedAboutToChange = true;
1237 mTimeElapsedSinceTransition = 0;
1240 public void startSlideshow() {
1242 mSlideshowMode = true;
1244 centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
1245 mTimeElapsedSinceView = SLIDESHOW_TRANSITION_TIME - 1.0f;
1247 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
1248 mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "GridView.Slideshow");
1249 mWakeLock.acquire();
1252 public void enterSelectionMode() {
1253 mSlideshowMode = false;
1254 mHud.enterSelectionMode();
1255 int currentSlot = mInputProcessor.getCurrentSelectedSlot();
1256 if (currentSlot == Shared.INVALID) {
1257 currentSlot = mInputProcessor.getCurrentFocusSlot();
1259 addSlotToSelectedItems(currentSlot, false, true);
1262 private float getFillScreenZoomValue() {
1263 return GridCameraManager.getFillScreenZoomValue(mCamera, sTempVec, mCurrentFocusItemWidth, mCurrentFocusItemHeight);
1266 public void zoomInToSelectedItem() {
1267 mSlideshowMode = false;
1268 float potentialZoomValue = getFillScreenZoomValue();
1269 if (mZoomValue < potentialZoomValue) {
1270 mZoomValue = potentialZoomValue;
1274 if (mZoomValue > 6.0f) {
1277 mHud.setAlpha(1.0f);
1278 centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
1281 public void zoomOutFromSelectedItem() {
1282 mSlideshowMode = false;
1283 if (mZoomValue == getFillScreenZoomValue()) {
1288 if (mZoomValue < 1.0f) {
1291 mHud.setAlpha(1.0f);
1292 centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
1295 public void rotateSelectedItems(float f) {
1296 MediaBucketList bucketList = sSelectedBucketList;
1297 ArrayList<MediaBucket> mediaBuckets = bucketList.get();
1298 DisplayList displayList = sDisplayList;
1299 int numBuckets = mediaBuckets.size();
1300 for (int i = 0; i < numBuckets; ++i) {
1301 MediaBucket bucket = mediaBuckets.get(i);
1302 ArrayList<MediaItem> mediaItems = bucket.mediaItems;
1303 if (mediaItems != null) {
1304 int numMediaItems = mediaItems.size();
1305 for (int j = 0; j < numMediaItems; ++j) {
1306 MediaItem item = mediaItems.get(j);
1307 DisplayItem displayItem = displayList.get(item);
1308 displayItem.rotateImageBy(f);
1309 displayList.addToAnimatables(displayItem);
1313 if (mState == STATE_FULL_SCREEN) {
1314 centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
1316 mMediaFeed.performOperation(MediaFeed.OPERATION_ROTATE, mediaBuckets, new Float(f));
1317 // we recreate these displayitems from the cache
1320 public void cropSelectedItem() {
1325 public boolean onTouchEvent(MotionEvent event) {
1326 return mInputProcessor.onTouchEvent(event);
1330 public boolean onKeyDown(int keyCode, KeyEvent event) {
1331 if (mInputProcessor != null)
1332 return mInputProcessor.onKeyDown(keyCode, event, mState);
1336 public boolean inSlideShowMode() {
1337 return mSlideshowMode;
1340 public boolean noDeleteMode() {
1341 return mNoDeleteMode || (mMediaFeed != null && mMediaFeed.isSingleImageMode());
1344 public float getZoomValue() {
1348 public boolean feedAboutToChange() {
1349 return mFeedAboutToChange;
1352 public boolean isInAlbumMode() {
1356 public Vector3f getDeltaAnchorPosition() {
1357 return sDeltaAnchorPosition;
1360 public int getExpandedSlot() {
1361 return mCurrentExpandedSlot;
1364 public GridLayoutInterface getLayoutInterface() {
1365 return (GridLayoutInterface) mLayoutInterface;
1368 public void setZoomValue(float f) {
1370 centerCameraForSlot(mInputProcessor.getCurrentSelectedSlot(), 1.0f);
1373 public void setPickIntent(boolean b) {
1375 mHud.getPathBar().popLabel();
1376 mHud.getPathBar().pushLabel(R.drawable.icon_location_small, mContext.getResources().getString(R.string.pick),
1379 if (mHud.getAlpha() == 1.0f) {
1380 if (!mFeedAboutToChange) {
1381 setState(STATE_MEDIA_SETS);
1384 mHud.setAlpha(1.0f);
1390 public boolean getPickIntent() {
1394 public void setViewIntent(boolean b, final String setName) {
1397 mMediaFeed.expandMediaSet(0);
1398 setState(STATE_GRID_VIEW);
1399 // We need to make sure we haven't pushed the same label twice
1400 if (mHud.getPathBar().getNumLevels() == 1) {
1401 mHud.getPathBar().pushLabel(R.drawable.icon_folder_small, setName, new Runnable() {
1403 if (mFeedAboutToChange) {
1406 if (mHud.getAlpha() == 1.0f) {
1407 disableLocationFiltering();
1408 if (mInputProcessor != null)
1409 mInputProcessor.clearSelection();
1410 setState(STATE_GRID_VIEW);
1412 mHud.setAlpha(1.0f);
1420 public boolean getViewIntent() {
1424 public void setSingleImage(boolean noDeleteMode) {
1425 mNoDeleteMode = noDeleteMode;
1426 mInputProcessor.setCurrentSelectedSlot(0);
1429 public MediaFeed getFeed() {
1433 public void markDirty(int numFrames) {
1434 mFramesDirty = numFrames;
1437 public void focusItem(String contentUri) {
1438 mRequestFocusContentUri = contentUri;
1439 mMediaFeed.updateListener(false);