Merge branch 'develop' into accounts_view
[pub/Android/ownCloud.git] / src / com / owncloud / android / ui / preview / PreviewImagePagerAdapter.java
1 /* ownCloud Android client application
2 * Copyright (C) 2012-2013 ownCloud Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17 package com.owncloud.android.ui.preview;
18
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.Iterator;
22 import java.util.Map;
23 import java.util.Set;
24 import java.util.Vector;
25
26 import android.accounts.Account;
27 import android.support.v4.app.Fragment;
28 import android.support.v4.app.FragmentManager;
29 import android.support.v4.app.FragmentStatePagerAdapter;
30 import android.view.ViewGroup;
31
32 import com.owncloud.android.datamodel.FileDataStorageManager;
33 import com.owncloud.android.datamodel.OCFile;
34 import com.owncloud.android.ui.fragment.FileFragment;
35
36 /**
37 * Adapter class that provides Fragment instances
38 *
39 * @author David A. Velasco
40 */
41 //public class PreviewImagePagerAdapter extends PagerAdapter {
42 public class PreviewImagePagerAdapter extends FragmentStatePagerAdapter {
43
44 private Vector<OCFile> mImageFiles;
45 private Account mAccount;
46 private Set<Object> mObsoleteFragments;
47 private Set<Integer> mObsoletePositions;
48 private Set<Integer> mDownloadErrors;
49 private FileDataStorageManager mStorageManager;
50
51 private Map<Integer, FileFragment> mCachedFragments;
52
53 /**
54 * Constructor.
55 *
56 * @param fragmentManager {@link FragmentManager} instance that will handle the {@link Fragment}s provided by the adapter.
57 * @param parentFolder Folder where images will be searched for.
58 * @param storageManager Bridge to database.
59 */
60 public PreviewImagePagerAdapter(FragmentManager fragmentManager, OCFile parentFolder, Account account, FileDataStorageManager storageManager) {
61 super(fragmentManager);
62
63 if (fragmentManager == null) {
64 throw new IllegalArgumentException("NULL FragmentManager instance");
65 }
66 if (parentFolder == null) {
67 throw new IllegalArgumentException("NULL parent folder");
68 }
69 if (storageManager == null) {
70 throw new IllegalArgumentException("NULL storage manager");
71 }
72
73 mAccount = account;
74 mStorageManager = storageManager;
75 mImageFiles = mStorageManager.getFolderImages(parentFolder);
76 mObsoleteFragments = new HashSet<Object>();
77 mObsoletePositions = new HashSet<Integer>();
78 mDownloadErrors = new HashSet<Integer>();
79 //mFragmentManager = fragmentManager;
80 mCachedFragments = new HashMap<Integer, FileFragment>();
81 }
82
83
84 /**
85 * Returns the image files handled by the adapter.
86 *
87 * @return A vector with the image files handled by the adapter.
88 */
89 protected OCFile getFileAt(int position) {
90 return mImageFiles.get(position);
91 }
92
93
94 public Fragment getItem(int i) {
95 OCFile file = mImageFiles.get(i);
96 Fragment fragment = null;
97 if (file.isDown()) {
98 fragment = new PreviewImageFragment(file, mAccount, mObsoletePositions.contains(Integer.valueOf(i)));
99
100 } else if (mDownloadErrors.contains(Integer.valueOf(i))) {
101 fragment = new FileDownloadFragment(file, mAccount, true);
102 ((FileDownloadFragment)fragment).setError(true);
103 mDownloadErrors.remove(Integer.valueOf(i));
104
105 } else {
106 fragment = new FileDownloadFragment(file, mAccount, mObsoletePositions.contains(Integer.valueOf(i)));
107 }
108 mObsoletePositions.remove(Integer.valueOf(i));
109 return fragment;
110 }
111
112 public int getFilePosition(OCFile file) {
113 return mImageFiles.indexOf(file);
114 }
115
116 @Override
117 public int getCount() {
118 return mImageFiles.size();
119 }
120
121 @Override
122 public CharSequence getPageTitle(int position) {
123 return mImageFiles.get(position).getFileName();
124 }
125
126
127 public void updateFile(int position, OCFile file) {
128 FileFragment fragmentToUpdate = mCachedFragments.get(Integer.valueOf(position));
129 if (fragmentToUpdate != null) {
130 mObsoleteFragments.add(fragmentToUpdate);
131 }
132 mObsoletePositions.add(Integer.valueOf(position));
133 mImageFiles.set(position, file);
134 }
135
136
137 public void updateWithDownloadError(int position) {
138 FileFragment fragmentToUpdate = mCachedFragments.get(Integer.valueOf(position));
139 if (fragmentToUpdate != null) {
140 mObsoleteFragments.add(fragmentToUpdate);
141 }
142 mDownloadErrors.add(Integer.valueOf(position));
143 }
144
145 public void clearErrorAt(int position) {
146 FileFragment fragmentToUpdate = mCachedFragments.get(Integer.valueOf(position));
147 if (fragmentToUpdate != null) {
148 mObsoleteFragments.add(fragmentToUpdate);
149 }
150 mDownloadErrors.remove(Integer.valueOf(position));
151 }
152
153
154 @Override
155 public int getItemPosition(Object object) {
156 if (mObsoleteFragments.contains(object)) {
157 mObsoleteFragments.remove(object);
158 return POSITION_NONE;
159 }
160 return super.getItemPosition(object);
161 }
162
163
164 @Override
165 public Object instantiateItem(ViewGroup container, int position) {
166 Object fragment = super.instantiateItem(container, position);
167 mCachedFragments.put(Integer.valueOf(position), (FileFragment)fragment);
168 return fragment;
169 }
170
171 @Override
172 public void destroyItem(ViewGroup container, int position, Object object) {
173 mCachedFragments.remove(Integer.valueOf(position));
174 super.destroyItem(container, position, object);
175 }
176
177
178 public boolean pendingErrorAt(int position) {
179 return mDownloadErrors.contains(Integer.valueOf(position));
180 }
181
182 /**
183 * Reset the image zoom to default value for each CachedFragments
184 */
185 public void resetZoom() {
186 Iterator<FileFragment> entries = mCachedFragments.values().iterator();
187 while (entries.hasNext()) {
188 FileFragment fileFragment = (FileFragment) entries.next();
189 if (fileFragment instanceof PreviewImageFragment) {
190 ((PreviewImageFragment) fileFragment).getImageView().resetZoom();
191 }
192 }
193 }
194
195 /* -*
196 * Called when a change in the shown pages is going to start being made.
197 *
198 * @param container The containing View which is displaying this adapter's page views.
199 *- /
200 @Override
201 public void startUpdate(ViewGroup container) {
202 Log.e(TAG, "** startUpdate");
203 }
204
205 @Override
206 public Object instantiateItem(ViewGroup container, int position) {
207 Log.e(TAG, "** instantiateItem " + position);
208
209 if (mFragments.size() > position) {
210 Fragment fragment = mFragments.get(position);
211 if (fragment != null) {
212 Log.e(TAG, "** \t returning cached item");
213 return fragment;
214 }
215 }
216
217 if (mCurTransaction == null) {
218 mCurTransaction = mFragmentManager.beginTransaction();
219 }
220
221 Fragment fragment = getItem(position);
222 if (mSavedState.size() > position) {
223 Fragment.SavedState savedState = mSavedState.get(position);
224 if (savedState != null) {
225 // TODO WATCH OUT:
226 // * The Fragment must currently be attached to the FragmentManager.
227 // * A new Fragment created using this saved state must be the same class type as the Fragment it was created from.
228 // * The saved state can not contain dependencies on other fragments -- that is it can't use putFragment(Bundle, String, Fragment)
229 // to store a fragment reference
230 fragment.setInitialSavedState(savedState);
231 }
232 }
233 while (mFragments.size() <= position) {
234 mFragments.add(null);
235 }
236 fragment.setMenuVisibility(false);
237 mFragments.set(position, fragment);
238 //Log.e(TAG, "** \t adding fragment at position " + position + ", containerId " + container.getId());
239 mCurTransaction.add(container.getId(), fragment);
240
241 return fragment;
242 }
243
244 @Override
245 public void destroyItem(ViewGroup container, int position, Object object) {
246 Log.e(TAG, "** destroyItem " + position);
247 Fragment fragment = (Fragment)object;
248
249 if (mCurTransaction == null) {
250 mCurTransaction = mFragmentManager.beginTransaction();
251 }
252 Log.e(TAG, "** \t removing fragment at position " + position);
253 while (mSavedState.size() <= position) {
254 mSavedState.add(null);
255 }
256 mSavedState.set(position, mFragmentManager.saveFragmentInstanceState(fragment));
257 mFragments.set(position, null);
258
259 mCurTransaction.remove(fragment);
260 }
261
262 @Override
263 public void setPrimaryItem(ViewGroup container, int position, Object object) {
264 Fragment fragment = (Fragment)object;
265 if (fragment != mCurrentPrimaryItem) {
266 if (mCurrentPrimaryItem != null) {
267 mCurrentPrimaryItem.setMenuVisibility(false);
268 }
269 if (fragment != null) {
270 fragment.setMenuVisibility(true);
271 }
272 mCurrentPrimaryItem = fragment;
273 }
274 }
275
276 @Override
277 public void finishUpdate(ViewGroup container) {
278 Log.e(TAG, "** finishUpdate (start)");
279 if (mCurTransaction != null) {
280 mCurTransaction.commitAllowingStateLoss();
281 mCurTransaction = null;
282 mFragmentManager.executePendingTransactions();
283 }
284 Log.e(TAG, "** finishUpdate (end)");
285 }
286
287 @Override
288 public boolean isViewFromObject(View view, Object object) {
289 return ((Fragment)object).getView() == view;
290 }
291
292 @Override
293 public Parcelable saveState() {
294 Bundle state = null;
295 if (mSavedState.size() > 0) {
296 state = new Bundle();
297 Fragment.SavedState[] savedStates = new Fragment.SavedState[mSavedState.size()];
298 mSavedState.toArray(savedStates);
299 state.putParcelableArray("states", savedStates);
300 }
301 for (int i=0; i<mFragments.size(); i++) {
302 Fragment fragment = mFragments.get(i);
303 if (fragment != null) {
304 if (state == null) {
305 state = new Bundle();
306 }
307 String key = "f" + i;
308 mFragmentManager.putFragment(state, key, fragment);
309 }
310 }
311 return state;
312 }
313
314 @Override
315 public void restoreState(Parcelable state, ClassLoader loader) {
316 if (state != null) {
317 Bundle bundle = (Bundle)state;
318 bundle.setClassLoader(loader);
319 Parcelable[] states = bundle.getParcelableArray("states");
320 mSavedState.clear();
321 mFragments.clear();
322 if (states != null) {
323 for (int i=0; i<states.length; i++) {
324 mSavedState.add((Fragment.SavedState)states[i]);
325 }
326 }
327 Iterable<String> keys = bundle.keySet();
328 for (String key: keys) {
329 if (key.startsWith("f")) {
330 int index = Integer.parseInt(key.substring(1));
331 Fragment f = mFragmentManager.getFragment(bundle, key);
332 if (f != null) {
333 while (mFragments.size() <= index) {
334 mFragments.add(null);
335 }
336 f.setMenuVisibility(false);
337 mFragments.set(index, f);
338 } else {
339 Log.w(TAG, "Bad fragment at key " + key);
340 }
341 }
342 }
343 }
344 }
345 */
346 }