Merge pull request #294 from owncloud/setup_buttons
[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.Map;
22 import java.util.Set;
23 import java.util.Vector;
24
25 import com.owncloud.android.datamodel.OCFile;
26 import com.owncloud.android.ui.fragment.FileFragment;
27
28 import android.accounts.Account;
29 import android.support.v4.app.Fragment;
30 import android.support.v4.app.FragmentManager;
31 import android.support.v4.app.FragmentStatePagerAdapter;
32 import android.view.ViewGroup;
33
34 import com.owncloud.android.datamodel.FileDataStorageManager;
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 * Called when a change in the shown pages is going to start being made.
184 *
185 * @param container The containing View which is displaying this adapter's page views.
186 *- /
187 @Override
188 public void startUpdate(ViewGroup container) {
189 Log.e(TAG, "** startUpdate");
190 }
191
192 @Override
193 public Object instantiateItem(ViewGroup container, int position) {
194 Log.e(TAG, "** instantiateItem " + position);
195
196 if (mFragments.size() > position) {
197 Fragment fragment = mFragments.get(position);
198 if (fragment != null) {
199 Log.e(TAG, "** \t returning cached item");
200 return fragment;
201 }
202 }
203
204 if (mCurTransaction == null) {
205 mCurTransaction = mFragmentManager.beginTransaction();
206 }
207
208 Fragment fragment = getItem(position);
209 if (mSavedState.size() > position) {
210 Fragment.SavedState savedState = mSavedState.get(position);
211 if (savedState != null) {
212 // TODO WATCH OUT:
213 // * The Fragment must currently be attached to the FragmentManager.
214 // * A new Fragment created using this saved state must be the same class type as the Fragment it was created from.
215 // * The saved state can not contain dependencies on other fragments -- that is it can't use putFragment(Bundle, String, Fragment)
216 // to store a fragment reference
217 fragment.setInitialSavedState(savedState);
218 }
219 }
220 while (mFragments.size() <= position) {
221 mFragments.add(null);
222 }
223 fragment.setMenuVisibility(false);
224 mFragments.set(position, fragment);
225 //Log.e(TAG, "** \t adding fragment at position " + position + ", containerId " + container.getId());
226 mCurTransaction.add(container.getId(), fragment);
227
228 return fragment;
229 }
230
231 @Override
232 public void destroyItem(ViewGroup container, int position, Object object) {
233 Log.e(TAG, "** destroyItem " + position);
234 Fragment fragment = (Fragment)object;
235
236 if (mCurTransaction == null) {
237 mCurTransaction = mFragmentManager.beginTransaction();
238 }
239 Log.e(TAG, "** \t removing fragment at position " + position);
240 while (mSavedState.size() <= position) {
241 mSavedState.add(null);
242 }
243 mSavedState.set(position, mFragmentManager.saveFragmentInstanceState(fragment));
244 mFragments.set(position, null);
245
246 mCurTransaction.remove(fragment);
247 }
248
249 @Override
250 public void setPrimaryItem(ViewGroup container, int position, Object object) {
251 Fragment fragment = (Fragment)object;
252 if (fragment != mCurrentPrimaryItem) {
253 if (mCurrentPrimaryItem != null) {
254 mCurrentPrimaryItem.setMenuVisibility(false);
255 }
256 if (fragment != null) {
257 fragment.setMenuVisibility(true);
258 }
259 mCurrentPrimaryItem = fragment;
260 }
261 }
262
263 @Override
264 public void finishUpdate(ViewGroup container) {
265 Log.e(TAG, "** finishUpdate (start)");
266 if (mCurTransaction != null) {
267 mCurTransaction.commitAllowingStateLoss();
268 mCurTransaction = null;
269 mFragmentManager.executePendingTransactions();
270 }
271 Log.e(TAG, "** finishUpdate (end)");
272 }
273
274 @Override
275 public boolean isViewFromObject(View view, Object object) {
276 return ((Fragment)object).getView() == view;
277 }
278
279 @Override
280 public Parcelable saveState() {
281 Bundle state = null;
282 if (mSavedState.size() > 0) {
283 state = new Bundle();
284 Fragment.SavedState[] savedStates = new Fragment.SavedState[mSavedState.size()];
285 mSavedState.toArray(savedStates);
286 state.putParcelableArray("states", savedStates);
287 }
288 for (int i=0; i<mFragments.size(); i++) {
289 Fragment fragment = mFragments.get(i);
290 if (fragment != null) {
291 if (state == null) {
292 state = new Bundle();
293 }
294 String key = "f" + i;
295 mFragmentManager.putFragment(state, key, fragment);
296 }
297 }
298 return state;
299 }
300
301 @Override
302 public void restoreState(Parcelable state, ClassLoader loader) {
303 if (state != null) {
304 Bundle bundle = (Bundle)state;
305 bundle.setClassLoader(loader);
306 Parcelable[] states = bundle.getParcelableArray("states");
307 mSavedState.clear();
308 mFragments.clear();
309 if (states != null) {
310 for (int i=0; i<states.length; i++) {
311 mSavedState.add((Fragment.SavedState)states[i]);
312 }
313 }
314 Iterable<String> keys = bundle.keySet();
315 for (String key: keys) {
316 if (key.startsWith("f")) {
317 int index = Integer.parseInt(key.substring(1));
318 Fragment f = mFragmentManager.getFragment(bundle, key);
319 if (f != null) {
320 while (mFragments.size() <= index) {
321 mFragments.add(null);
322 }
323 f.setMenuVisibility(false);
324 mFragments.set(index, f);
325 } else {
326 Log.w(TAG, "Bad fragment at key " + key);
327 }
328 }
329 }
330 }
331 }
332 */
333 }