PreviewImagePagerAdapter.java 14 KB

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