1 /* ownCloud Android client application 
   2  *   Copyright (C) 2012-2013  ownCloud Inc. 
   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. 
   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. 
  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/>. 
  17 package com
.owncloud
.android
.ui
.preview
; 
  19 import java
.util
.HashMap
; 
  20 import java
.util
.HashSet
; 
  21 import java
.util
.Iterator
; 
  24 import java
.util
.Vector
; 
  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
; 
  32 import com
.owncloud
.android
.datamodel
.FileDataStorageManager
; 
  33 import com
.owncloud
.android
.datamodel
.OCFile
; 
  34 import com
.owncloud
.android
.ui
.fragment
.FileFragment
; 
  37  * Adapter class that provides Fragment instances   
  39  * @author David A. Velasco 
  41 //public class PreviewImagePagerAdapter extends PagerAdapter { 
  42 public class PreviewImagePagerAdapter 
extends FragmentStatePagerAdapter 
{ 
  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
; 
  51     private Map
<Integer
, FileFragment
> mCachedFragments
; 
  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. 
  60     public PreviewImagePagerAdapter(FragmentManager fragmentManager
, OCFile parentFolder
, Account account
, FileDataStorageManager storageManager
) { 
  61         super(fragmentManager
); 
  63         if (fragmentManager 
== null
) { 
  64             throw new IllegalArgumentException("NULL FragmentManager instance"); 
  66         if (parentFolder 
== null
) { 
  67             throw new IllegalArgumentException("NULL parent folder"); 
  69         if (storageManager 
== null
) { 
  70             throw new IllegalArgumentException("NULL storage manager"); 
  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
>(); 
  85      * Returns the image files handled by the adapter. 
  87      * @return  A vector with the image files handled by the adapter. 
  89     protected OCFile 
getFileAt(int position
) { 
  90         return mImageFiles
.get(position
); 
  94     public Fragment 
getItem(int i
) { 
  95         OCFile file 
= mImageFiles
.get(i
); 
  96         Fragment fragment 
= null
; 
  98             fragment 
= new PreviewImageFragment(file
, mAccount
, mObsoletePositions
.contains(Integer
.valueOf(i
))); 
 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
)); 
 106             fragment 
= new FileDownloadFragment(file
, mAccount
, mObsoletePositions
.contains(Integer
.valueOf(i
))); 
 108         mObsoletePositions
.remove(Integer
.valueOf(i
)); 
 112     public int getFilePosition(OCFile file
) { 
 113         return mImageFiles
.indexOf(file
); 
 117     public int getCount() { 
 118         return mImageFiles
.size(); 
 122     public CharSequence 
getPageTitle(int position
) { 
 123         return mImageFiles
.get(position
).getFileName(); 
 127     public void updateFile(int position
, OCFile file
) { 
 128         FileFragment fragmentToUpdate 
= mCachedFragments
.get(Integer
.valueOf(position
)); 
 129         if (fragmentToUpdate 
!= null
) { 
 130             mObsoleteFragments
.add(fragmentToUpdate
); 
 132         mObsoletePositions
.add(Integer
.valueOf(position
)); 
 133         mImageFiles
.set(position
, file
); 
 137     public void updateWithDownloadError(int position
) { 
 138         FileFragment fragmentToUpdate 
= mCachedFragments
.get(Integer
.valueOf(position
)); 
 139         if (fragmentToUpdate 
!= null
) { 
 140             mObsoleteFragments
.add(fragmentToUpdate
); 
 142         mDownloadErrors
.add(Integer
.valueOf(position
)); 
 145     public void clearErrorAt(int position
) { 
 146         FileFragment fragmentToUpdate 
= mCachedFragments
.get(Integer
.valueOf(position
)); 
 147         if (fragmentToUpdate 
!= null
) { 
 148             mObsoleteFragments
.add(fragmentToUpdate
); 
 150         mDownloadErrors
.remove(Integer
.valueOf(position
)); 
 155     public int getItemPosition(Object object
) { 
 156         if (mObsoleteFragments
.contains(object
)) { 
 157             mObsoleteFragments
.remove(object
); 
 158             return POSITION_NONE
; 
 160         return super.getItemPosition(object
); 
 165     public Object 
instantiateItem(ViewGroup container
, int position
) { 
 166         Object fragment 
= super.instantiateItem(container
, position
); 
 167         mCachedFragments
.put(Integer
.valueOf(position
), (FileFragment
)fragment
); 
 172     public void destroyItem(ViewGroup container
, int position
, Object object
) { 
 173        mCachedFragments
.remove(Integer
.valueOf(position
)); 
 174        super.destroyItem(container
, position
, object
); 
 178     public boolean pendingErrorAt(int position
) { 
 179         return mDownloadErrors
.contains(Integer
.valueOf(position
)); 
 183      * Reset the image zoom to default value for each CachedFragments 
 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(); 
 196      * Called when a change in the shown pages is going to start being made. 
 198      * @param   container   The containing View which is displaying this adapter's page views. 
 201     public void startUpdate(ViewGroup container) { 
 202         Log.e(TAG, "** startUpdate"); 
 206     public Object instantiateItem(ViewGroup container, int position) { 
 207         Log.e(TAG, "** instantiateItem " + position); 
 209         if (mFragments.size() > position) { 
 210             Fragment fragment = mFragments.get(position); 
 211             if (fragment != null) { 
 212                 Log.e(TAG, "** \t returning cached item"); 
 217         if (mCurTransaction == null) { 
 218             mCurTransaction = mFragmentManager.beginTransaction(); 
 221         Fragment fragment = getItem(position); 
 222         if (mSavedState.size() > position) { 
 223             Fragment.SavedState savedState = mSavedState.get(position); 
 224             if (savedState != null) { 
 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); 
 233         while (mFragments.size() <= position) { 
 234             mFragments.add(null); 
 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); 
 245     public void destroyItem(ViewGroup container, int position, Object object) { 
 246         Log.e(TAG, "** destroyItem " + position); 
 247         Fragment fragment = (Fragment)object; 
 249         if (mCurTransaction == null) { 
 250             mCurTransaction = mFragmentManager.beginTransaction(); 
 252         Log.e(TAG, "** \t removing fragment at position " + position); 
 253         while (mSavedState.size() <= position) { 
 254             mSavedState.add(null); 
 256         mSavedState.set(position, mFragmentManager.saveFragmentInstanceState(fragment)); 
 257         mFragments.set(position, null); 
 259         mCurTransaction.remove(fragment); 
 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); 
 269             if (fragment != null) { 
 270                 fragment.setMenuVisibility(true); 
 272             mCurrentPrimaryItem = fragment; 
 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(); 
 284         Log.e(TAG, "** finishUpdate (end)"); 
 288     public boolean isViewFromObject(View view, Object object) { 
 289         return ((Fragment)object).getView() == view; 
 293     public Parcelable saveState() { 
 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); 
 301         for (int i=0; i<mFragments.size(); i++) { 
 302             Fragment fragment = mFragments.get(i); 
 303             if (fragment != null) { 
 305                     state = new Bundle(); 
 307                 String key = "f" + i; 
 308                 mFragmentManager.putFragment(state, key, fragment); 
 315     public void restoreState(Parcelable state, ClassLoader loader) { 
 317             Bundle bundle = (Bundle)state; 
 318             bundle.setClassLoader(loader); 
 319             Parcelable[] states = bundle.getParcelableArray("states"); 
 322             if (states != null) { 
 323                 for (int i=0; i<states.length; i++) { 
 324                     mSavedState.add((Fragment.SavedState)states[i]); 
 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); 
 333                         while (mFragments.size() <= index) { 
 334                             mFragments.add(null); 
 336                         f.setMenuVisibility(false); 
 337                         mFragments.set(index, f); 
 339                         Log.w(TAG, "Bad fragment at key " + key);