1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.gallery3d.ui; 18 19 import android.graphics.Rect; 20 21 import com.android.gallery3d.app.GalleryActivity; 22 import com.android.gallery3d.data.MediaItem; 23 import com.android.gallery3d.ui.PositionRepository.Position; 24 25 public class AlbumView extends SlotView { 26 @SuppressWarnings("unused") 27 private static final String TAG = "AlbumView"; 28 private static final int CACHE_SIZE = 64; 29 30 private int mVisibleStart = 0; 31 private int mVisibleEnd = 0; 32 33 private AlbumSlidingWindow mDataWindow; 34 private final GalleryActivity mActivity; 35 private SelectionDrawer mSelectionDrawer; 36 private int mCacheThumbSize; 37 38 private boolean mIsActive = false; 39 40 public static interface Model { 41 public int size(); 42 public MediaItem get(int index); 43 public void setActiveWindow(int start, int end); 44 public void setModelListener(ModelListener listener); 45 } 46 47 public static interface ModelListener { 48 public void onWindowContentChanged(int index); 49 public void onSizeChanged(int size); 50 } 51 52 public AlbumView(GalleryActivity activity, SlotView.Spec spec, 53 int cacheThumbSize) { 54 super(activity.getAndroidContext()); 55 mCacheThumbSize = cacheThumbSize; 56 setSlotSpec(spec); 57 mActivity = activity; 58 } 59 60 public void setSelectionDrawer(SelectionDrawer drawer) { 61 mSelectionDrawer = drawer; 62 if (mDataWindow != null) mDataWindow.setSelectionDrawer(drawer); 63 } 64 65 public void setModel(Model model) { 66 if (mDataWindow != null) { 67 mDataWindow.setListener(null); 68 setSlotCount(0); 69 mDataWindow = null; 70 } 71 if (model != null) { 72 mDataWindow = new AlbumSlidingWindow( 73 mActivity, model, CACHE_SIZE, 74 mCacheThumbSize); 75 mDataWindow.setSelectionDrawer(mSelectionDrawer); 76 mDataWindow.setListener(new MyDataModelListener()); 77 setSlotCount(model.size()); 78 updateVisibleRange(getVisibleStart(), getVisibleEnd()); 79 } 80 } 81 82 public void setFocusIndex(int slotIndex) { 83 if (mDataWindow != null) { 84 mDataWindow.setFocusIndex(slotIndex); 85 } 86 } 87 88 private void putSlotContent(int slotIndex, DisplayItem item) { 89 Rect rect = getSlotRect(slotIndex); 90 Position position = new Position( 91 (rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2, 0); 92 putDisplayItem(position, position, item); 93 } 94 95 private void updateVisibleRange(int start, int end) { 96 if (start == mVisibleStart && end == mVisibleEnd) { 97 // we need to set the mDataWindow active range in any case. 98 mDataWindow.setActiveWindow(start, end); 99 return; 100 } 101 102 if (!mIsActive) { 103 mVisibleStart = start; 104 mVisibleEnd = end; 105 mDataWindow.setActiveWindow(start, end); 106 return; 107 } 108 109 if (start >= mVisibleEnd || mVisibleStart >= end) { 110 for (int i = mVisibleStart, n = mVisibleEnd; i < n; ++i) { 111 DisplayItem item = mDataWindow.get(i); 112 if (item != null) removeDisplayItem(item); 113 } 114 mDataWindow.setActiveWindow(start, end); 115 for (int i = start; i < end; ++i) { 116 putSlotContent(i, mDataWindow.get(i)); 117 } 118 } else { 119 for (int i = mVisibleStart; i < start; ++i) { 120 DisplayItem item = mDataWindow.get(i); 121 if (item != null) removeDisplayItem(item); 122 } 123 for (int i = end, n = mVisibleEnd; i < n; ++i) { 124 DisplayItem item = mDataWindow.get(i); 125 if (item != null) removeDisplayItem(item); 126 } 127 mDataWindow.setActiveWindow(start, end); 128 for (int i = start, n = mVisibleStart; i < n; ++i) { 129 putSlotContent(i, mDataWindow.get(i)); 130 } 131 for (int i = mVisibleEnd; i < end; ++i) { 132 putSlotContent(i, mDataWindow.get(i)); 133 } 134 } 135 136 mVisibleStart = start; 137 mVisibleEnd = end; 138 } 139 140 @Override 141 protected void onLayoutChanged(int width, int height) { 142 // Reput all the items 143 updateVisibleRange(0, 0); 144 updateVisibleRange(getVisibleStart(), getVisibleEnd()); 145 } 146 147 @Override 148 protected void onScrollPositionChanged(int position) { 149 super.onScrollPositionChanged(position); 150 updateVisibleRange(getVisibleStart(), getVisibleEnd()); 151 } 152 153 @Override 154 protected void render(GLCanvas canvas) { 155 mSelectionDrawer.prepareDrawing(); 156 super.render(canvas); 157 } 158 159 private class MyDataModelListener implements AlbumSlidingWindow.Listener { 160 161 public void onContentInvalidated() { 162 invalidate(); 163 } 164 165 public void onSizeChanged(int size) { 166 if (setSlotCount(size)) { 167 // If the layout parameters are changed, we need reput all items. 168 // We keep the visible range at the same center but with size 0. 169 // So that we can: 170 // 1.) flush all visible items 171 // 2.) keep the cached data 172 int center = (getVisibleStart() + getVisibleEnd()) / 2; 173 updateVisibleRange(center, center); 174 } 175 updateVisibleRange(getVisibleStart(), getVisibleEnd()); 176 invalidate(); 177 } 178 179 public void onWindowContentChanged( 180 int slotIndex, DisplayItem old, DisplayItem update) { 181 removeDisplayItem(old); 182 putSlotContent(slotIndex, update); 183 } 184 } 185 186 public void resume() { 187 mIsActive = true; 188 mDataWindow.resume(); 189 for (int i = mVisibleStart, n = mVisibleEnd; i < n; ++i) { 190 putSlotContent(i, mDataWindow.get(i)); 191 } 192 } 193 194 public void pause() { 195 mIsActive = false; 196 for (int i = mVisibleStart, n = mVisibleEnd; i < n; ++i) { 197 removeDisplayItem(mDataWindow.get(i)); 198 } 199 mDataWindow.pause(); 200 } 201 } 202