am 3b42928c: Merge "Print spooler UI polish and bug fixes." into lmp-dev

* commit '3b42928c318d2732d75bb9c0ed7b864c47a265a2':
  Print spooler UI polish and bug fixes.
This commit is contained in:
Svetoslav
2014-09-05 22:45:40 +00:00
committed by Android Git Automerger
9 changed files with 108 additions and 49 deletions

View File

@@ -535,7 +535,7 @@ public final class PrintManager {
destroyed = isDestroyedLocked();
}
if (destroyed) {
if (destroyed && observer != null) {
try {
observer.onDestroy();
} catch (RemoteException re) {

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="36dip"
android:layout_gravity="center"
android:src="@drawable/ic_grayedout_printer"
android:contentDescription="@null"
android:scaleType="centerInside"
android:adjustViewBounds="true">
</ImageView>
</FrameLayout>

View File

@@ -16,7 +16,7 @@
<resources>
<integer name="preview_page_per_row_count">2</integer>
<integer name="preview_page_per_row_count">4</integer>
<integer name="print_option_column_count">3</integer>

View File

@@ -76,7 +76,6 @@
<!-- Title for the print dialog announced to the user for accessibility. Not shown in the UI. [CHAR LIMIT=none] -->
<string name="print_dialog">Print dialog</string>
<!-- Template for the message that shows the current page out of the total number of pages -->
<string name="current_page_template"><xliff:g id="current_page">%1$d</xliff:g>
/<xliff:g id="page_count">%2$d</xliff:g></string>

View File

@@ -317,6 +317,11 @@ public final class RemotePrintDocument {
return mState == STATE_FAILED;
}
public boolean hasLaidOutPages() {
return mDocumentInfo.info != null
&& mDocumentInfo.info.getPageCount() > 0;
}
public void clearUpdateError() {
if (!hasUpdateError()) {
throw new IllegalStateException("No update error to clear");

View File

@@ -17,6 +17,9 @@
package com.android.printspooler.ui;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.os.ParcelFileDescriptor;
import android.print.PageRange;
import android.print.PrintAttributes.MediaSize;
@@ -26,12 +29,12 @@ import android.support.v7.widget.RecyclerView.Adapter;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.util.Log;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.View.MeasureSpec;
import android.widget.TextView;
import com.android.printspooler.R;
import com.android.printspooler.model.PageContentRepository;
@@ -48,7 +51,7 @@ import java.util.List;
* This class represents the adapter for the pages in the print preview list.
*/
public final class PageAdapter extends Adapter implements
PageContentRepository.OnMalformedPdfFileListener{
PageContentRepository.OnMalformedPdfFileListener {
private static final String LOG_TAG = "PageAdapter";
private static final int MAX_PREVIEW_PAGES_BATCH = 50;
@@ -86,6 +89,8 @@ public final class PageAdapter extends Adapter implements
// Pages the user selected in the UI.
private PageRange[] mSelectedPages;
private BitmapDrawable mEmptyState;
private int mDocumentPageCount = PrintDocumentInfo.PAGE_COUNT_UNKNOWN;
private int mSelectedPageCount;
@@ -257,7 +262,7 @@ public final class PageAdapter extends Adapter implements
}
if (updatePreviewAreaAndPageSize) {
updatePreviewAreaAndPageSize();
updatePreviewAreaPageSizeAndEmptyState();
}
if (documentChanged) {
@@ -318,12 +323,12 @@ public final class PageAdapter extends Adapter implements
}
// OK, there are bugs in recycler view which tries to bind views
// without recycling them which would give us a chane to clean up.
// without recycling them which would give us a chance to clean up.
PageContentProvider boundProvider = mPageContentRepository
.peekPageContentProvider(pageIndexInFile);
.peekPageContentProvider(pageIndexInFile);
if (boundProvider != null) {
PageContentView owner = (PageContentView) boundProvider.getOwner();
owner.init(null, mMediaSize, mMinMargins);
owner.init(null, mEmptyState, mMediaSize, mMinMargins);
mPageContentRepository.releasePageContentProvider(boundProvider);
}
@@ -333,7 +338,7 @@ public final class PageAdapter extends Adapter implements
} else {
onSelectedPageNotInFile(pageInDocument);
}
content.init(provider, mMediaSize, mMinMargins);
content.init(provider, mEmptyState, mMediaSize, mMinMargins);
View pageSelector = page.findViewById(R.id.page_selector);
pageSelector.setTag(myHolder);
@@ -384,7 +389,7 @@ public final class PageAdapter extends Adapter implements
mSelectedPages = selectedPages;
mSelectedPageCount = PageRangeUtils.getNormalizedPageCount(
mSelectedPages, mDocumentPageCount);
updatePreviewAreaAndPageSize();
updatePreviewAreaPageSizeAndEmptyState();
notifyDataSetChanged();
}
return mSelectedPages;
@@ -392,12 +397,12 @@ public final class PageAdapter extends Adapter implements
public void onPreviewAreaSizeChanged() {
if (mMediaSize != null) {
updatePreviewAreaAndPageSize();
updatePreviewAreaPageSizeAndEmptyState();
notifyDataSetChanged();
}
}
private void updatePreviewAreaAndPageSize() {
private void updatePreviewAreaPageSizeAndEmptyState() {
final int availableWidth = mPreviewArea.getWidth();
final int availableHeight = mPreviewArea.getHeight();
@@ -419,7 +424,7 @@ public final class PageAdapter extends Adapter implements
final int pageContentDesiredHeight = (int) (((float) pageContentDesiredWidth
/ pageAspectRatio) + 0.5f);
// If the page does not fit entirely in a vertial direction,
// If the page does not fit entirely in a vertical direction,
// we shirk it but not less than the minimal page width.
final int pageContentMinHeight = (int) (mPreviewPageMinWidth / pageAspectRatio + 0.5f);
final int pageContentMaxHeight = Math.max(pageContentMinHeight,
@@ -448,6 +453,23 @@ public final class PageAdapter extends Adapter implements
mPreviewArea.setPadding(horizontalPadding, verticalPadding,
horizontalPadding, verticalPadding);
// Now update the empty state drawable, as it depends on the page
// size and is reused for all views for better performance.
LayoutInflater inflater = LayoutInflater.from(mContext);
View content = inflater.inflate(R.layout.preview_page_loading, null, false);
content.measure(MeasureSpec.makeMeasureSpec(mPageContentWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mPageContentHeight, MeasureSpec.EXACTLY));
content.layout(0, 0, content.getMeasuredWidth(), content.getMeasuredHeight());
Bitmap bitmap = Bitmap.createBitmap(mPageContentWidth, mPageContentHeight,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
content.draw(canvas);
// Do not recycle the old bitmap if such as it may be set as an empty
// state to any of the page views. Just let the GC take care of it.
mEmptyState = new BitmapDrawable(mContext.getResources(), bitmap);
}
private PageRange[] computeSelectedPages() {
@@ -718,7 +740,7 @@ public final class PageAdapter extends Adapter implements
private void recyclePageView(PageContentView page, int pageIndexInAdapter) {
PageContentProvider provider = page.getPageContentProvider();
if (provider != null) {
page.init(null, null, null);
page.init(null, null, null, null);
mPageContentRepository.releasePageContentProvider(provider);
mBoundPagesInAdapter.remove(pageIndexInAdapter);
}

View File

@@ -114,14 +114,15 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
private static final int DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF = Integer.MAX_VALUE;
private static final int DEST_ADAPTER_ITEM_ID_ALL_PRINTERS = Integer.MAX_VALUE - 1;
private static final int STATE_CONFIGURING = 0;
private static final int STATE_PRINT_CONFIRMED = 1;
private static final int STATE_PRINT_CANCELED = 2;
private static final int STATE_UPDATE_FAILED = 3;
private static final int STATE_CREATE_FILE_FAILED = 4;
private static final int STATE_PRINTER_UNAVAILABLE = 5;
private static final int STATE_UPDATE_SLOW = 6;
private static final int STATE_PRINT_COMPLETED = 7;
private static final int STATE_INITIALIZING = 0;
private static final int STATE_CONFIGURING = 1;
private static final int STATE_PRINT_CONFIRMED = 2;
private static final int STATE_PRINT_CANCELED = 3;
private static final int STATE_UPDATE_FAILED = 4;
private static final int STATE_CREATE_FILE_FAILED = 5;
private static final int STATE_PRINTER_UNAVAILABLE = 6;
private static final int STATE_UPDATE_SLOW = 7;
private static final int STATE_PRINT_COMPLETED = 8;
private static final int UI_STATE_PREVIEW = 0;
private static final int UI_STATE_ERROR = 1;
@@ -196,7 +197,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
private int mCurrentPageCount;
private int mState;
private int mState = STATE_INITIALIZING;
private int mUiState = UI_STATE_PREVIEW;
@@ -290,10 +291,17 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
mPrintedDocument.start();
ensurePreviewUiShown();
setState(STATE_CONFIGURING);
}
@Override
public void onPause() {
if (mState == STATE_INITIALIZING) {
super.onPause();
return;
}
if (isFinishing()) {
PrintSpoolerService spooler = mSpoolerProvider.getSpooler();
spooler.updatePrintJobUserConfigurableOptionsNoPersistence(mPrintJob);
@@ -341,9 +349,13 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (mState == STATE_INITIALIZING) {
return super.onKeyUp(keyCode, event);
}
if (keyCode == KeyEvent.KEYCODE_BACK
&& event.isTracking() && !event.isCanceled()) {
if (mPrintPreviewController != null&&mPrintPreviewController.isOptionsOpened()
if (mPrintPreviewController != null && mPrintPreviewController.isOptionsOpened()
&& !hasErrors()) {
mPrintPreviewController.closeOptions();
} else {
@@ -900,7 +912,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
final boolean willUpdate = mPrintedDocument.update(mPrintJob.getAttributes(),
pages, preview);
if (willUpdate) {
if (willUpdate && !mPrintedDocument.hasLaidOutPages()) {
// When the update is done we update the print preview.
mProgressMessageController.post();
return true;

View File

@@ -195,6 +195,7 @@ class PrintPreviewController implements MutexFileProvider.OnReleaseRequestCallba
if (mPageAdapter.isOpened()) {
mPageAdapter.close(null);
}
mRecyclerView.setAdapter(null);
mPageAdapter.destroy();
}

View File

@@ -17,17 +17,15 @@
package com.android.printspooler.widget;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.print.PrintAttributes.MediaSize;
import android.print.PrintAttributes.Margins;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import com.android.printspooler.model.PageContentRepository;
import com.android.printspooler.model.PageContentRepository.PageContentProvider;
import com.android.printspooler.model.PageContentRepository.RenderSpec;
import com.android.printspooler.model.PageContentRepository.PageContentProvider;
/**
* This class represents a page in the print preview list. The width of the page
@@ -37,35 +35,20 @@ import com.android.printspooler.model.PageContentRepository.RenderSpec;
*/
public class PageContentView extends View
implements PageContentRepository.OnPageContentAvailableCallback {
private final ColorDrawable mEmptyState;
private PageContentProvider mProvider;
private MediaSize mMediaSize;
private Margins mMinMargins;
private Drawable mEmptyState;
private boolean mContentRequested;
private boolean mNeedsLayout;
public PageContentView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedValue typedValue = new TypedValue();
context.getTheme().resolveAttribute(com.android.internal.R.attr.textColorPrimary,
typedValue, true);
mEmptyState = new ColorDrawable(typedValue.data);
setBackground(mEmptyState);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
requestPageContentIfNeeded();
}
@Override
@@ -85,15 +68,19 @@ public class PageContentView extends View
return mProvider;
}
public void init(PageContentProvider provider, MediaSize mediaSize, Margins minMargins) {
public void init(PageContentProvider provider, Drawable emptyState,
MediaSize mediaSize, Margins minMargins) {
final boolean providerChanged = (mProvider == null)
? provider != null : !mProvider.equals(provider);
final boolean loadingDrawableChanged = (mEmptyState == null)
? mEmptyState != null : !mEmptyState.equals(emptyState);
final boolean mediaSizeChanged = (mMediaSize == null)
? mediaSize != null : !mMediaSize.equals(mediaSize);
final boolean marginsChanged = (mMinMargins == null)
? minMargins != null : !mMinMargins.equals(minMargins);
if (!providerChanged && !mediaSizeChanged && !marginsChanged) {
if (!providerChanged && !mediaSizeChanged
&& !marginsChanged && !loadingDrawableChanged) {
return;
}
@@ -101,6 +88,7 @@ public class PageContentView extends View
mMediaSize = mediaSize;
mMinMargins = minMargins;
mEmptyState = emptyState;
mContentRequested = false;
mNeedsLayout = mNeedsLayout || mediaSizeChanged || marginsChanged;