1525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov/* 2525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * Copyright (C) 2014 The Android Open Source Project 3525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * 4525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * Licensed under the Apache License, Version 2.0 (the "License"); 5525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * you may not use this file except in compliance with the License. 6525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * You may obtain a copy of the License at 7525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * 8525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * http://www.apache.org/licenses/LICENSE-2.0 9525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * 10525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * Unless required by applicable law or agreed to in writing, software 11525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * distributed under the License is distributed on an "AS IS" BASIS, 12525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * See the License for the specific language governing permissions and 14525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * limitations under the License. 15525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov */ 16525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 17525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovpackage com.android.printspooler.ui; 18525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 19525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport android.content.Context; 206552bf3da60159607d9266eb295ee3c448f6c3deSvetoslavimport android.graphics.Bitmap; 216552bf3da60159607d9266eb295ee3c448f6c3deSvetoslavimport android.graphics.Canvas; 226552bf3da60159607d9266eb295ee3c448f6c3deSvetoslavimport android.graphics.drawable.BitmapDrawable; 23525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport android.os.ParcelFileDescriptor; 24525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport android.print.PageRange; 25525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport android.print.PrintAttributes.MediaSize; 26525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport android.print.PrintAttributes.Margins; 27525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport android.print.PrintDocumentInfo; 28525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport android.support.v7.widget.RecyclerView.Adapter; 29525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport android.support.v7.widget.RecyclerView.ViewHolder; 30525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport android.util.Log; 31525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport android.util.SparseArray; 32525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport android.view.LayoutInflater; 33525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport android.view.View; 34525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport android.view.View.OnClickListener; 35525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport android.view.ViewGroup; 36525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport android.view.ViewGroup.LayoutParams; 376552bf3da60159607d9266eb295ee3c448f6c3deSvetoslavimport android.view.View.MeasureSpec; 38525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport android.widget.TextView; 39525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport com.android.printspooler.R; 40fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganovimport com.android.printspooler.model.OpenDocumentCallback; 41525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport com.android.printspooler.model.PageContentRepository; 42525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport com.android.printspooler.model.PageContentRepository.PageContentProvider; 43525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport com.android.printspooler.util.PageRangeUtils; 44525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport com.android.printspooler.widget.PageContentView; 45e652b02d45bbda11c9cb8f663fa7f25903b90225Svetoslavimport com.android.printspooler.widget.PreviewPageFrame; 46525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport dalvik.system.CloseGuard; 47525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 48525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport java.util.ArrayList; 49525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport java.util.Arrays; 50525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganovimport java.util.List; 51525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 52525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov/** 53525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * This class represents the adapter for the pages in the print preview list. 54525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov */ 55fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganovpublic final class PageAdapter extends Adapter { 56525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private static final String LOG_TAG = "PageAdapter"; 57525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 58525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private static final int MAX_PREVIEW_PAGES_BATCH = 50; 59525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 60f3f963b0bebea91b17f7e60d9b826c458bfde38cSvetoslav private static final boolean DEBUG = false; 61525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 62525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private static final PageRange[] ALL_PAGES_ARRAY = new PageRange[] { 63525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageRange.ALL_PAGES 64525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov }; 65525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 66525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private static final int INVALID_PAGE_INDEX = -1; 67525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 68525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private static final int STATE_CLOSED = 0; 69525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private static final int STATE_OPENED = 1; 70525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private static final int STATE_DESTROYED = 2; 71525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 72525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private final CloseGuard mCloseGuard = CloseGuard.get(); 73525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 74525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private final SparseArray<Void> mBoundPagesInAdapter = new SparseArray<>(); 75525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private final SparseArray<Void> mConfirmedPagesInDocument = new SparseArray<>(); 76525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 77525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private final PageClickListener mPageClickListener = new PageClickListener(); 78525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 79525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private final Context mContext; 8015cbc8a03250eafdf947cd8ad4e77f34444d5ba4Svetoslav private final LayoutInflater mLayoutInflater; 81525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 825ef522bc19cc9fc1af48cccd2865744228c5ec02Svetoslav private final ContentCallbacks mCallbacks; 83525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private final PageContentRepository mPageContentRepository; 84525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private final PreviewArea mPreviewArea; 85525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 86525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov // Which document pages to be written. 87525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private PageRange[] mRequestedPages; 88525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov // Pages written in the current file. 89525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private PageRange[] mWrittenPages; 90525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov // Pages the user selected in the UI. 91525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private PageRange[] mSelectedPages; 92525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 936552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav private BitmapDrawable mEmptyState; 946552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav 9515cbc8a03250eafdf947cd8ad4e77f34444d5ba4Svetoslav private int mDocumentPageCount = PrintDocumentInfo.PAGE_COUNT_UNKNOWN; 9615cbc8a03250eafdf947cd8ad4e77f34444d5ba4Svetoslav private int mSelectedPageCount; 97525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 98525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private int mPreviewPageMargin; 9938781bd2c2c61385651314098b4a615cb8e8efa1Svet Ganov private int mPreviewPageMinWidth; 100525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private int mPreviewListPadding; 101525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private int mFooterHeight; 102525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 103525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private int mColumnCount; 104525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 105525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private MediaSize mMediaSize; 106525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private Margins mMinMargins; 107525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 108525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private int mState; 109525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 110525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private int mPageContentWidth; 111525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private int mPageContentHeight; 112525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 1135ef522bc19cc9fc1af48cccd2865744228c5ec02Svetoslav public interface ContentCallbacks { 1145ef522bc19cc9fc1af48cccd2865744228c5ec02Svetoslav public void onRequestContentUpdate(); 1155ef522bc19cc9fc1af48cccd2865744228c5ec02Svetoslav public void onMalformedPdfFile(); 116fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov public void onSecurePdfFile(); 117525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 118525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 119525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public interface PreviewArea { 120525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public int getWidth(); 121525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public int getHeight(); 122525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public void setColumnCount(int columnCount); 123525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public void setPadding(int left, int top, int right, int bottom); 124525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 125525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 1265ef522bc19cc9fc1af48cccd2865744228c5ec02Svetoslav public PageAdapter(Context context, ContentCallbacks callbacks, PreviewArea previewArea) { 127525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mContext = context; 1285ef522bc19cc9fc1af48cccd2865744228c5ec02Svetoslav mCallbacks = callbacks; 129525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mLayoutInflater = (LayoutInflater) context.getSystemService( 130525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov Context.LAYOUT_INFLATER_SERVICE); 131fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov mPageContentRepository = new PageContentRepository(context); 132525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 133525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mPreviewPageMargin = mContext.getResources().getDimensionPixelSize( 134525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov R.dimen.preview_page_margin); 135525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 13638781bd2c2c61385651314098b4a615cb8e8efa1Svet Ganov mPreviewPageMinWidth = mContext.getResources().getDimensionPixelSize( 13738781bd2c2c61385651314098b4a615cb8e8efa1Svet Ganov R.dimen.preview_page_min_width); 13838781bd2c2c61385651314098b4a615cb8e8efa1Svet Ganov 139525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mPreviewListPadding = mContext.getResources().getDimensionPixelSize( 140525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov R.dimen.preview_list_padding); 141525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 142525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mColumnCount = mContext.getResources().getInteger( 143525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov R.integer.preview_page_per_row_count); 144525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 14538781bd2c2c61385651314098b4a615cb8e8efa1Svet Ganov mFooterHeight = mContext.getResources().getDimensionPixelSize( 14638781bd2c2c61385651314098b4a615cb8e8efa1Svet Ganov R.dimen.preview_page_footer_height); 147525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 148525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mPreviewArea = previewArea; 149525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 150525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mCloseGuard.open("destroy"); 151525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 152525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov setHasStableIds(true); 153525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 154525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mState = STATE_CLOSED; 155525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (DEBUG) { 156525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov Log.i(LOG_TAG, "STATE_CLOSED"); 157525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 158525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 159525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 160525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public void onOrientationChanged() { 161525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mColumnCount = mContext.getResources().getInteger( 162525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov R.integer.preview_page_per_row_count); 163139ba7fb0ed976bdbc7c283e3f7fe9980eed22a6Svetoslav notifyDataSetChanged(); 164525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 165525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 166525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public boolean isOpened() { 167525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov return mState == STATE_OPENED; 168525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 169525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 170525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public int getFilePageCount() { 171525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov return mPageContentRepository.getFilePageCount(); 172525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 173525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 174f3f963b0bebea91b17f7e60d9b826c458bfde38cSvetoslav public void open(ParcelFileDescriptor source, final Runnable callback) { 175525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov throwIfNotClosed(); 176525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mState = STATE_OPENED; 177525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (DEBUG) { 178525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov Log.i(LOG_TAG, "STATE_OPENED"); 179525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 180fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov mPageContentRepository.open(source, new OpenDocumentCallback() { 181f3f963b0bebea91b17f7e60d9b826c458bfde38cSvetoslav @Override 182fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov public void onSuccess() { 183f3f963b0bebea91b17f7e60d9b826c458bfde38cSvetoslav notifyDataSetChanged(); 184f3f963b0bebea91b17f7e60d9b826c458bfde38cSvetoslav callback.run(); 185f3f963b0bebea91b17f7e60d9b826c458bfde38cSvetoslav } 186fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov 187fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov @Override 188fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov public void onFailure(int error) { 189fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov switch (error) { 190fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov case OpenDocumentCallback.ERROR_MALFORMED_PDF_FILE: { 191fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov mCallbacks.onMalformedPdfFile(); 192fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov } break; 193fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov 194fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov case OpenDocumentCallback.ERROR_SECURE_PDF_FILE: { 195fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov mCallbacks.onSecurePdfFile(); 196fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov } break; 197fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov } 198fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov } 199f3f963b0bebea91b17f7e60d9b826c458bfde38cSvetoslav }); 200525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 201525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 202525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public void update(PageRange[] writtenPages, PageRange[] selectedPages, 203525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov int documentPageCount, MediaSize mediaSize, Margins minMargins) { 204525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov boolean documentChanged = false; 205525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov boolean updatePreviewAreaAndPageSize = false; 206525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 207525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov // If the app does not tell how many pages are in the document we cannot 208525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov // optimize and ask for all pages whose count we get from the renderer. 209525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (documentPageCount == PrintDocumentInfo.PAGE_COUNT_UNKNOWN) { 210525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (writtenPages == null) { 211525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov // If we already requested all pages, just wait. 212525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (!Arrays.equals(ALL_PAGES_ARRAY, mRequestedPages)) { 213525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mRequestedPages = ALL_PAGES_ARRAY; 2145ef522bc19cc9fc1af48cccd2865744228c5ec02Svetoslav mCallbacks.onRequestContentUpdate(); 215525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 216525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov return; 217525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } else { 218525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov documentPageCount = mPageContentRepository.getFilePageCount(); 219525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (documentPageCount <= 0) { 220525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov return; 221525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 222525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 223525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 224525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 225525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (!Arrays.equals(mSelectedPages, selectedPages)) { 226525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mSelectedPages = selectedPages; 227525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mSelectedPageCount = PageRangeUtils.getNormalizedPageCount( 228525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mSelectedPages, documentPageCount); 229525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov setConfirmedPages(mSelectedPages, documentPageCount); 230525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov updatePreviewAreaAndPageSize = true; 231525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov documentChanged = true; 232525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 233525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 234525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (mDocumentPageCount != documentPageCount) { 235525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mDocumentPageCount = documentPageCount; 236525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov documentChanged = true; 237525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 238525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 239525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (mMediaSize == null || !mMediaSize.equals(mediaSize)) { 240525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mMediaSize = mediaSize; 241525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov updatePreviewAreaAndPageSize = true; 242525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov documentChanged = true; 243525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 244525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 245525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (mMinMargins == null || !mMinMargins.equals(minMargins)) { 246525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mMinMargins = minMargins; 247525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov updatePreviewAreaAndPageSize = true; 248525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov documentChanged = true; 249525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 250525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 251525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov // If *all pages* is selected we need to convert that to absolute 252525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov // range as we will be checking if some pages are written or not. 253525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (writtenPages != null) { 254525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov // If we get all pages, this means all pages that we requested. 255525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (PageRangeUtils.isAllPages(writtenPages)) { 256525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov writtenPages = mRequestedPages; 257525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 258525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (!Arrays.equals(mWrittenPages, writtenPages)) { 259525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov // TODO: Do a surgical invalidation of only written pages changed. 260525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mWrittenPages = writtenPages; 261525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov documentChanged = true; 262525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 263525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 264525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 265525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (updatePreviewAreaAndPageSize) { 2666552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav updatePreviewAreaPageSizeAndEmptyState(); 267525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 268525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 269525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (documentChanged) { 270525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov notifyDataSetChanged(); 271525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 272525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 273525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 274525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public void close(Runnable callback) { 275525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov throwIfNotOpened(); 276525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mState = STATE_CLOSED; 277525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (DEBUG) { 278525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov Log.i(LOG_TAG, "STATE_CLOSED"); 279525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 280525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mPageContentRepository.close(callback); 281525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 282525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 283525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov @Override 284525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 285525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov View page = mLayoutInflater.inflate(R.layout.preview_page, parent, false); 2860d2d9637ed4f46062d508cfa7da0e9776fc444f8Svetoslav return new MyViewHolder(page); 287525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 288525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 289525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov @Override 290525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public void onBindViewHolder(ViewHolder holder, int position) { 291525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (DEBUG) { 292525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov Log.i(LOG_TAG, "Binding holder: " + holder + " with id: " + getItemId(position) 293525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov + " for position: " + position); 294525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 295525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 296525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov MyViewHolder myHolder = (MyViewHolder) holder; 297525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 298e652b02d45bbda11c9cb8f663fa7f25903b90225Svetoslav PreviewPageFrame page = (PreviewPageFrame) holder.itemView; 299c404cacd3a480776dd625fb300810ffccc5f51b0Svetoslav page.setOnClickListener(mPageClickListener); 300c404cacd3a480776dd625fb300810ffccc5f51b0Svetoslav 301525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov page.setTag(holder); 302525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 303525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov myHolder.mPageInAdapter = position; 304525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 305525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int pageInDocument = computePageIndexInDocument(position); 306525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int pageIndexInFile = computePageIndexInFile(pageInDocument); 307525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 308525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageContentView content = (PageContentView) page.findViewById(R.id.page_content); 309525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 310525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov LayoutParams params = content.getLayoutParams(); 311525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov params.width = mPageContentWidth; 312525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov params.height = mPageContentHeight; 313525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 314525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageContentProvider provider = content.getPageContentProvider(); 315525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 316525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (pageIndexInFile != INVALID_PAGE_INDEX) { 317525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (DEBUG) { 318525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov Log.i(LOG_TAG, "Binding provider:" 319525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov + " pageIndexInAdapter: " + position 320525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov + ", pageInDocument: " + pageInDocument 321525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov + ", pageIndexInFile: " + pageIndexInFile); 322525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 323525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 324525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov provider = mPageContentRepository.acquirePageContentProvider( 325525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov pageIndexInFile, content); 326525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mBoundPagesInAdapter.put(position, null); 327525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } else { 328525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov onSelectedPageNotInFile(pageInDocument); 329525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 3306552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav content.init(provider, mEmptyState, mMediaSize, mMinMargins); 331525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 332525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (mConfirmedPagesInDocument.indexOfKey(pageInDocument) >= 0) { 333e652b02d45bbda11c9cb8f663fa7f25903b90225Svetoslav page.setSelected(true, false); 334525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } else { 335e652b02d45bbda11c9cb8f663fa7f25903b90225Svetoslav page.setSelected(false, false); 336525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 337525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 338e652b02d45bbda11c9cb8f663fa7f25903b90225Svetoslav page.setContentDescription(mContext.getString(R.string.page_description_template, 339e652b02d45bbda11c9cb8f663fa7f25903b90225Svetoslav pageInDocument + 1, mDocumentPageCount)); 340e652b02d45bbda11c9cb8f663fa7f25903b90225Svetoslav 341525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov TextView pageNumberView = (TextView) page.findViewById(R.id.page_number); 342525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov String text = mContext.getString(R.string.current_page_template, 343525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov pageInDocument + 1, mDocumentPageCount); 344525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov pageNumberView.setText(text); 345525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 346525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 347525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov @Override 348525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public int getItemCount() { 349525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov return mSelectedPageCount; 350525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 351525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 352525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov @Override 353525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public long getItemId(int position) { 354525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov return computePageIndexInDocument(position); 355525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 356525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 357525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov @Override 358525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public void onViewRecycled(ViewHolder holder) { 359525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov MyViewHolder myHolder = (MyViewHolder) holder; 360525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageContentView content = (PageContentView) holder.itemView 361525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov .findViewById(R.id.page_content); 362525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov recyclePageView(content, myHolder.mPageInAdapter); 363525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov myHolder.mPageInAdapter = INVALID_PAGE_INDEX; 364525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 365525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 366525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public PageRange[] getRequestedPages() { 367525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov return mRequestedPages; 368525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 369525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 370525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public PageRange[] getSelectedPages() { 371525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageRange[] selectedPages = computeSelectedPages(); 372525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (!Arrays.equals(mSelectedPages, selectedPages)) { 373525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mSelectedPages = selectedPages; 374525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mSelectedPageCount = PageRangeUtils.getNormalizedPageCount( 375525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mSelectedPages, mDocumentPageCount); 3766552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav updatePreviewAreaPageSizeAndEmptyState(); 377525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov notifyDataSetChanged(); 378525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 379525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov return mSelectedPages; 380525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 381525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 382525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public void onPreviewAreaSizeChanged() { 383525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (mMediaSize != null) { 3846552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav updatePreviewAreaPageSizeAndEmptyState(); 385525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov notifyDataSetChanged(); 386525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 387525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 388525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 3896552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav private void updatePreviewAreaPageSizeAndEmptyState() { 390e771caf332bb3f2b668aaf249b30f37f13755553Svet Ganov if (mMediaSize == null) { 391e771caf332bb3f2b668aaf249b30f37f13755553Svet Ganov return; 392e771caf332bb3f2b668aaf249b30f37f13755553Svet Ganov } 393e771caf332bb3f2b668aaf249b30f37f13755553Svet Ganov 394525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int availableWidth = mPreviewArea.getWidth(); 395525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int availableHeight = mPreviewArea.getHeight(); 396525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 397525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov // Page aspect ratio to keep. 398525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final float pageAspectRatio = (float) mMediaSize.getWidthMils() 399525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov / mMediaSize.getHeightMils(); 400525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 401525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov // Make sure we have no empty columns. 402525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int columnCount = Math.min(mSelectedPageCount, mColumnCount); 403525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mPreviewArea.setColumnCount(columnCount); 404525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 405525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov // Compute max page width. 406525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int horizontalMargins = 2 * columnCount * mPreviewPageMargin; 407525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int horizontalPaddingAndMargins = horizontalMargins + 2 * mPreviewListPadding; 408525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int pageContentDesiredWidth = (int) ((((float) availableWidth 409525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov - horizontalPaddingAndMargins) / columnCount) + 0.5f); 410525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 411525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov // Compute max page height. 412525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int pageContentDesiredHeight = (int) (((float) pageContentDesiredWidth 413525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov / pageAspectRatio) + 0.5f); 41438781bd2c2c61385651314098b4a615cb8e8efa1Svet Ganov 4156552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav // If the page does not fit entirely in a vertical direction, 41638781bd2c2c61385651314098b4a615cb8e8efa1Svet Ganov // we shirk it but not less than the minimal page width. 41738781bd2c2c61385651314098b4a615cb8e8efa1Svet Ganov final int pageContentMinHeight = (int) (mPreviewPageMinWidth / pageAspectRatio + 0.5f); 41838781bd2c2c61385651314098b4a615cb8e8efa1Svet Ganov final int pageContentMaxHeight = Math.max(pageContentMinHeight, 41938781bd2c2c61385651314098b4a615cb8e8efa1Svet Ganov availableHeight - 2 * (mPreviewListPadding + mPreviewPageMargin) - mFooterHeight); 420525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 421525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mPageContentHeight = Math.min(pageContentDesiredHeight, pageContentMaxHeight); 422525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mPageContentWidth = (int) ((mPageContentHeight * pageAspectRatio) + 0.5f); 423525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 424525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int totalContentWidth = columnCount * mPageContentWidth + horizontalMargins; 425525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int horizontalPadding = (availableWidth - totalContentWidth) / 2; 426525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 427525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int rowCount = mSelectedPageCount / columnCount 428525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov + ((mSelectedPageCount % columnCount) > 0 ? 1 : 0); 42938781bd2c2c61385651314098b4a615cb8e8efa1Svet Ganov final int totalContentHeight = rowCount * (mPageContentHeight + mFooterHeight + 2 430525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov * mPreviewPageMargin); 43138781bd2c2c61385651314098b4a615cb8e8efa1Svet Ganov 43238781bd2c2c61385651314098b4a615cb8e8efa1Svet Ganov final int verticalPadding; 433dfa3e7c6fd4e8a28ba51b54c769b891191459012Svetoslav if (mPageContentHeight + mFooterHeight + mPreviewListPadding 434dfa3e7c6fd4e8a28ba51b54c769b891191459012Svetoslav + 2 * mPreviewPageMargin > availableHeight) { 435c404cacd3a480776dd625fb300810ffccc5f51b0Svetoslav verticalPadding = Math.max(0, 436c404cacd3a480776dd625fb300810ffccc5f51b0Svetoslav (availableHeight - mPageContentHeight - mFooterHeight) / 2 437c404cacd3a480776dd625fb300810ffccc5f51b0Svetoslav - mPreviewPageMargin); 43838781bd2c2c61385651314098b4a615cb8e8efa1Svet Ganov } else { 43938781bd2c2c61385651314098b4a615cb8e8efa1Svet Ganov verticalPadding = Math.max(mPreviewListPadding, 44038781bd2c2c61385651314098b4a615cb8e8efa1Svet Ganov (availableHeight - totalContentHeight) / 2); 44138781bd2c2c61385651314098b4a615cb8e8efa1Svet Ganov } 442525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 443525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mPreviewArea.setPadding(horizontalPadding, verticalPadding, 444525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov horizontalPadding, verticalPadding); 4456552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav 4466552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav // Now update the empty state drawable, as it depends on the page 4476552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav // size and is reused for all views for better performance. 4486552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav LayoutInflater inflater = LayoutInflater.from(mContext); 4496552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav View content = inflater.inflate(R.layout.preview_page_loading, null, false); 4506552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav content.measure(MeasureSpec.makeMeasureSpec(mPageContentWidth, MeasureSpec.EXACTLY), 4516552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav MeasureSpec.makeMeasureSpec(mPageContentHeight, MeasureSpec.EXACTLY)); 4526552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav content.layout(0, 0, content.getMeasuredWidth(), content.getMeasuredHeight()); 4536552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav 4546552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav Bitmap bitmap = Bitmap.createBitmap(mPageContentWidth, mPageContentHeight, 4556552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav Bitmap.Config.ARGB_8888); 4566552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav Canvas canvas = new Canvas(bitmap); 4576552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav content.draw(canvas); 4586552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav 4596552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav // Do not recycle the old bitmap if such as it may be set as an empty 4606552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav // state to any of the page views. Just let the GC take care of it. 4616552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav mEmptyState = new BitmapDrawable(mContext.getResources(), bitmap); 462525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 463525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 464525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private PageRange[] computeSelectedPages() { 465525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov ArrayList<PageRange> selectedPagesList = new ArrayList<>(); 466525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 467525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov int startPageIndex = INVALID_PAGE_INDEX; 468525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov int endPageIndex = INVALID_PAGE_INDEX; 469525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 470525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int pageCount = mConfirmedPagesInDocument.size(); 471525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov for (int i = 0; i < pageCount; i++) { 472525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int pageIndex = mConfirmedPagesInDocument.keyAt(i); 473525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (startPageIndex == INVALID_PAGE_INDEX) { 474525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov startPageIndex = endPageIndex = pageIndex; 475525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 476525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (endPageIndex + 1 < pageIndex) { 477525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageRange pageRange = new PageRange(startPageIndex, endPageIndex); 478525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov selectedPagesList.add(pageRange); 479525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov startPageIndex = pageIndex; 480525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 481525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov endPageIndex = pageIndex; 482525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 483525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 484525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (startPageIndex != INVALID_PAGE_INDEX 485525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov && endPageIndex != INVALID_PAGE_INDEX) { 486525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageRange pageRange = new PageRange(startPageIndex, endPageIndex); 487525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov selectedPagesList.add(pageRange); 488525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 489525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 490525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageRange[] selectedPages = new PageRange[selectedPagesList.size()]; 491525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov selectedPagesList.toArray(selectedPages); 492525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 493525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov return selectedPages; 494525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 495525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 496c80814e70aea8940d0d43cd7170baae8c0c4e8e3Svet Ganov public void destroy(Runnable callback) { 4974237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov mCloseGuard.close(); 4984237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov mState = STATE_DESTROYED; 4994237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov if (DEBUG) { 5004237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov Log.i(LOG_TAG, "STATE_DESTROYED"); 5014237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov } 502c80814e70aea8940d0d43cd7170baae8c0c4e8e3Svet Ganov mPageContentRepository.destroy(callback); 503525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 504525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 505525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov @Override 506525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov protected void finalize() throws Throwable { 507525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov try { 508525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (mState != STATE_DESTROYED) { 509525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mCloseGuard.warnIfOpen(); 510c80814e70aea8940d0d43cd7170baae8c0c4e8e3Svet Ganov destroy(null); 511525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 512525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } finally { 513525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov super.finalize(); 514525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 515525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 516525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 517525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private int computePageIndexInDocument(int indexInAdapter) { 518525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov int skippedAdapterPages = 0; 519525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int selectedPagesCount = mSelectedPages.length; 520525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov for (int i = 0; i < selectedPagesCount; i++) { 521525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageRange pageRange = PageRangeUtils.asAbsoluteRange( 522525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mSelectedPages[i], mDocumentPageCount); 523525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov skippedAdapterPages += pageRange.getSize(); 524525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (skippedAdapterPages > indexInAdapter) { 525525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int overshoot = skippedAdapterPages - indexInAdapter - 1; 526525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov return pageRange.getEnd() - overshoot; 527525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 528525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 529525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov return INVALID_PAGE_INDEX; 530525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 531525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 532525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private int computePageIndexInFile(int pageIndexInDocument) { 533525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (!PageRangeUtils.contains(mSelectedPages, pageIndexInDocument)) { 534525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov return INVALID_PAGE_INDEX; 535525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 536525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (mWrittenPages == null) { 537525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov return INVALID_PAGE_INDEX; 538525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 539525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 540525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov int indexInFile = INVALID_PAGE_INDEX; 541525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int rangeCount = mWrittenPages.length; 542525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov for (int i = 0; i < rangeCount; i++) { 543525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageRange pageRange = mWrittenPages[i]; 544525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (!pageRange.contains(pageIndexInDocument)) { 545525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov indexInFile += pageRange.getSize(); 546525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } else { 547525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov indexInFile += pageIndexInDocument - pageRange.getStart() + 1; 548525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov return indexInFile; 549525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 550525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 551525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov return INVALID_PAGE_INDEX; 552525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 553525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 554525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private void setConfirmedPages(PageRange[] pagesInDocument, int documentPageCount) { 555525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mConfirmedPagesInDocument.clear(); 556525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int rangeCount = pagesInDocument.length; 557525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov for (int i = 0; i < rangeCount; i++) { 558525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageRange pageRange = PageRangeUtils.asAbsoluteRange(pagesInDocument[i], 559525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov documentPageCount); 560525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov for (int j = pageRange.getStart(); j <= pageRange.getEnd(); j++) { 561525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mConfirmedPagesInDocument.put(j, null); 562525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 563525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 564525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 565525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 566525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private void onSelectedPageNotInFile(int pageInDocument) { 567525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageRange[] requestedPages = computeRequestedPages(pageInDocument); 568525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (!Arrays.equals(mRequestedPages, requestedPages)) { 569525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mRequestedPages = requestedPages; 570525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (DEBUG) { 571525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov Log.i(LOG_TAG, "Requesting pages: " + Arrays.toString(mRequestedPages)); 572525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 5735ef522bc19cc9fc1af48cccd2865744228c5ec02Svetoslav mCallbacks.onRequestContentUpdate(); 574525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 575525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 576525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 577525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private PageRange[] computeRequestedPages(int pageInDocument) { 578525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (mRequestedPages != null && 579525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageRangeUtils.contains(mRequestedPages, pageInDocument)) { 580525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov return mRequestedPages; 581525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 582525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 583525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov List<PageRange> pageRangesList = new ArrayList<>(); 584525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 585525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov int remainingPagesToRequest = MAX_PREVIEW_PAGES_BATCH; 586525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int selectedPagesCount = mSelectedPages.length; 587525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 588525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov // We always request the pages that are bound, i.e. shown on screen. 589525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageRange[] boundPagesInDocument = computeBoundPagesInDocument(); 590525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 591525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int boundRangeCount = boundPagesInDocument.length; 592525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov for (int i = 0; i < boundRangeCount; i++) { 593525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageRange boundRange = boundPagesInDocument[i]; 594525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov pageRangesList.add(boundRange); 595525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 596525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov remainingPagesToRequest -= PageRangeUtils.getNormalizedPageCount( 597525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov boundPagesInDocument, mDocumentPageCount); 598525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 599525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final boolean requestFromStart = mRequestedPages == null 600525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov || pageInDocument > mRequestedPages[mRequestedPages.length - 1].getEnd(); 601525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 602525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (!requestFromStart) { 603525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (DEBUG) { 604525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov Log.i(LOG_TAG, "Requesting from end"); 605525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 606525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 607525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov // Reminder that ranges are always normalized. 608525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov for (int i = selectedPagesCount - 1; i >= 0; i--) { 609525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (remainingPagesToRequest <= 0) { 610525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov break; 611525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 612525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 613525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageRange selectedRange = PageRangeUtils.asAbsoluteRange(mSelectedPages[i], 614525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mDocumentPageCount); 615525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (pageInDocument < selectedRange.getStart()) { 616525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov continue; 617525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 618525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 619525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageRange pagesInRange; 620525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov int rangeSpan; 621525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 622525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (selectedRange.contains(pageInDocument)) { 623525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov rangeSpan = pageInDocument - selectedRange.getStart() + 1; 624525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov rangeSpan = Math.min(rangeSpan, remainingPagesToRequest); 625525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int fromPage = Math.max(pageInDocument - rangeSpan - 1, 0); 626525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov rangeSpan = Math.max(rangeSpan, 0); 627525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov pagesInRange = new PageRange(fromPage, pageInDocument); 628525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } else { 629525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov rangeSpan = selectedRange.getSize(); 630525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov rangeSpan = Math.min(rangeSpan, remainingPagesToRequest); 631525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov rangeSpan = Math.max(rangeSpan, 0); 632525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int fromPage = Math.max(selectedRange.getEnd() - rangeSpan - 1, 0); 633525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int toPage = selectedRange.getEnd(); 634525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov pagesInRange = new PageRange(fromPage, toPage); 635525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 636525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 637525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov pageRangesList.add(pagesInRange); 638525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov remainingPagesToRequest -= rangeSpan; 639525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 640525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } else { 641525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (DEBUG) { 642525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov Log.i(LOG_TAG, "Requesting from start"); 643525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 644525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 645525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov // Reminder that ranges are always normalized. 646525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov for (int i = 0; i < selectedPagesCount; i++) { 647525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (remainingPagesToRequest <= 0) { 648525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov break; 649525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 650525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 651525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageRange selectedRange = PageRangeUtils.asAbsoluteRange(mSelectedPages[i], 652525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mDocumentPageCount); 653525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (pageInDocument > selectedRange.getEnd()) { 654525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov continue; 655525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 656525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 657525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageRange pagesInRange; 658525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov int rangeSpan; 659525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 660525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (selectedRange.contains(pageInDocument)) { 661525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov rangeSpan = selectedRange.getEnd() - pageInDocument + 1; 662525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov rangeSpan = Math.min(rangeSpan, remainingPagesToRequest); 663525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int toPage = Math.min(pageInDocument + rangeSpan - 1, 664525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mDocumentPageCount - 1); 665525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov pagesInRange = new PageRange(pageInDocument, toPage); 666525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } else { 667525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov rangeSpan = selectedRange.getSize(); 668525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov rangeSpan = Math.min(rangeSpan, remainingPagesToRequest); 669525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int fromPage = selectedRange.getStart(); 670525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int toPage = Math.min(selectedRange.getStart() + rangeSpan - 1, 671525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mDocumentPageCount - 1); 672525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov pagesInRange = new PageRange(fromPage, toPage); 673525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 674525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 675525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (DEBUG) { 676525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov Log.i(LOG_TAG, "computeRequestedPages() Adding range:" + pagesInRange); 677525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 678525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov pageRangesList.add(pagesInRange); 679525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov remainingPagesToRequest -= rangeSpan; 680525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 681525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 682525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 683525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageRange[] pageRanges = new PageRange[pageRangesList.size()]; 684525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov pageRangesList.toArray(pageRanges); 685525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 686525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov return PageRangeUtils.normalize(pageRanges); 687525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 688525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 689525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private PageRange[] computeBoundPagesInDocument() { 690525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov List<PageRange> pagesInDocumentList = new ArrayList<>(); 691525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 692525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov int fromPage = INVALID_PAGE_INDEX; 693525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov int toPage = INVALID_PAGE_INDEX; 694525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 695525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int boundPageCount = mBoundPagesInAdapter.size(); 696525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov for (int i = 0; i < boundPageCount; i++) { 697525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov // The container is a sparse array, so keys are sorted in ascending order. 698525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int boundPageInAdapter = mBoundPagesInAdapter.keyAt(i); 699525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int boundPageInDocument = computePageIndexInDocument(boundPageInAdapter); 700525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 701525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (fromPage == INVALID_PAGE_INDEX) { 702525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov fromPage = boundPageInDocument; 703525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 704525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 705525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (toPage == INVALID_PAGE_INDEX) { 706525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov toPage = boundPageInDocument; 707525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 708525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 709525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (boundPageInDocument > toPage + 1) { 710525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageRange pageRange = new PageRange(fromPage, toPage); 711525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov pagesInDocumentList.add(pageRange); 712525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov fromPage = toPage = boundPageInDocument; 713525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } else { 714525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov toPage = boundPageInDocument; 715525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 716525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 717525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 718525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (fromPage != INVALID_PAGE_INDEX && toPage != INVALID_PAGE_INDEX) { 719525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageRange pageRange = new PageRange(fromPage, toPage); 720525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov pagesInDocumentList.add(pageRange); 721525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 722525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 723525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageRange[] pageInDocument = new PageRange[pagesInDocumentList.size()]; 724525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov pagesInDocumentList.toArray(pageInDocument); 725525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 726525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (DEBUG) { 727525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov Log.i(LOG_TAG, "Bound pages: " + Arrays.toString(pageInDocument)); 728525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 729525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 730525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov return pageInDocument; 731525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 732525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 733525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private void recyclePageView(PageContentView page, int pageIndexInAdapter) { 734525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov PageContentProvider provider = page.getPageContentProvider(); 735525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (provider != null) { 7360d2d9637ed4f46062d508cfa7da0e9776fc444f8Svetoslav page.init(null, mEmptyState, mMediaSize, mMinMargins); 737525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mPageContentRepository.releasePageContentProvider(provider); 738525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 739f3f963b0bebea91b17f7e60d9b826c458bfde38cSvetoslav mBoundPagesInAdapter.remove(pageIndexInAdapter); 740525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov page.setTag(null); 741525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 742525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 743525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public void startPreloadContent(PageRange pageRangeInAdapter) { 7441710e0318db5db833974e390eb4bde54ab2f3c62Svetoslav final int startPageInDocument = computePageIndexInDocument(pageRangeInAdapter.getStart()); 7451710e0318db5db833974e390eb4bde54ab2f3c62Svetoslav final int startPageInFile = computePageIndexInFile(startPageInDocument); 7461710e0318db5db833974e390eb4bde54ab2f3c62Svetoslav final int endPageInDocument = computePageIndexInDocument(pageRangeInAdapter.getEnd()); 7471710e0318db5db833974e390eb4bde54ab2f3c62Svetoslav final int endPageInFile = computePageIndexInFile(endPageInDocument); 7481710e0318db5db833974e390eb4bde54ab2f3c62Svetoslav if (startPageInDocument != INVALID_PAGE_INDEX && endPageInDocument != INVALID_PAGE_INDEX) { 7491710e0318db5db833974e390eb4bde54ab2f3c62Svetoslav mPageContentRepository.startPreload(startPageInFile, endPageInFile); 7501710e0318db5db833974e390eb4bde54ab2f3c62Svetoslav } 751525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 752525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 753525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public void stopPreloadContent() { 7541710e0318db5db833974e390eb4bde54ab2f3c62Svetoslav mPageContentRepository.stopPreload(); 755525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 756525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 757525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private void throwIfNotOpened() { 758525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (mState != STATE_OPENED) { 759525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov throw new IllegalStateException("Not opened"); 760525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 761525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 762525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 763525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private void throwIfNotClosed() { 764525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (mState != STATE_CLOSED) { 765525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov throw new IllegalStateException("Not closed"); 766525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 767525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 768525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 769525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private final class MyViewHolder extends ViewHolder { 770525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov int mPageInAdapter; 771525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 772525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private MyViewHolder(View itemView) { 773525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov super(itemView); 774525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 775525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 776525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 777525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private final class PageClickListener implements OnClickListener { 778525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov @Override 779e652b02d45bbda11c9cb8f663fa7f25903b90225Svetoslav public void onClick(View view) { 780e652b02d45bbda11c9cb8f663fa7f25903b90225Svetoslav PreviewPageFrame page = (PreviewPageFrame) view; 781525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov MyViewHolder holder = (MyViewHolder) page.getTag(); 782525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int pageInAdapter = holder.mPageInAdapter; 783525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov final int pageInDocument = computePageIndexInDocument(pageInAdapter); 784525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (mConfirmedPagesInDocument.indexOfKey(pageInDocument) < 0) { 785525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mConfirmedPagesInDocument.put(pageInDocument, null); 786e652b02d45bbda11c9cb8f663fa7f25903b90225Svetoslav page.setSelected(true, true); 787525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } else { 788c404cacd3a480776dd625fb300810ffccc5f51b0Svetoslav if (mConfirmedPagesInDocument.size() <= 1) { 789c404cacd3a480776dd625fb300810ffccc5f51b0Svetoslav return; 790c404cacd3a480776dd625fb300810ffccc5f51b0Svetoslav } 791525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mConfirmedPagesInDocument.remove(pageInDocument); 792e652b02d45bbda11c9cb8f663fa7f25903b90225Svetoslav page.setSelected(false, true); 793525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 794525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 795525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 796525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov} 797