18ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin/*T
2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project
3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License");
5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License.
6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at
7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *      http://www.apache.org/licenses/LICENSE-2.0
9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software
11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS,
12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and
14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License.
15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */
16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.ui;
18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
19dbf4ba12afba115888493caa34937643257e2bb1Ray Chenimport android.graphics.Bitmap;
20dbf4ba12afba115888493caa34937643257e2bb1Ray Chenimport android.os.Message;
21dbf4ba12afba115888493caa34937643257e2bb1Ray Chen
22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.R;
23b21b8e58a604f6c701245d84b141b5b87663192bOwen Linimport com.android.gallery3d.app.AbstractGalleryActivity;
24c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Linimport com.android.gallery3d.app.AlbumSetDataLoader;
25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.common.Utils;
2631cac30e46a293f6d0901e22c6ab0d083cae7021Owen Linimport com.android.gallery3d.data.DataSourceType;
27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaItem;
281a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Linimport com.android.gallery3d.data.MediaObject;
29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaSet;
30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.Path;
31a4eae1abb4f2547dfbda84301ee764ce35464881John Reckimport com.android.gallery3d.glrenderer.BitmapTexture;
32a4eae1abb4f2547dfbda84301ee764ce35464881John Reckimport com.android.gallery3d.glrenderer.Texture;
33a4eae1abb4f2547dfbda84301ee764ce35464881John Reckimport com.android.gallery3d.glrenderer.TextureUploader;
34a4eae1abb4f2547dfbda84301ee764ce35464881John Reckimport com.android.gallery3d.glrenderer.TiledTexture;
35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.Future;
36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.FutureListener;
37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.util.ThreadPool;
38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
39c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Linpublic class AlbumSetSlidingWindow implements AlbumSetDataLoader.DataListener {
401a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private static final String TAG = "AlbumSetSlidingWindow";
411a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private static final int MSG_UPDATE_ALBUM_ENTRY = 1;
42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static interface Listener {
44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public void onSizeChanged(int size);
457260f6f74d465520e4497b23fe56f98abb0c15a2Owen Lin        public void onContentChanged();
46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
48c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Lin    private final AlbumSetDataLoader mSource;
49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private int mSize;
50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private int mContentStart = 0;
52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private int mContentEnd = 0;
53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private int mActiveStart = 0;
55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private int mActiveEnd = 0;
56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private Listener mListener;
58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
591a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private final AlbumSetEntry mData[];
60dbf4ba12afba115888493caa34937643257e2bb1Ray Chen    private final SynchronizedHandler mHandler;
61dbf4ba12afba115888493caa34937643257e2bb1Ray Chen    private final ThreadPool mThreadPool;
621a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private final AlbumLabelMaker mLabelMaker;
631a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private final String mLoadingText;
64adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin
65adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    private final TiledTexture.Uploader mContentUploader;
66adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin    private final TextureUploader mLabelUploader;
67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private int mActiveRequestCount = 0;
69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private boolean mIsActive = false;
701a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private BitmapTexture mLoadingLabel;
711a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
721a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private int mSlotWidth;
73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
741a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public static class AlbumSetEntry {
751a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public MediaSet album;
761a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public MediaItem coverItem;
771a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public Texture content;
783535d67239b1b1e4ee038f39dece64545b78f2edOwen Lin        public BitmapTexture labelTexture;
79adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin        public TiledTexture bitmapTexture;
80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public Path setPath;
818ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin        public String title;
828ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin        public int totalCount;
83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public int sourceType;
84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public int cacheFlag;
85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public int cacheStatus;
861a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public int rotation;
871a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public boolean isWaitLoadingDisplayed;
881a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public long setDataVersion;
891a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public long coverDataVersion;
901a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        private BitmapLoader labelLoader;
911a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        private BitmapLoader coverLoader;
92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
94b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin    public AlbumSetSlidingWindow(AbstractGalleryActivity activity,
95c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Lin            AlbumSetDataLoader source, AlbumSetSlotRenderer.LabelSpec labelSpec, int cacheSize) {
96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        source.setModelListener(this);
97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mSource = source;
981a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mData = new AlbumSetEntry[cacheSize];
99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mSize = source.size();
1001a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mThreadPool = activity.getThreadPool();
101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
1021a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mLabelMaker = new AlbumLabelMaker(activity.getAndroidContext(), labelSpec);
1031a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mLoadingText = activity.getAndroidContext().getString(R.string.loading);
104adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin        mContentUploader = new TiledTexture.Uploader(activity.getGLRoot());
105adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin        mLabelUploader = new TextureUploader(activity.getGLRoot());
106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mHandler = new SynchronizedHandler(activity.getGLRoot()) {
108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            @Override
109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            public void handleMessage(Message message) {
1101a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                Utils.assertTrue(message.what == MSG_UPDATE_ALBUM_ENTRY);
1111a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                ((EntryUpdater) message.obj).updateEntry();
112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        };
114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void setListener(Listener listener) {
117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mListener = listener;
118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
1201a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public AlbumSetEntry get(int slotIndex) {
121cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang        if (!isActiveSlot(slotIndex)) {
122cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang            Utils.fail("invalid slot: %s outsides (%s, %s)",
123cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang                    slotIndex, mActiveStart, mActiveEnd);
124cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang        }
125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return mData[slotIndex % mData.length];
126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public int size() {
129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return mSize;
130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public boolean isActiveSlot(int slotIndex) {
133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return slotIndex >= mActiveStart && slotIndex < mActiveEnd;
134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void setContentWindow(int contentStart, int contentEnd) {
137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (contentStart == mContentStart && contentEnd == mContentEnd) return;
138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (contentStart >= mContentEnd || mContentStart >= contentEnd) {
140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                freeSlotContent(i);
142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mSource.setActiveWindow(contentStart, contentEnd);
144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            for (int i = contentStart; i < contentEnd; ++i) {
145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                prepareSlotContent(i);
146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } else {
148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            for (int i = mContentStart; i < contentStart; ++i) {
149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                freeSlotContent(i);
150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            for (int i = contentEnd, n = mContentEnd; i < n; ++i) {
152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                freeSlotContent(i);
153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mSource.setActiveWindow(contentStart, contentEnd);
155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            for (int i = contentStart, n = mContentStart; i < n; ++i) {
156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                prepareSlotContent(i);
157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            for (int i = mContentEnd; i < contentEnd; ++i) {
159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                prepareSlotContent(i);
160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mContentStart = contentStart;
164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mContentEnd = contentEnd;
165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void setActiveWindow(int start, int end) {
168cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang        if (!(start <= end && end - start <= mData.length && end <= mSize)) {
169cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang            Utils.fail("start = %s, end = %s, length = %s, size = %s",
170cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang                    start, end, mData.length, mSize);
171cfa105d3934c4dfa14f02b693bfa97c8d17d56a9Chih-Chung Chang        }
172f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
1731a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        AlbumSetEntry data[] = mData;
174f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mActiveStart = start;
175f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mActiveEnd = end;
176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        int contentStart = Utils.clamp((start + end) / 2 - data.length / 2,
177f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                0, Math.max(0, mSize - data.length));
178f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        int contentEnd = Math.min(contentStart + data.length, mSize);
179f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        setContentWindow(contentStart, contentEnd);
180d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin
181d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        if (mIsActive) {
182d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            updateTextureUploadQueue();
183d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            updateAllImageRequests();
184d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        }
185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
186f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
187f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    // We would like to request non active slots in the following order:
188f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    // Order:    8 6 4 2                   1 3 5 7
189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    //         |---------|---------------|---------|
190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    //                   |<-  active  ->|
191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    //         |<-------- cached range ----------->|
192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void requestNonactiveImages() {
193f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        int range = Math.max(
194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mContentEnd - mActiveEnd, mActiveStart - mContentStart);
195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        for (int i = 0 ;i < range; ++i) {
196f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            requestImagesInSlot(mActiveEnd + i);
197f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            requestImagesInSlot(mActiveStart - 1 - i);
198f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
199f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
200f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
201f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void cancelNonactiveImages() {
202f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        int range = Math.max(
203f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mContentEnd - mActiveEnd, mActiveStart - mContentStart);
204f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        for (int i = 0 ;i < range; ++i) {
205f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            cancelImagesInSlot(mActiveEnd + i);
206f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            cancelImagesInSlot(mActiveStart - 1 - i);
207f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
208f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
209f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
210f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void requestImagesInSlot(int slotIndex) {
211f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (slotIndex < mContentStart || slotIndex >= mContentEnd) return;
2121a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        AlbumSetEntry entry = mData[slotIndex % mData.length];
2131a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (entry.coverLoader != null) entry.coverLoader.startLoad();
2141a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (entry.labelLoader != null) entry.labelLoader.startLoad();
215f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
216f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
217f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void cancelImagesInSlot(int slotIndex) {
218f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (slotIndex < mContentStart || slotIndex >= mContentEnd) return;
2191a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        AlbumSetEntry entry = mData[slotIndex % mData.length];
2201a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (entry.coverLoader != null) entry.coverLoader.cancelLoad();
2211a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (entry.labelLoader != null) entry.labelLoader.cancelLoad();
2221a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
2231a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
2241a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private static long getDataVersion(MediaObject object) {
2251a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        return object == null
2261a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                ? MediaSet.INVALID_DATA_VERSION
2271a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                : object.getDataVersion();
228f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
229f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
230f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void freeSlotContent(int slotIndex) {
2311a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        AlbumSetEntry entry = mData[slotIndex % mData.length];
2321a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (entry.coverLoader != null) entry.coverLoader.recycle();
2331a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (entry.labelLoader != null) entry.labelLoader.recycle();
2343535d67239b1b1e4ee038f39dece64545b78f2edOwen Lin        if (entry.labelTexture != null) entry.labelTexture.recycle();
2353535d67239b1b1e4ee038f39dece64545b78f2edOwen Lin        if (entry.bitmapTexture != null) entry.bitmapTexture.recycle();
2361a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mData[slotIndex % mData.length] = null;
237f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
238f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
2398ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin    private boolean isLabelChanged(
2408ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin            AlbumSetEntry entry, String title, int totalCount, int sourceType) {
2418ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin        return !Utils.equals(entry.title, title)
2428ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin                || entry.totalCount != totalCount
2438ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin                || entry.sourceType != sourceType;
2448ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin    }
2458ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin
2468ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin    private void updateAlbumSetEntry(AlbumSetEntry entry, int slotIndex) {
2478ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin        MediaSet album = mSource.getMediaSet(slotIndex);
2488ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin        MediaItem cover = mSource.getCoverItem(slotIndex);
2498ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin        int totalCount = mSource.getTotalCount(slotIndex);
2508ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin
2511a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        entry.album = album;
2521a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        entry.setDataVersion = getDataVersion(album);
2531a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        entry.cacheFlag = identifyCacheFlag(album);
2541a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        entry.cacheStatus = identifyCacheStatus(album);
2551a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        entry.setPath = (album == null) ? null : album.getPath();
2561a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
2578ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin        String title = (album == null) ? "" : Utils.ensureNotNull(album.getName());
2588ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin        int sourceType = DataSourceType.identifySourceType(album);
2598ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin        if (isLabelChanged(entry, title, totalCount, sourceType)) {
2608ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin            entry.title = title;
2618ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin            entry.totalCount = totalCount;
2628ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin            entry.sourceType = sourceType;
2638ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin            if (entry.labelLoader != null) {
2648ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin                entry.labelLoader.recycle();
2658ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin                entry.labelLoader = null;
2663535d67239b1b1e4ee038f39dece64545b78f2edOwen Lin                entry.labelTexture = null;
2678ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin            }
2688ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin            if (album != null) {
2698ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin                entry.labelLoader = new AlbumLabelLoader(
2708ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin                        slotIndex, title, totalCount, sourceType);
2718ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin            }
2721a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        }
2731a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
2741a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        entry.coverItem = cover;
2751a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (getDataVersion(cover) != entry.coverDataVersion) {
2761a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            entry.coverDataVersion = getDataVersion(cover);
2771a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            entry.rotation = (cover == null) ? 0 : cover.getRotation();
2781a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            if (entry.coverLoader != null) {
2791a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                entry.coverLoader.recycle();
2801a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                entry.coverLoader = null;
2813535d67239b1b1e4ee038f39dece64545b78f2edOwen Lin                entry.bitmapTexture = null;
2821a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                entry.content = null;
2831a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            }
2841a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            if (cover != null) {
2851a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                entry.coverLoader = new AlbumCoverLoader(slotIndex, cover);
2861a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            }
2871a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        }
288f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
289f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
290f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void prepareSlotContent(int slotIndex) {
2911a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        AlbumSetEntry entry = new AlbumSetEntry();
2928ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin        updateAlbumSetEntry(entry, slotIndex);
2931a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mData[slotIndex % mData.length] = entry;
294f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
295f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
2961a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private static boolean startLoadBitmap(BitmapLoader loader) {
2971a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (loader == null) return false;
2981a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        loader.startLoad();
2991a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        return loader.isRequestInProgress();
300f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
301f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
302cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin    private void uploadBackgroundTextureInSlot(int index) {
303cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin        if (index < mContentStart || index >= mContentEnd) return;
304cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin        AlbumSetEntry entry = mData[index % mData.length];
3053535d67239b1b1e4ee038f39dece64545b78f2edOwen Lin        if (entry.bitmapTexture != null) {
306adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin            mContentUploader.addTexture(entry.bitmapTexture);
307cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin        }
3083535d67239b1b1e4ee038f39dece64545b78f2edOwen Lin        if (entry.labelTexture != null) {
309adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin            mLabelUploader.addBgTexture(entry.labelTexture);
310f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
311d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin    }
3121a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
313d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin    private void updateTextureUploadQueue() {
314d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        if (!mIsActive) return;
315adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin        mContentUploader.clear();
316adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin        mLabelUploader.clear();
317cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin
318cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin        // Upload foreground texture
319cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin        for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) {
320d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            AlbumSetEntry entry = mData[i % mData.length];
3213535d67239b1b1e4ee038f39dece64545b78f2edOwen Lin            if (entry.bitmapTexture != null) {
322adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin                mContentUploader.addTexture(entry.bitmapTexture);
323cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin            }
3243535d67239b1b1e4ee038f39dece64545b78f2edOwen Lin            if (entry.labelTexture != null) {
325adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin                mLabelUploader.addFgTexture(entry.labelTexture);
326cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin            }
327cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin        }
328cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin
329cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin        // add background textures
330cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin        int range = Math.max(
331cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin                (mContentEnd - mActiveEnd), (mActiveStart - mContentStart));
332cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin        for (int i = 0; i < range; ++i) {
333cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin            uploadBackgroundTextureInSlot(mActiveEnd + i);
334cd36bfc52cc4e7f4b667ba3c5e8eb950647ae9d1Owen Lin            uploadBackgroundTextureInSlot(mActiveStart - i - 1);
335f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
336f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
337f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
338f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void updateAllImageRequests() {
339f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mActiveRequestCount = 0;
340f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) {
3411a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            AlbumSetEntry entry = mData[i % mData.length];
3421a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            if (startLoadBitmap(entry.coverLoader)) ++mActiveRequestCount;
3431a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            if (startLoadBitmap(entry.labelLoader)) ++mActiveRequestCount;
344f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
345f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mActiveRequestCount == 0) {
346f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            requestNonactiveImages();
347f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } else {
348f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            cancelNonactiveImages();
349f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
350f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
351f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
3521a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    @Override
3531a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public void onSizeChanged(int size) {
3541a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (mIsActive && mSize != size) {
3551a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mSize = size;
3561a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            if (mListener != null) mListener.onSizeChanged(mSize);
357cd938f3f05975de73658dc2f2b6c632b7ee569a3Yuli Huang            if (mContentEnd > mSize) mContentEnd = mSize;
358cd938f3f05975de73658dc2f2b6c632b7ee569a3Yuli Huang            if (mActiveEnd > mSize) mActiveEnd = mSize;
359f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
3601a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
361f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
3621a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    @Override
363c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Lin    public void onContentChanged(int index) {
3641a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (!mIsActive) {
3651a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            // paused, ignore slot changed event
3661a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            return;
3674bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin        }
368d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin
369d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        // If the updated content is not cached, ignore it
370d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        if (index < mContentStart || index >= mContentEnd) {
371d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            Log.w(TAG, String.format(
372d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin                    "invalid update: %s is outside (%s, %s)",
373d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin                    index, mContentStart, mContentEnd) );
374d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            return;
375d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        }
376d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin
377d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        AlbumSetEntry entry = mData[index % mData.length];
3788ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin        updateAlbumSetEntry(entry, index);
379d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        updateAllImageRequests();
380d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        updateTextureUploadQueue();
381d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        if (mListener != null && isActiveSlot(index)) {
382d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            mListener.onContentChanged();
383d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        }
3841a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
3854bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin
3861a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public BitmapTexture getLoadingTexture() {
3871a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (mLoadingLabel == null) {
3888ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin            Bitmap bitmap = mLabelMaker.requestLabel(
3898ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin                    mLoadingText, "", DataSourceType.TYPE_NOT_CATEGORIZED)
3901a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                    .run(ThreadPool.JOB_CONTEXT_STUB);
3911a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mLoadingLabel = new BitmapTexture(bitmap);
3921a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mLoadingLabel.setOpaque(false);
393f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
3941a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        return mLoadingLabel;
3951a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
396f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
3971a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public void pause() {
3981a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mIsActive = false;
399adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin        mLabelUploader.clear();
400adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin        mContentUploader.clear();
401adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin        TiledTexture.freeResources();
4021a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
4031a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            freeSlotContent(i);
4049201679ed1c485767f2e334aa618bd733024af03Chih-Chung Chang        }
4051a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
406f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
4071a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public void resume() {
4081a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mIsActive = true;
409adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin        TiledTexture.prepareResources();
4101a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
4111a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            prepareSlotContent(i);
4121a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        }
4131a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        updateAllImageRequests();
4141a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
415f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
4161a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private static interface EntryUpdater {
4171a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public void updateEntry();
4181a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    }
419da071d27a1435cce080b5c609d0d833555e5a175Chih-Chung Chang
4201a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private class AlbumCoverLoader extends BitmapLoader implements EntryUpdater {
4211a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        private MediaItem mMediaItem;
4221a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        private final int mSlotIndex;
4236c1f01e21406a05dc7d3258001aa901bd8628a79Chih-Chung Chang
4241a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public AlbumCoverLoader(int slotIndex, MediaItem item) {
4251a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mSlotIndex = slotIndex;
4261a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mMediaItem = item;
427f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
428f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
429f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
4301a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l) {
4311a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            return mThreadPool.submit(mMediaItem.requestImage(
4321a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                    MediaItem.TYPE_MICROTHUMBNAIL), l);
433f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
434f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
435f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
4361a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        protected void onLoadComplete(Bitmap bitmap) {
4371a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mHandler.obtainMessage(MSG_UPDATE_ALBUM_ENTRY, this).sendToTarget();
438f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
439f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
440f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
4411a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public void updateEntry() {
4421a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            Bitmap bitmap = getBitmap();
443d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            if (bitmap == null) return; // error or recycled
4441a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
4451a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            AlbumSetEntry entry = mData[mSlotIndex % mData.length];
446adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin            TiledTexture texture = new TiledTexture(bitmap);
4473535d67239b1b1e4ee038f39dece64545b78f2edOwen Lin            entry.bitmapTexture = texture;
448d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            entry.content = texture;
4491a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
4501a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            if (isActiveSlot(mSlotIndex)) {
451adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin                mContentUploader.addTexture(texture);
4521a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                --mActiveRequestCount;
4531a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                if (mActiveRequestCount == 0) requestNonactiveImages();
4541a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                if (mListener != null) mListener.onContentChanged();
455d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            } else {
456adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin                mContentUploader.addTexture(texture);
4571a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            }
458f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
459f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
460f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
461f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static int identifyCacheFlag(MediaSet set) {
462f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (set == null || (set.getSupportedOperations()
463f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                & MediaSet.SUPPORT_CACHE) == 0) {
464f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return MediaSet.CACHE_FLAG_NO;
465f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
466f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
467f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return set.getCacheFlag();
468f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
469f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
470f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static int identifyCacheStatus(MediaSet set) {
471f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (set == null || (set.getSupportedOperations()
472f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                & MediaSet.SUPPORT_CACHE) == 0) {
473f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return MediaSet.CACHE_STATUS_NOT_CACHED;
474f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
475f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
476f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return set.getCacheStatus();
477f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
478f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
4791a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    private class AlbumLabelLoader extends BitmapLoader implements EntryUpdater {
480f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private final int mSlotIndex;
4818ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin        private final String mTitle;
4828ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin        private final int mTotalCount;
4831a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        private final int mSourceType;
484f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
485d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        public AlbumLabelLoader(
4868ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin                int slotIndex, String title, int totalCount, int sourceType) {
487f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mSlotIndex = slotIndex;
4888ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin            mTitle = title;
4898ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin            mTotalCount = totalCount;
4901a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mSourceType = sourceType;
491f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
492f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
4931a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        @Override
4941a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l) {
4951a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            return mThreadPool.submit(mLabelMaker.requestLabel(
4968ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin                    mTitle, String.valueOf(mTotalCount), mSourceType), l);
497f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
498f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
499f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
5001a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        protected void onLoadComplete(Bitmap bitmap) {
5011a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            mHandler.obtainMessage(MSG_UPDATE_ALBUM_ENTRY, this).sendToTarget();
502f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
503f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
5041a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        @Override
5051a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        public void updateEntry() {
5061a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            Bitmap bitmap = getBitmap();
507d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            if (bitmap == null) return; // Error or recycled
508f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
5091a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            AlbumSetEntry entry = mData[mSlotIndex % mData.length];
510d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            BitmapTexture texture = new BitmapTexture(bitmap);
511d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            texture.setOpaque(false);
5123535d67239b1b1e4ee038f39dece64545b78f2edOwen Lin            entry.labelTexture = texture;
5131a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
5141a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            if (isActiveSlot(mSlotIndex)) {
515adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin                mLabelUploader.addFgTexture(texture);
5161a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                --mActiveRequestCount;
5171a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                if (mActiveRequestCount == 0) requestNonactiveImages();
5181a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                if (mListener != null) mListener.onContentChanged();
519d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin            } else {
520adee31f028d839e7baa8f9e052dc4e4d60b137daOwen Lin                mLabelUploader.addBgTexture(texture);
5211a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            }
522f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
523f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
524f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
5251a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin    public void onSlotSizeChanged(int width, int height) {
5261a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        if (mSlotWidth == width) return;
527d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin
5281a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mSlotWidth = width;
5291a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin        mLoadingLabel = null;
530d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        mLabelMaker.setLabelWidth(mSlotWidth);
531d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin
532d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        if (!mIsActive) return;
5331a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin
534f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
5351a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            AlbumSetEntry entry = mData[i % mData.length];
5361a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            if (entry.labelLoader != null) {
5371a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                entry.labelLoader.recycle();
5381a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin                entry.labelLoader = null;
5393535d67239b1b1e4ee038f39dece64545b78f2edOwen Lin                entry.labelTexture = null;
5401a4bd273afe5dd11592f7625c2f19853b6f174e9Owen Lin            }
5418ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin            if (entry.album != null) {
5428ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin                entry.labelLoader = new AlbumLabelLoader(i,
5438ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin                        entry.title, entry.totalCount, entry.sourceType);
5448ef6c55bdad9a3e835ce56bdc98681434b4ac5b3Owen Lin            }
545f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
546f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        updateAllImageRequests();
547d8fb81f601830385a2343d08ad5dd171e4c7bfe0Owen Lin        updateTextureUploadQueue();
548f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
549f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin}
550