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